diff options
Diffstat (limited to 'lib/libproc')
-rw-r--r-- | lib/libproc/Makefile | 2 | ||||
-rw-r--r-- | lib/libproc/_libproc.h | 2 | ||||
-rw-r--r-- | lib/libproc/libproc.h | 1 | ||||
-rw-r--r-- | lib/libproc/proc_bkpt.c | 29 | ||||
-rw-r--r-- | lib/libproc/proc_create.c | 52 | ||||
-rw-r--r-- | lib/libproc/proc_rtld.c | 3 | ||||
-rw-r--r-- | lib/libproc/proc_sym.c | 25 | ||||
-rw-r--r-- | lib/libproc/proc_util.c | 24 |
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) { |