svn commit: r303533 - in head: lib/libproc share/mk

Mark Johnston markj at FreeBSD.org
Sat Jul 30 03:09:25 UTC 2016


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


More information about the svn-src-all mailing list