diff options
Diffstat (limited to 'lib/libproc')
-rw-r--r-- | lib/libproc/Makefile | 2 | ||||
-rw-r--r-- | lib/libproc/_libproc.h | 21 | ||||
-rw-r--r-- | lib/libproc/libproc.h | 4 | ||||
-rw-r--r-- | lib/libproc/proc_create.c | 127 | ||||
-rw-r--r-- | lib/libproc/proc_rtld.c | 2 | ||||
-rw-r--r-- | lib/libproc/proc_util.c | 10 |
6 files changed, 114 insertions, 52 deletions
diff --git a/lib/libproc/Makefile b/lib/libproc/Makefile index 0372377d8b64..9744557e680d 100644 --- a/lib/libproc/Makefile +++ b/lib/libproc/Makefile @@ -24,7 +24,7 @@ LIBADD+= cxxrt LIBADD+= supcplusplus .endif -LIBADD+= elf rtld_db util +LIBADD+= elf procstat rtld_db util .if ${MK_CDDL} != "no" LIBADD+= ctf diff --git a/lib/libproc/_libproc.h b/lib/libproc/_libproc.h index ffc89cfdad83..29951932a151 100644 --- a/lib/libproc/_libproc.h +++ b/lib/libproc/_libproc.h @@ -26,28 +26,29 @@ * $FreeBSD$ */ -#include <sys/cdefs.h> -#include <sys/param.h> #include <sys/types.h> -#include <sys/event.h> #include <sys/ptrace.h> + #include <rtld_db.h> #include "libproc.h" +struct procstat; + struct proc_handle { pid_t pid; /* Process ID. */ - int kq; /* Kernel event queue ID. */ int flags; /* Process flags. */ int status; /* Process status (PS_*). */ int wstat; /* Process wait status. */ + int model; /* Process data model. */ rd_agent_t *rdap; /* librtld_db agent */ - rd_loadobj_t *rdobjs; - size_t rdobjsz; - size_t nobjs; - struct lwpstatus lwps; - rd_loadobj_t *rdexec; /* rdobj index of program executable. */ - char execname[MAXPATHLEN]; /* Path to program executable. */ + rd_loadobj_t *rdobjs; /* Array of loaded objects. */ + size_t rdobjsz; /* Array size. */ + size_t nobjs; /* Num. objects currently loaded. */ + rd_loadobj_t *rdexec; /* rdobj for program executable. */ + struct lwpstatus lwps; /* Process status. */ + struct procstat *procstat; /* libprocstat handle. */ + char execpath[MAXPATHLEN]; /* Path to program executable. */ }; #ifdef DEBUG diff --git a/lib/libproc/libproc.h b/lib/libproc/libproc.h index 5d81c2bf4505..5445d47abef6 100644 --- a/lib/libproc/libproc.h +++ b/lib/libproc/libproc.h @@ -113,6 +113,9 @@ typedef struct lwpstatus { #define FLTBPT -1 } lwpstatus_t; +#define PR_MODEL_ILP32 1 +#define PR_MODEL_LP64 2 + /* Function prototype definitions. */ __BEGIN_DECLS @@ -136,6 +139,7 @@ int proc_name2sym(struct proc_handle *, const char *, const char *, struct ctf_file *proc_name2ctf(struct proc_handle *, const char *); int proc_setflags(struct proc_handle *, int); int proc_state(struct proc_handle *); +int proc_getmodel(struct proc_handle *); pid_t proc_getpid(struct proc_handle *); int proc_wstatus(struct proc_handle *); int proc_getwstat(struct proc_handle *); diff --git a/lib/libproc/proc_create.c b/lib/libproc/proc_create.c index 4a925809badf..477fa6fd3003 100644 --- a/lib/libproc/proc_create.c +++ b/lib/libproc/proc_create.c @@ -28,6 +28,7 @@ #include <sys/types.h> #include <sys/sysctl.h> +#include <sys/user.h> #include <sys/wait.h> #include <err.h> @@ -38,57 +39,103 @@ #include <string.h> #include <unistd.h> +#include <libelf.h> +#include <libprocstat.h> + #include "_libproc.h" -static int proc_init(pid_t, int, int, struct proc_handle *); +static int getelfclass(int); +static int proc_init(pid_t, int, int, struct proc_handle **); + +static int +getelfclass(int fd) +{ + GElf_Ehdr ehdr; + Elf *e; + int class; + + class = ELFCLASSNONE; + + if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) + goto out; + if (gelf_getehdr(e, &ehdr) == NULL) + goto out; + class = ehdr.e_ident[EI_CLASS]; +out: + (void)elf_end(e); + return (class); +} static int -proc_init(pid_t pid, int flags, int status, struct proc_handle *phdl) +proc_init(pid_t pid, int flags, int status, struct proc_handle **pphdl) { - int mib[4], error; - size_t len; + struct kinfo_proc *kp; + struct proc_handle *phdl; + int error, class, count, fd; + + error = ENOMEM; + if ((phdl = malloc(sizeof(*phdl))) == NULL) + goto out; memset(phdl, 0, sizeof(*phdl)); phdl->pid = pid; phdl->flags = flags; phdl->status = status; + phdl->procstat = procstat_open_sysctl(); + if (phdl->procstat == NULL) + goto out; + + /* Obtain a path to the executable. */ + if ((kp = procstat_getprocs(phdl->procstat, KERN_PROC_PID, pid, + &count)) == NULL) + goto out; + error = procstat_getpathname(phdl->procstat, kp, phdl->execpath, + sizeof(phdl->execpath)); + procstat_freeprocs(phdl->procstat, kp); + if (error != 0) + goto out; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = pid; - len = sizeof(phdl->execname); - if (sysctl(mib, 4, phdl->execname, &len, NULL, 0) != 0) { + /* Use it to determine the data model for the process. */ + if ((fd = open(phdl->execpath, O_RDONLY)) < 0) { error = errno; - DPRINTF("ERROR: cannot get pathname for child process %d", pid); - return (error); + goto out; + } + class = getelfclass(fd); + switch (class) { + case ELFCLASS64: + phdl->model = PR_MODEL_LP64; + break; + case ELFCLASS32: + phdl->model = PR_MODEL_ILP32; + break; + case ELFCLASSNONE: + default: + error = EINVAL; + break; } - if (len == 0) - phdl->execname[0] = '\0'; + (void)close(fd); - return (0); +out: + *pphdl = phdl; + return (error); } int proc_attach(pid_t pid, int flags, struct proc_handle **pphdl) { struct proc_handle *phdl; - int error = 0; - int status; + int error, status; if (pid == 0 || pid == getpid()) return (EINVAL); + if (elf_version(EV_CURRENT) == EV_NONE) + return (ENOENT); /* * Allocate memory for the process handle, a structure containing * all things related to the process. */ - if ((phdl = malloc(sizeof(struct proc_handle))) == NULL) - return (ENOMEM); - - elf_version(EV_CURRENT); - - error = proc_init(pid, flags, PS_RUN, phdl); + error = proc_init(pid, flags, PS_RUN, &phdl); if (error != 0) goto out; @@ -106,16 +153,17 @@ proc_attach(pid_t pid, int flags, struct proc_handle **pphdl) } /* Check for an unexpected status. */ - if (WIFSTOPPED(status) == 0) + if (!WIFSTOPPED(status)) DPRINTFX("ERROR: child process %d status 0x%x", pid, status); else phdl->status = PS_STOP; out: - if (error) + if (error && phdl != NULL) { proc_free(phdl); - else - *pphdl = phdl; + phdl = NULL; + } + *pphdl = phdl; return (error); } @@ -128,14 +176,8 @@ proc_create(const char *file, char * const *argv, proc_child_func *pcf, int status; pid_t pid; - /* - * Allocate memory for the process handle, a structure containing - * all things related to the process. - */ - if ((phdl = malloc(sizeof(struct proc_handle))) == NULL) - return (ENOMEM); - - elf_version(EV_CURRENT); + if (elf_version(EV_CURRENT) == EV_NONE) + return (ENOENT); /* Fork a new process. */ if ((pid = vfork()) == -1) @@ -153,9 +195,10 @@ proc_create(const char *file, char * const *argv, proc_child_func *pcf, /* Couldn't execute the file. */ _exit(2); + /* NOTREACHED */ } else { /* The parent owns the process handle. */ - error = proc_init(pid, 0, PS_IDLE, phdl); + error = proc_init(pid, 0, PS_IDLE, &phdl); if (error != 0) goto bad; @@ -167,7 +210,7 @@ proc_create(const char *file, char * const *argv, proc_child_func *pcf, } /* Check for an unexpected status. */ - if (WIFSTOPPED(status) == 0) { + if (!WIFSTOPPED(status)) { error = errno; DPRINTFX("ERROR: child process %d status 0x%x", pid, status); goto bad; @@ -175,15 +218,19 @@ proc_create(const char *file, char * const *argv, proc_child_func *pcf, phdl->status = PS_STOP; } bad: - if (error) + if (error && phdl != NULL) { proc_free(phdl); - else - *pphdl = phdl; + phdl = NULL; + } + *pphdl = phdl; return (error); } void proc_free(struct proc_handle *phdl) { + + if (phdl->procstat != NULL) + procstat_close(phdl->procstat); free(phdl); } diff --git a/lib/libproc/proc_rtld.c b/lib/libproc/proc_rtld.c index 8dff3b726615..6c34a8a21bb3 100644 --- a/lib/libproc/proc_rtld.c +++ b/lib/libproc/proc_rtld.c @@ -49,7 +49,7 @@ map_iter(const rd_loadobj_t *lop, void *arg) if (phdl->rdobjs == NULL) return (-1); } - if (strcmp(lop->rdl_path, phdl->execname) == 0 && + if (strcmp(lop->rdl_path, phdl->execpath) == 0 && (lop->rdl_prot & RD_RDL_X) != 0) phdl->rdexec = &phdl->rdobjs[phdl->nobjs]; memcpy(&phdl->rdobjs[phdl->nobjs++], lop, sizeof(*lop)); diff --git a/lib/libproc/proc_util.c b/lib/libproc/proc_util.c index 4d9aa20b3de6..1e14c4fd3837 100644 --- a/lib/libproc/proc_util.c +++ b/lib/libproc/proc_util.c @@ -140,6 +140,16 @@ proc_getpid(struct proc_handle *phdl) } int +proc_getmodel(struct proc_handle *phdl) +{ + + if (phdl == NULL) + return (-1); + + return (phdl->model); +} + +int proc_wstatus(struct proc_handle *phdl) { int status; |