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 <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;
+
+       *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
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to