aboutsummaryrefslogtreecommitdiff
path: root/lib/libproc
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2016-07-30 03:09:23 +0000
committerMark Johnston <markj@FreeBSD.org>2016-07-30 03:09:23 +0000
commit4808a67805fe7287d8054934d978cd1076302689 (patch)
treef04ff2fa3ed04fc3c8cc0e96637bb6210b3c7f21 /lib/libproc
parent700244a246427d903ba6a6135b9c2bd920a24d03 (diff)
downloadsrc-4808a67805fe7287d8054934d978cd1076302689.tar.gz
src-4808a67805fe7287d8054934d978cd1076302689.zip
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
Notes
Notes: svn path=/head/; revision=303533
Diffstat (limited to 'lib/libproc')
-rw-r--r--lib/libproc/Makefile2
-rw-r--r--lib/libproc/_libproc.h6
-rw-r--r--lib/libproc/libproc.h4
-rw-r--r--lib/libproc/proc_create.c127
-rw-r--r--lib/libproc/proc_rtld.c2
-rw-r--r--lib/libproc/proc_util.c10
6 files changed, 108 insertions, 43 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 0ab3251e55b8..29951932a151 100644
--- a/lib/libproc/_libproc.h
+++ b/lib/libproc/_libproc.h
@@ -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
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..ad975b4c9979 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;
+
+ *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 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;