From owner-svn-src-all@freebsd.org Sat Jul 30 03:09:24 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E771EBA75F8; Sat, 30 Jul 2016 03:09:24 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C167B12E3; Sat, 30 Jul 2016 03:09:24 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u6U39OYQ006119; Sat, 30 Jul 2016 03:09:24 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u6U39NOJ006112; Sat, 30 Jul 2016 03:09:23 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201607300309.u6U39NOJ006112@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Sat, 30 Jul 2016 03:09:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r303533 - in head: lib/libproc share/mk X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 Jul 2016 03:09:25 -0000 Author: markj Date: Sat Jul 30 03:09:23 2016 New Revision: 303533 URL: https://svnweb.freebsd.org/changeset/base/303533 Log: libproc: Add proc_getmodel(). This is used by libdtrace to determine the data model of target processes. This allows for the creation of pid provider probes in 32-bit processes on amd64. MFC after: 1 month Modified: head/lib/libproc/Makefile head/lib/libproc/_libproc.h head/lib/libproc/libproc.h head/lib/libproc/proc_create.c head/lib/libproc/proc_rtld.c head/lib/libproc/proc_util.c head/share/mk/src.libnames.mk Modified: head/lib/libproc/Makefile ============================================================================== --- head/lib/libproc/Makefile Sat Jul 30 03:07:14 2016 (r303532) +++ head/lib/libproc/Makefile Sat Jul 30 03:09:23 2016 (r303533) @@ -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 Modified: head/lib/libproc/_libproc.h ============================================================================== --- head/lib/libproc/_libproc.h Sat Jul 30 03:07:14 2016 (r303532) +++ head/lib/libproc/_libproc.h Sat Jul 30 03:09:23 2016 (r303533) @@ -33,18 +33,22 @@ #include "libproc.h" +struct procstat; + struct proc_handle { pid_t pid; /* Process 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; /* 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. */ - char execname[MAXPATHLEN]; /* Path to program executable. */ + struct procstat *procstat; /* libprocstat handle. */ + char execpath[MAXPATHLEN]; /* Path to program executable. */ }; #ifdef DEBUG Modified: head/lib/libproc/libproc.h ============================================================================== --- head/lib/libproc/libproc.h Sat Jul 30 03:07:14 2016 (r303532) +++ head/lib/libproc/libproc.h Sat Jul 30 03:09:23 2016 (r303533) @@ -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 *, 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 *); Modified: head/lib/libproc/proc_create.c ============================================================================== --- head/lib/libproc/proc_create.c Sat Jul 30 03:07:14 2016 (r303532) +++ head/lib/libproc/proc_create.c Sat Jul 30 03:09:23 2016 (r303533) @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -38,57 +39,103 @@ #include #include +#include +#include + #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; + + *pphdl = NULL; + if ((phdl = malloc(sizeof(*phdl))) == NULL) + return (ENOMEM); memset(phdl, 0, sizeof(*phdl)); phdl->pid = pid; phdl->flags = flags; phdl->status = status; + phdl->procstat = procstat_open_sysctl(); + if (phdl->procstat == NULL) + return (ENOMEM); - 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) { - error = errno; - DPRINTF("ERROR: cannot get pathname for child process %d", pid); + /* Obtain a path to the executable. */ + if ((kp = procstat_getprocs(phdl->procstat, KERN_PROC_PID, pid, + &count)) == NULL) + return (ENOMEM); + error = procstat_getpathname(phdl->procstat, kp, phdl->execpath, + sizeof(phdl->execpath)); + procstat_freeprocs(phdl->procstat, kp); + if (error != 0) return (error); + + /* Use it to determine the data model for the process. */ + if ((fd = open(phdl->execpath, O_RDONLY)) < 0) { + error = errno; + goto out; } - if (len == 0) - phdl->execname[0] = '\0'; + 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; + } + (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 } /* 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 * con 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 * con /* 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 * con } /* 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 * con 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); } Modified: head/lib/libproc/proc_rtld.c ============================================================================== --- head/lib/libproc/proc_rtld.c Sat Jul 30 03:07:14 2016 (r303532) +++ head/lib/libproc/proc_rtld.c Sat Jul 30 03:09:23 2016 (r303533) @@ -49,7 +49,7 @@ map_iter(const rd_loadobj_t *lop, void * 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)); Modified: head/lib/libproc/proc_util.c ============================================================================== --- head/lib/libproc/proc_util.c Sat Jul 30 03:07:14 2016 (r303532) +++ head/lib/libproc/proc_util.c Sat Jul 30 03:09:23 2016 (r303533) @@ -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; Modified: head/share/mk/src.libnames.mk ============================================================================== --- head/share/mk/src.libnames.mk Sat Jul 30 03:07:14 2016 (r303532) +++ head/share/mk/src.libnames.mk Sat Jul 30 03:09:23 2016 (r303533) @@ -255,7 +255,7 @@ _DP_proc= supcplusplus .if ${MK_CDDL} != "no" _DP_proc+= ctf .endif -_DP_proc+= elf rtld_db util +_DP_proc+= elf procstat rtld_db util _DP_mp= crypto _DP_memstat= kvm _DP_magic= z