From 59e2aa1159caf3b16981b104c5a49f61c553e72c Mon Sep 17 00:00:00 2001 From: Hiten Pandya Date: Thu, 3 Jun 2004 16:28:15 +0000 Subject: [PATCH] VM Resident Executables update: Kernel Part: * decrement the exec_res_id counter in exec_sys_unregister, otherwise we will have an incorrect count of currently resident executables. * add a structure called 'xresident' which stores enough information about resident executables, so that we can export it to userland via sysctl; the structure resides in sys/resident.h. * add a sysctl node, called 'vm.resident' which enumerates though exec_res_list, i.e., the queue which stores information about the executables that are currently resident * move the exec_res_list queue initialization and a MALLOC_DEFINE near the top of the file, right after the include files; and also initialize the exec_res_id counter to '0'. NOTE! The 'vm.resident' sysctl node is only available to root! Userland Part: * add a '-l' option to resident(8), so that it displays the list of executables that are currently memory-resident. * update the program usage string so that it is in par with the functionality offered by the program. * update the manual page. Requested-by: many... Discussed-with: Matthew Dillon --- sys/kern/imgact_resident.c | 100 ++++++++++++++++++++++++++++++++--- sys/sys/resident.h | 10 +++- usr.sbin/resident/resident.8 | 7 ++- usr.sbin/resident/resident.c | 65 +++++++++++++++++++++-- 4 files changed, 169 insertions(+), 13 deletions(-) diff --git a/sys/kern/imgact_resident.c b/sys/kern/imgact_resident.c index 9bc8808de1..dafd14f25b 100644 --- a/sys/kern/imgact_resident.c +++ b/sys/kern/imgact_resident.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/imgact_resident.c,v 1.2 2004/01/20 21:03:23 dillon Exp $ + * $DragonFly: src/sys/kern/imgact_resident.c,v 1.3 2004/06/03 16:28:15 hmp Exp $ */ #include @@ -38,17 +38,107 @@ #include #include #include +#include #include #include +#include +#include +#include #include #include -#include #include #include #include #include +static int exec_res_id = 0; +static TAILQ_HEAD(,vmresident) exec_res_list = TAILQ_HEAD_INITIALIZER(exec_res_list); + +static MALLOC_DEFINE(M_EXEC_RES, "vmresident", "resident execs"); + +static int +fill_xresident(struct vmresident *vr, struct xresident *in, struct thread *td) +{ + struct stat st; + struct vnode *vrtmp; + int error = 0; + + vrtmp = vr->vr_vnode; + + in->res_entry_addr = vr->vr_entry_addr; + in->res_id = vr->vr_id; + if (vrtmp) { + char *freepath, *fullpath; + error = vn_fullpath(td->td_proc, vrtmp, &fullpath, &freepath); + if (error != 0) { + /* could not retrieve cached path, return zero'ed string */ + bzero(in->res_file, MAXPATHLEN); + error = 0; + } else { + bcopy(fullpath, in->res_file, MAXPATHLEN); + free(freepath, M_TEMP); + } + + /* indicate that we are using the vnode */ + error = vget(vrtmp, NULL, LK_EXCLUSIVE, td); + if (error) + goto done; + + /* retrieve underlying stat information and release vnode */ + error = vn_stat(vrtmp, &st, td); + vput(vrtmp); + if (error) + goto done; + + in->res_stat = st; + } + +done: + if (error) + printf("fill_xresident, error = %d\n", error); + return (error); +} + +static int +sysctl_vm_resident(SYSCTL_HANDLER_ARGS) +{ + struct vmresident *vmres; + struct thread *td; + int error; + int count; + + /* only super-user should call this sysctl */ + td = req->td; + if ((suser(td)) != 0) + return EPERM; + + error = count = 0; + + if (exec_res_id == 0) + return error; + + /* client queried for number of resident binaries */ + if (!req->oldptr) + return SYSCTL_OUT(req, 0, exec_res_id); + + TAILQ_FOREACH(vmres, &exec_res_list, vr_link) { + struct xresident xres; + error = fill_xresident(vmres, &xres, td); + if (error != 0) + break; + + error = SYSCTL_OUT(req, (void *)&xres, + sizeof(struct xresident)); + if (error != 0) + break; + } + + return (error); +} +SYSCTL_PROC(_vm, OID_AUTO, resident, CTLTYPE_OPAQUE|CTLFLAG_RD, 0, 0, + sysctl_vm_resident, "S,xresident", "resident executables (sys/resident.h)"); + int exec_resident_imgact(struct image_params *imgp) { @@ -67,11 +157,6 @@ exec_resident_imgact(struct image_params *imgp) return(0); } -static int exec_res_id; -static TAILQ_HEAD(,vmresident) exec_res_list = TAILQ_HEAD_INITIALIZER(exec_res_list); - -static MALLOC_DEFINE(M_EXEC_RES, "vmresident", "resident execs"); - /* * exec_sys_register(entry) * @@ -151,6 +236,7 @@ restart: vmres->vr_vmspace = NULL; } free(vmres, M_EXEC_RES); + exec_res_id--; error = 0; ++count; goto restart; diff --git a/sys/sys/resident.h b/sys/sys/resident.h index a0a458b4ef..41fd04f464 100644 --- a/sys/sys/resident.h +++ b/sys/sys/resident.h @@ -3,7 +3,7 @@ * * Userland system calls for resident executable support. * - * $DragonFly: src/sys/sys/resident.h,v 1.2 2004/02/25 17:38:51 joerg Exp $ + * $DragonFly: src/sys/sys/resident.h,v 1.3 2004/06/03 16:28:15 hmp Exp $ */ #ifndef _SYS_RESIDENT_H_ @@ -16,5 +16,13 @@ int exec_sys_unregister(int); #endif +struct stat; +/* structure exported via sysctl 'vm.resident' for userland */ +struct xresident { + intptr_t res_entry_addr; + int res_id; + char res_file[MAXPATHLEN]; + struct stat res_stat; +}; #endif diff --git a/usr.sbin/resident/resident.8 b/usr.sbin/resident/resident.8 index b0c936d482..4400ee4667 100644 --- a/usr.sbin/resident/resident.8 +++ b/usr.sbin/resident/resident.8 @@ -1,4 +1,4 @@ -.\" $DragonFly: src/usr.sbin/resident/resident.8,v 1.2 2004/01/20 21:14:00 dillon Exp $ +.\" $DragonFly: src/usr.sbin/resident/resident.8,v 1.3 2004/06/03 16:28:15 hmp Exp $ .\" .Dd May 21, 2003 .Dt RESIDENT 8 @@ -8,11 +8,12 @@ .Nd Make a dynamic binary resident. .Sh SYNOPSIS .Nm +.Op Fl l .Op Fl f .Op Fl x Ar id .Op Fl d .Op Fl R -.Ar [program ...] +.Ar "program ..." .Sh DESCRIPTION The .Nm @@ -29,6 +30,8 @@ and binaries. .Pp The following options are available: .Bl -tag -width indent +.It Fl l +List binaries that are currently memory-resident. .It Fl f Force mode, even if the binary does not appear to be a dynamic binary. This way you can run resident through statically compiled wrappers. The first diff --git a/usr.sbin/resident/resident.c b/usr.sbin/resident/resident.c index d2c6e11b17..4c18c50293 100644 --- a/usr.sbin/resident/resident.c +++ b/usr.sbin/resident/resident.c @@ -23,14 +23,16 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/usr.sbin/resident/resident.c,v 1.4 2004/01/20 21:34:19 dillon Exp $ + * $DragonFly: src/usr.sbin/resident/resident.c,v 1.5 2004/06/03 16:28:15 hmp Exp $ */ #include #include #include +#include #include +#include #include #include @@ -46,10 +48,61 @@ static void usage(void) { - fprintf(stderr, "usage: resident [-d] program ...\n"); + fprintf(stderr, "usage: resident [-l] [-f] [-x id] [-d] [-R] program ...\n"); exit(1); } +static int +list_residents(void) +{ + const char *mib = "vm.resident"; + struct xresident *buf; + int res_count, res_total; + int error, i; + + /* get the number of resident binaries */ + error = sysctlbyname(mib, NULL, &res_count, NULL, 0); + if (error != 0) { + perror("sysctl: vm.resident"); + goto done; + } + + if (res_count == 0) { + printf("no resident binaries to list\n"); + goto done; + } + + /* allocate memory for the list of binaries */ + res_total = sizeof(*buf) * res_count; + if ((buf = malloc(res_total)) != NULL) { + /* retrieve entries via sysctl */ + error = sysctlbyname(mib, buf, &res_total, NULL, 0); + if (error != 0) { + perror("sysctl: vm.resident"); + goto done; + } + } else { + perror("malloc"); + goto done; + } + + /* print the list of retrieved resident binary */ + printf("%-4s\t%-30s\t%-15s\t%-12s\n", "Id", "Executable", "Size", "Address"); + for (i = 0; i < res_count; ++i) { + printf("%-4d\t%-30s\t%-15lld\t0x%-12x\n", + buf[i].res_id, + buf[i].res_file, + buf[i].res_stat.st_size, + buf[i].res_entry_addr); + } + + /* free back the memory */ + free(buf); + +done: + return error; +} + int main(int argc, char *argv[]) { @@ -58,11 +111,17 @@ main(int argc, char *argv[]) int doreg = 1; int force = 0; - while ((c = getopt(argc, argv, "Rdfx:")) != -1) { + while ((c = getopt(argc, argv, "Rdflx:")) != -1) { switch (c) { case 'f': force = 1; break; + case 'l': + rval = list_residents(); + if (rval < 0) + exit(EXIT_FAILURE); + else + exit(EXIT_SUCCESS); case 'd': doreg = 0; break; -- 2.41.0