summaryrefslogtreecommitdiffstats
path: root/lib/libproc
diff options
context:
space:
mode:
authorsjg <sjg@FreeBSD.org>2014-05-08 23:54:15 +0000
committersjg <sjg@FreeBSD.org>2014-05-08 23:54:15 +0000
commited3fc70bf5a8edaf648093b11acca450802244ef (patch)
tree8ce0ddd0e6f508bd20c77429c448969589170fae /lib/libproc
parentd4e443e0426fee44056ba3c1123455666d083aef (diff)
parenta2e6be0add027bf3e713c0d56ba9715b83a01144 (diff)
downloadFreeBSD-src-ed3fc70bf5a8edaf648093b11acca450802244ef.zip
FreeBSD-src-ed3fc70bf5a8edaf648093b11acca450802244ef.tar.gz
Merge from head
Diffstat (limited to 'lib/libproc')
-rw-r--r--lib/libproc/Makefile2
-rw-r--r--lib/libproc/_libproc.h2
-rw-r--r--lib/libproc/libproc.h1
-rw-r--r--lib/libproc/proc_bkpt.c29
-rw-r--r--lib/libproc/proc_create.c52
-rw-r--r--lib/libproc/proc_rtld.c3
-rw-r--r--lib/libproc/proc_sym.c25
-rw-r--r--lib/libproc/proc_util.c24
8 files changed, 94 insertions, 44 deletions
diff --git a/lib/libproc/Makefile b/lib/libproc/Makefile
index d221296..9302496 100644
--- a/lib/libproc/Makefile
+++ b/lib/libproc/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.include <bsd.own.mk>
+.include <src.opts.mk>
LIB= proc
diff --git a/lib/libproc/_libproc.h b/lib/libproc/_libproc.h
index 8099ba1..ffc89cf 100644
--- a/lib/libproc/_libproc.h
+++ b/lib/libproc/_libproc.h
@@ -46,6 +46,8 @@ struct proc_handle {
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. */
};
#ifdef DEBUG
diff --git a/lib/libproc/libproc.h b/lib/libproc/libproc.h
index d80e88c..be77e4b 100644
--- a/lib/libproc/libproc.h
+++ b/lib/libproc/libproc.h
@@ -102,6 +102,7 @@ typedef struct lwpstatus {
#define PR_FAULTED 2
#define PR_SYSENTRY 3
#define PR_SYSEXIT 4
+#define PR_SIGNALLED 5
int pr_what;
#define FLTBPT -1
} lwpstatus_t;
diff --git a/lib/libproc/proc_bkpt.c b/lib/libproc/proc_bkpt.c
index 2c2761a..fe6ed4a 100644
--- a/lib/libproc/proc_bkpt.c
+++ b/lib/libproc/proc_bkpt.c
@@ -55,13 +55,6 @@ __FBSDID("$FreeBSD$");
#error "Add support for your architecture"
#endif
-static void
-proc_cont(struct proc_handle *phdl)
-{
-
- ptrace(PT_CONTINUE, proc_getpid(phdl), (caddr_t)1, 0);
-}
-
static int
proc_stop(struct proc_handle *phdl)
{
@@ -87,7 +80,7 @@ proc_bkptset(struct proc_handle *phdl, uintptr_t address,
{
struct ptrace_io_desc piod;
unsigned long paddr, caddr;
- int ret = 0;
+ int ret = 0, stopped;
*saved = 0;
if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
@@ -98,9 +91,12 @@ proc_bkptset(struct proc_handle *phdl, uintptr_t address,
DPRINTFX("adding breakpoint at 0x%lx", address);
- if (phdl->status != PS_STOP)
+ stopped = 0;
+ if (phdl->status != PS_STOP) {
if (proc_stop(phdl) != 0)
return (-1);
+ stopped = 1;
+ }
/*
* Read the original instruction.
@@ -135,9 +131,9 @@ proc_bkptset(struct proc_handle *phdl, uintptr_t address,
}
done:
- if (phdl->status != PS_STOP)
+ if (stopped)
/* Restart the process if we had to stop it. */
- proc_cont(phdl);
+ proc_continue(phdl);
return (ret);
}
@@ -148,7 +144,7 @@ proc_bkptdel(struct proc_handle *phdl, uintptr_t address,
{
struct ptrace_io_desc piod;
unsigned long paddr, caddr;
- int ret = 0;
+ int ret = 0, stopped;
if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
phdl->status == PS_IDLE) {
@@ -158,9 +154,12 @@ proc_bkptdel(struct proc_handle *phdl, uintptr_t address,
DPRINTFX("removing breakpoint at 0x%lx", address);
- if (phdl->status != PS_STOP)
+ stopped = 0;
+ if (phdl->status != PS_STOP) {
if (proc_stop(phdl) != 0)
return (-1);
+ stopped = 1;
+ }
/*
* Overwrite the breakpoint instruction that we setup previously.
@@ -177,9 +176,9 @@ proc_bkptdel(struct proc_handle *phdl, uintptr_t address,
ret = -1;
}
- if (phdl->status != PS_STOP)
+ if (stopped)
/* Restart the process if we had to stop it. */
- proc_cont(phdl);
+ proc_continue(phdl);
return (ret);
}
diff --git a/lib/libproc/proc_create.c b/lib/libproc/proc_create.c
index d02eccf..4a92580 100644
--- a/lib/libproc/proc_create.c
+++ b/lib/libproc/proc_create.c
@@ -26,8 +26,10 @@
* $FreeBSD$
*/
-#include "_libproc.h"
-#include <stdio.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -35,7 +37,37 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <sys/wait.h>
+
+#include "_libproc.h"
+
+static int proc_init(pid_t, int, int, struct proc_handle *);
+
+static int
+proc_init(pid_t pid, int flags, int status, struct proc_handle *phdl)
+{
+ int mib[4], error;
+ size_t len;
+
+ memset(phdl, 0, sizeof(*phdl));
+ phdl->pid = pid;
+ phdl->flags = flags;
+ phdl->status = status;
+
+ 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);
+ return (error);
+ }
+ if (len == 0)
+ phdl->execname[0] = '\0';
+
+ return (0);
+}
int
proc_attach(pid_t pid, int flags, struct proc_handle **pphdl)
@@ -54,12 +86,12 @@ proc_attach(pid_t pid, int flags, struct proc_handle **pphdl)
if ((phdl = malloc(sizeof(struct proc_handle))) == NULL)
return (ENOMEM);
- memset(phdl, 0, sizeof(struct proc_handle));
- phdl->pid = pid;
- phdl->flags = flags;
- phdl->status = PS_RUN;
elf_version(EV_CURRENT);
+ error = proc_init(pid, flags, PS_RUN, phdl);
+ if (error != 0)
+ goto out;
+
if (ptrace(PT_ATTACH, phdl->pid, 0, 0) != 0) {
error = errno;
DPRINTF("ERROR: cannot ptrace child process %d", pid);
@@ -123,9 +155,9 @@ proc_create(const char *file, char * const *argv, proc_child_func *pcf,
_exit(2);
} else {
/* The parent owns the process handle. */
- memset(phdl, 0, sizeof(struct proc_handle));
- phdl->pid = pid;
- phdl->status = PS_IDLE;
+ error = proc_init(pid, 0, PS_IDLE, phdl);
+ if (error != 0)
+ goto bad;
/* Wait for the child process to stop. */
if (waitpid(pid, &status, WUNTRACED) == -1) {
diff --git a/lib/libproc/proc_rtld.c b/lib/libproc/proc_rtld.c
index 5259049..8dff3b7 100644
--- a/lib/libproc/proc_rtld.c
+++ b/lib/libproc/proc_rtld.c
@@ -49,6 +49,9 @@ map_iter(const rd_loadobj_t *lop, void *arg)
if (phdl->rdobjs == NULL)
return (-1);
}
+ if (strcmp(lop->rdl_path, phdl->execname) == 0 &&
+ (lop->rdl_prot & RD_RDL_X) != 0)
+ phdl->rdexec = &phdl->rdobjs[phdl->nobjs];
memcpy(&phdl->rdobjs[phdl->nobjs++], lop, sizeof(*lop));
return (0);
diff --git a/lib/libproc/proc_sym.c b/lib/libproc/proc_sym.c
index 2338895..3777a46 100644
--- a/lib/libproc/proc_sym.c
+++ b/lib/libproc/proc_sym.c
@@ -112,17 +112,23 @@ proc_obj2map(struct proc_handle *p, const char *objname)
rd_loadobj_t *rdl;
char path[MAXPATHLEN];
+ rdl = NULL;
for (i = 0; i < p->nobjs; i++) {
- rdl = &p->rdobjs[i];
- basename_r(rdl->rdl_path, path);
+ basename_r(p->rdobjs[i].rdl_path, path);
if (strcmp(path, objname) == 0) {
- if ((map = malloc(sizeof(*map))) == NULL)
- return (NULL);
- proc_rdl2prmap(rdl, map);
- return (map);
+ rdl = &p->rdobjs[i];
+ break;
}
}
- return (NULL);
+ if (rdl == NULL && strcmp(objname, "a.out") == 0 && p->rdexec != NULL)
+ rdl = p->rdexec;
+ else
+ return (NULL);
+
+ if ((map = malloc(sizeof(*map))) == NULL)
+ return (NULL);
+ proc_rdl2prmap(rdl, map);
+ return (map);
}
int
@@ -386,8 +392,9 @@ proc_name2map(struct proc_handle *p, const char *name)
free(kves);
return (NULL);
}
- if (name == NULL || strcmp(name, "a.out") == 0) {
- map = proc_addr2map(p, p->rdobjs[0].rdl_saddr);
+ if ((name == NULL || strcmp(name, "a.out") == 0) &&
+ p->rdexec != NULL) {
+ map = proc_addr2map(p, p->rdexec->rdl_saddr);
return (map);
}
for (i = 0; i < p->nobjs; i++) {
diff --git a/lib/libproc/proc_util.c b/lib/libproc/proc_util.c
index 1c3d522..4d9aa20 100644
--- a/lib/libproc/proc_util.c
+++ b/lib/libproc/proc_util.c
@@ -35,10 +35,9 @@
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
#include <signal.h>
#include <string.h>
+#include <unistd.h>
#include "_libproc.h"
int
@@ -59,11 +58,14 @@ proc_clearflags(struct proc_handle *phdl, int mask)
int
proc_continue(struct proc_handle *phdl)
{
+ int pending = 0;
if (phdl == NULL)
return (-1);
- if (ptrace(PT_CONTINUE, phdl->pid, (caddr_t)(uintptr_t) 1, 0) != 0)
+ if (phdl->status == PS_STOP && WSTOPSIG(phdl->wstat) != SIGTRAP)
+ pending = WSTOPSIG(phdl->wstat);
+ if (ptrace(PT_CONTINUE, phdl->pid, (caddr_t)(uintptr_t)1, pending) != 0)
return (-1);
phdl->status = PS_RUN;
@@ -208,12 +210,16 @@ proc_getlwpstatus(struct proc_handle *phdl)
return (NULL);
siginfo = &lwpinfo.pl_siginfo;
if (lwpinfo.pl_event == PL_EVENT_SIGNAL &&
- (lwpinfo.pl_flags & PL_FLAG_SI) &&
- siginfo->si_signo == SIGTRAP &&
- (siginfo->si_code == TRAP_BRKPT ||
- siginfo->si_code == TRAP_TRACE)) {
- psp->pr_why = PR_FAULTED;
- psp->pr_what = FLTBPT;
+ (lwpinfo.pl_flags & PL_FLAG_SI) != 0) {
+ if (siginfo->si_signo == SIGTRAP &&
+ (siginfo->si_code == TRAP_BRKPT ||
+ siginfo->si_code == TRAP_TRACE)) {
+ psp->pr_why = PR_FAULTED;
+ psp->pr_what = FLTBPT;
+ } else {
+ psp->pr_why = PR_SIGNALLED;
+ psp->pr_what = siginfo->si_signo;
+ }
} else if (lwpinfo.pl_flags & PL_FLAG_SCE) {
psp->pr_why = PR_SYSENTRY;
} else if (lwpinfo.pl_flags & PL_FLAG_SCX) {
OpenPOWER on IntegriCloud