aboutsummaryrefslogtreecommitdiff
path: root/lib/libproc
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2014-04-27 08:13:43 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2014-04-27 08:13:43 +0000
commit9d2ab4a62d6733c45958627ac113bdbd818d1e2a (patch)
treeb92e741b68057a24e381faa9809f32030d65574c /lib/libproc
parent1991e07af89dbccabfb71af86738da2a979b3d20 (diff)
parent8be1b6d975fae2513af1b0e5ad6923c3c2428ddd (diff)
downloadsrc-9d2ab4a62d6733c45958627ac113bdbd818d1e2a.tar.gz
src-9d2ab4a62d6733c45958627ac113bdbd818d1e2a.zip
Merge head
Notes
Notes: svn path=/projects/bmake/; revision=265006
Diffstat (limited to 'lib/libproc')
-rw-r--r--lib/libproc/Makefile2
-rw-r--r--lib/libproc/_libproc.h6
-rw-r--r--lib/libproc/proc_bkpt.c88
-rw-r--r--lib/libproc/proc_create.c6
-rw-r--r--lib/libproc/proc_regs.c4
-rw-r--r--lib/libproc/proc_sym.c58
-rw-r--r--lib/libproc/proc_util.c2
-rw-r--r--lib/libproc/test/t1-bkpt/Makefile2
-rw-r--r--lib/libproc/test/t2-name2map/Makefile2
-rw-r--r--lib/libproc/test/t3-name2sym/Makefile2
10 files changed, 117 insertions, 55 deletions
diff --git a/lib/libproc/Makefile b/lib/libproc/Makefile
index 5b1df7432f64..d2212961a033 100644
--- a/lib/libproc/Makefile
+++ b/lib/libproc/Makefile
@@ -27,6 +27,6 @@ DPADD+= ${LIBSTDCPLUSPLUS}
SHLIB_MAJOR= 2
-WITHOUT_MAN=
+MAN=
.include <bsd.lib.mk>
diff --git a/lib/libproc/_libproc.h b/lib/libproc/_libproc.h
index aee1ac1f67f8..8099ba1d9173 100644
--- a/lib/libproc/_libproc.h
+++ b/lib/libproc/_libproc.h
@@ -49,7 +49,9 @@ struct proc_handle {
};
#ifdef DEBUG
-#define DPRINTF(fmt, ...) warn(fmt, __VA_ARGS__)
+#define DPRINTF(...) warn(__VA_ARGS__)
+#define DPRINTFX(...) warnx(__VA_ARGS__)
#else
-#define DPRINTF(fmt, ...)
+#define DPRINTF(...) do { } while (0)
+#define DPRINTFX(...) do { } while (0)
#endif
diff --git a/lib/libproc/proc_bkpt.c b/lib/libproc/proc_bkpt.c
index c15e53ce38d7..2c2761acc998 100644
--- a/lib/libproc/proc_bkpt.c
+++ b/lib/libproc/proc_bkpt.c
@@ -37,8 +37,9 @@ __FBSDID("$FreeBSD$");
#include <assert.h>
#include <err.h>
-#include <stdio.h>
#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
#include "_libproc.h"
#if defined(__i386__) || defined(__amd64__)
@@ -54,12 +55,39 @@ __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)
+{
+ int status;
+
+ if (kill(proc_getpid(phdl), SIGSTOP) == -1) {
+ DPRINTF("kill %d", proc_getpid(phdl));
+ return (-1);
+ } else if (waitpid(proc_getpid(phdl), &status, WSTOPPED) == -1) {
+ DPRINTF("waitpid %d", proc_getpid(phdl));
+ return (-1);
+ } else if (!WIFSTOPPED(status)) {
+ DPRINTFX("waitpid: unexpected status 0x%x", status);
+ return (-1);
+ }
+
+ return (0);
+}
+
int
proc_bkptset(struct proc_handle *phdl, uintptr_t address,
unsigned long *saved)
{
struct ptrace_io_desc piod;
unsigned long paddr, caddr;
+ int ret = 0;
*saved = 0;
if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
@@ -68,6 +96,12 @@ proc_bkptset(struct proc_handle *phdl, uintptr_t address,
return (-1);
}
+ DPRINTFX("adding breakpoint at 0x%lx", address);
+
+ if (phdl->status != PS_STOP)
+ if (proc_stop(phdl) != 0)
+ return (-1);
+
/*
* Read the original instruction.
*/
@@ -78,9 +112,10 @@ proc_bkptset(struct proc_handle *phdl, uintptr_t address,
piod.piod_addr = &paddr;
piod.piod_len = BREAKPOINT_INSTR_SZ;
if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) {
- DPRINTF("ERROR: couldn't read instruction at address 0x%" PRIuPTR,
- address);
- return (-1);
+ DPRINTF("ERROR: couldn't read instruction at address 0x%"
+ PRIuPTR, address);
+ ret = -1;
+ goto done;
}
*saved = paddr;
/*
@@ -93,12 +128,18 @@ proc_bkptset(struct proc_handle *phdl, uintptr_t address,
piod.piod_addr = &paddr;
piod.piod_len = BREAKPOINT_INSTR_SZ;
if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) {
- warn("ERROR: couldn't write instruction at address 0x%" PRIuPTR,
- address);
- return (-1);
+ DPRINTF("ERROR: couldn't write instruction at address 0x%"
+ PRIuPTR, address);
+ ret = -1;
+ goto done;
}
- return (0);
+done:
+ if (phdl->status != PS_STOP)
+ /* Restart the process if we had to stop it. */
+ proc_cont(phdl);
+
+ return (ret);
}
int
@@ -107,13 +148,20 @@ proc_bkptdel(struct proc_handle *phdl, uintptr_t address,
{
struct ptrace_io_desc piod;
unsigned long paddr, caddr;
+ int ret = 0;
if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
phdl->status == PS_IDLE) {
errno = ENOENT;
return (-1);
}
- DPRINTF("removing breakpoint at 0x%lx\n", address);
+
+ DPRINTFX("removing breakpoint at 0x%lx", address);
+
+ if (phdl->status != PS_STOP)
+ if (proc_stop(phdl) != 0)
+ return (-1);
+
/*
* Overwrite the breakpoint instruction that we setup previously.
*/
@@ -124,12 +172,16 @@ proc_bkptdel(struct proc_handle *phdl, uintptr_t address,
piod.piod_addr = &paddr;
piod.piod_len = BREAKPOINT_INSTR_SZ;
if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) {
- DPRINTF("ERROR: couldn't write instruction at address 0x%" PRIuPTR,
- address);
- return (-1);
+ DPRINTF("ERROR: couldn't write instruction at address 0x%"
+ PRIuPTR, address);
+ ret = -1;
}
+
+ if (phdl->status != PS_STOP)
+ /* Restart the process if we had to stop it. */
+ proc_cont(phdl);
- return (0);
+ return (ret);
}
/*
@@ -153,12 +205,12 @@ proc_bkptexec(struct proc_handle *phdl, unsigned long saved)
int status;
if (proc_regget(phdl, REG_PC, &pc) < 0) {
- warn("ERROR: couldn't get PC register");
+ DPRINTFX("ERROR: couldn't get PC register");
return (-1);
}
proc_bkptregadj(&pc);
if (proc_bkptdel(phdl, pc, saved) < 0) {
- warn("ERROR: couldn't delete breakpoint");
+ DPRINTFX("ERROR: couldn't delete breakpoint");
return (-1);
}
/*
@@ -167,13 +219,13 @@ proc_bkptexec(struct proc_handle *phdl, unsigned long saved)
*/
proc_regset(phdl, REG_PC, pc);
if (ptrace(PT_STEP, proc_getpid(phdl), (caddr_t)1, 0) < 0) {
- warn("ERROR: ptrace step failed");
+ DPRINTFX("ERROR: ptrace step failed");
return (-1);
}
proc_wstatus(phdl);
status = proc_getwstat(phdl);
if (!WIFSTOPPED(status)) {
- warn("ERROR: don't know why process stopped");
+ DPRINTFX("ERROR: don't know why process stopped");
return (-1);
}
/*
@@ -181,7 +233,7 @@ proc_bkptexec(struct proc_handle *phdl, unsigned long saved)
* the same as the one that we were passed in.
*/
if (proc_bkptset(phdl, pc, &samesaved) < 0) {
- warn("ERROR: couldn't restore breakpoint");
+ DPRINTFX("ERROR: couldn't restore breakpoint");
return (-1);
}
assert(samesaved == saved);
diff --git a/lib/libproc/proc_create.c b/lib/libproc/proc_create.c
index 9bd24a232b26..d02eccf0d147 100644
--- a/lib/libproc/proc_create.c
+++ b/lib/libproc/proc_create.c
@@ -75,7 +75,7 @@ proc_attach(pid_t pid, int flags, struct proc_handle **pphdl)
/* Check for an unexpected status. */
if (WIFSTOPPED(status) == 0)
- DPRINTF("ERROR: child process %d status 0x%x", pid, status);
+ DPRINTFX("ERROR: child process %d status 0x%x", pid, status);
else
phdl->status = PS_STOP;
@@ -130,14 +130,14 @@ proc_create(const char *file, char * const *argv, proc_child_func *pcf,
/* Wait for the child process to stop. */
if (waitpid(pid, &status, WUNTRACED) == -1) {
error = errno;
- DPRINTF("ERROR: child process %d didn't stop as expected", pid);
+ DPRINTF("ERROR: child process %d didn't stop as expected", pid);
goto bad;
}
/* Check for an unexpected status. */
if (WIFSTOPPED(status) == 0) {
error = errno;
- DPRINTF("ERROR: child process %d status 0x%x", pid, status);
+ DPRINTFX("ERROR: child process %d status 0x%x", pid, status);
goto bad;
} else
phdl->status = PS_STOP;
diff --git a/lib/libproc/proc_regs.c b/lib/libproc/proc_regs.c
index aac012555a41..145c8fe3fbbc 100644
--- a/lib/libproc/proc_regs.c
+++ b/lib/libproc/proc_regs.c
@@ -76,7 +76,7 @@ proc_regget(struct proc_handle *phdl, proc_reg_t reg, unsigned long *regvalue)
#endif
break;
default:
- warn("ERROR: no support for reg number %d", reg);
+ DPRINTFX("ERROR: no support for reg number %d", reg);
return (-1);
}
@@ -119,7 +119,7 @@ proc_regset(struct proc_handle *phdl, proc_reg_t reg, unsigned long regvalue)
#endif
break;
default:
- warn("ERROR: no support for reg number %d", reg);
+ DPRINTFX("ERROR: no support for reg number %d", reg);
return (-1);
}
if (ptrace(PT_SETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
diff --git a/lib/libproc/proc_sym.c b/lib/libproc/proc_sym.c
index 2dd21fee5648..2338895ffa4a 100644
--- a/lib/libproc/proc_sym.c
+++ b/lib/libproc/proc_sym.c
@@ -96,7 +96,7 @@ proc_objname(struct proc_handle *p, uintptr_t addr, char *objname,
for (i = 0; i < p->nobjs; i++) {
rdl = &p->rdobjs[i];
- if (addr >= rdl->rdl_saddr && addr <= rdl->rdl_eaddr) {
+ if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
strlcpy(objname, rdl->rdl_path, objnamesz);
return (objname);
}
@@ -176,7 +176,7 @@ proc_addr2map(struct proc_handle *p, uintptr_t addr)
kve = kves + i;
if (kve->kve_type == KVME_TYPE_VNODE)
lastvn = i;
- if (addr >= kve->kve_start && addr <= kve->kve_end) {
+ if (addr >= kve->kve_start && addr < kve->kve_end) {
if ((map = malloc(sizeof(*map))) == NULL) {
free(kves);
return (NULL);
@@ -209,7 +209,7 @@ proc_addr2map(struct proc_handle *p, uintptr_t addr)
for (i = 0; i < p->nobjs; i++) {
rdl = &p->rdobjs[i];
- if (addr >= rdl->rdl_saddr && addr <= rdl->rdl_eaddr) {
+ if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
if ((map = malloc(sizeof(*map))) == NULL)
return (NULL);
proc_rdl2prmap(rdl, map);
@@ -238,16 +238,16 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
if ((map = proc_addr2map(p, addr)) == NULL)
return (-1);
- if (!map->pr_mapname || (fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) {
- warn("ERROR: open %s failed", map->pr_mapname);
+ if ((fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) {
+ DPRINTF("ERROR: open %s failed", map->pr_mapname);
goto err0;
}
if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
- warn("ERROR: elf_begin() failed");
+ DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
goto err1;
}
if (gelf_getehdr(e, &ehdr) == NULL) {
- warn("ERROR: gelf_getehdr() failed");
+ DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
goto err2;
}
/*
@@ -275,7 +275,7 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
* Then look up the string name in STRTAB (.dynstr)
*/
if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
- DPRINTF("ERROR: elf_getdata() failed");
+ DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
goto symtab;
}
i = 0;
@@ -284,8 +284,11 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
* Calculate the address mapped to the virtual memory
* by rtld.
*/
- rsym = map->pr_vaddr + sym.st_value;
- if (addr >= rsym && addr <= (rsym + sym.st_size)) {
+ if (ehdr.e_type != ET_EXEC)
+ rsym = map->pr_vaddr + sym.st_value;
+ else
+ rsym = sym.st_value;
+ if (addr >= rsym && addr < rsym + sym.st_size) {
s = elf_strptr(e, dynsymstridx, sym.st_name);
if (s) {
if (s[0] == '_' && s[1] == 'Z' && s[2])
@@ -309,10 +312,8 @@ symtab:
* Iterate over the Symbols Table to find the symbol.
* Then look up the string name in STRTAB (.dynstr)
*/
- if (symtabscn == NULL)
- goto err2;
if ((data = elf_getdata(symtabscn, NULL)) == NULL) {
- DPRINTF("ERROR: elf_getdata() failed");
+ DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
goto err2;
}
i = 0;
@@ -325,7 +326,7 @@ symtab:
rsym = map->pr_vaddr + sym.st_value;
else
rsym = sym.st_value;
- if (addr >= rsym && addr <= (rsym + sym.st_size)) {
+ if (addr >= rsym && addr < rsym + sym.st_size) {
s = elf_strptr(e, symtabstridx, sym.st_name);
if (s) {
if (s[0] == '_' && s[1] == 'Z' && s[2])
@@ -420,7 +421,7 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
unsigned long symtabstridx = 0, dynsymstridx = 0;
if ((map = proc_name2map(p, object)) == NULL) {
- DPRINTF("ERROR: couldn't find object %s", object);
+ DPRINTFX("ERROR: couldn't find object %s", object);
goto err0;
}
if ((fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) {
@@ -428,11 +429,11 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
goto err0;
}
if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
- warn("ERROR: elf_begin() failed");
+ DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
goto err1;
}
if (gelf_getehdr(e, &ehdr) == NULL) {
- warn("ERROR: gelf_getehdr() failed");
+ DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
goto err2;
}
/*
@@ -460,13 +461,13 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
* Then look up the string name in STRTAB (.dynstr)
*/
if ((data = elf_getdata(dynsymscn, NULL))) {
- DPRINTF("ERROR: elf_getdata() failed");
i = 0;
while (gelf_getsym(data, i++, &sym) != NULL) {
s = elf_strptr(e, dynsymstridx, sym.st_name);
if (s && strcmp(s, symbol) == 0) {
memcpy(symcopy, &sym, sizeof(sym));
- symcopy->st_value = map->pr_vaddr + sym.st_value;
+ if (ehdr.e_type != ET_EXEC)
+ symcopy->st_value += map->pr_vaddr;
error = 0;
goto out;
}
@@ -476,20 +477,21 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
* Iterate over the Symbols Table to find the symbol.
* Then look up the string name in STRTAB (.dynstr)
*/
- if (symtabscn == NULL)
- goto err2;
if ((data = elf_getdata(symtabscn, NULL))) {
i = 0;
while (gelf_getsym(data, i++, &sym) != NULL) {
s = elf_strptr(e, symtabstridx, sym.st_name);
if (s && strcmp(s, symbol) == 0) {
memcpy(symcopy, &sym, sizeof(sym));
+ if (ehdr.e_type != ET_EXEC)
+ symcopy->st_value += map->pr_vaddr;
error = 0;
goto out;
}
}
}
out:
+ DPRINTFX("found addr 0x%lx for %s", symcopy->st_value, symbol);
err2:
elf_end(e);
err1:
@@ -510,6 +512,7 @@ proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
prmap_t *map;
Elf_Scn *scn, *foundscn = NULL;
Elf_Data *data;
+ GElf_Ehdr ehdr;
GElf_Shdr shdr;
GElf_Sym sym;
unsigned long stridx = -1;
@@ -519,13 +522,17 @@ proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
if ((map = proc_name2map(p, object)) == NULL)
return (-1);
if ((fd = open(map->pr_mapname, O_RDONLY)) < 0) {
- warn("ERROR: open %s failed", map->pr_mapname);
+ DPRINTF("ERROR: open %s failed", map->pr_mapname);
goto err0;
}
if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
- warn("ERROR: elf_begin() failed");
+ DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
goto err1;
}
+ if (gelf_getehdr(e, &ehdr) == NULL) {
+ DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
+ goto err2;
+ }
/*
* Find the section we are looking for.
*/
@@ -546,7 +553,7 @@ proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
return (-1);
stridx = shdr.sh_link;
if ((data = elf_getdata(foundscn, NULL)) == NULL) {
- DPRINTF("ERROR: elf_getdata() failed");
+ DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
goto err2;
}
i = 0;
@@ -576,7 +583,8 @@ proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
(mask & TYPE_FILE) == 0)
continue;
s = elf_strptr(e, stridx, sym.st_name);
- sym.st_value += map->pr_vaddr;
+ if (ehdr.e_type != ET_EXEC)
+ sym.st_value += map->pr_vaddr;
(*func)(cd, &sym, s);
}
error = 0;
diff --git a/lib/libproc/proc_util.c b/lib/libproc/proc_util.c
index 089095e9ed50..1c3d5229c9f4 100644
--- a/lib/libproc/proc_util.c
+++ b/lib/libproc/proc_util.c
@@ -146,7 +146,7 @@ proc_wstatus(struct proc_handle *phdl)
return (-1);
if (waitpid(phdl->pid, &status, WUNTRACED) < 0) {
if (errno != EINTR)
- warn("waitpid");
+ DPRINTF("waitpid");
return (-1);
}
if (WIFSTOPPED(status))
diff --git a/lib/libproc/test/t1-bkpt/Makefile b/lib/libproc/test/t1-bkpt/Makefile
index fd93fdd98ee8..eb5b37f94936 100644
--- a/lib/libproc/test/t1-bkpt/Makefile
+++ b/lib/libproc/test/t1-bkpt/Makefile
@@ -7,6 +7,6 @@ SRCS= t1-bkpt.c
LDADD= -lproc -lelf -lrtld_db -lutil
DPADD= ${LIBPROC} ${LIBELF}
-WITHOUT_MAN=
+MAN=
.include <bsd.prog.mk>
diff --git a/lib/libproc/test/t2-name2map/Makefile b/lib/libproc/test/t2-name2map/Makefile
index 3dca51c26c9e..9002accf6904 100644
--- a/lib/libproc/test/t2-name2map/Makefile
+++ b/lib/libproc/test/t2-name2map/Makefile
@@ -7,6 +7,6 @@ SRCS= t2-name2map.c
LDADD= -lproc -lelf -lrtld_db -lutil
DPADD= ${LIBPROC} ${LIBELF}
-WITHOUT_MAN=
+MAN=
.include <bsd.prog.mk>
diff --git a/lib/libproc/test/t3-name2sym/Makefile b/lib/libproc/test/t3-name2sym/Makefile
index 187f9c1c2641..68e23c6199d9 100644
--- a/lib/libproc/test/t3-name2sym/Makefile
+++ b/lib/libproc/test/t3-name2sym/Makefile
@@ -7,6 +7,6 @@ SRCS= t3-name2sym.c
LDADD= -lproc -lelf -lrtld_db -lutil
DPADD= ${LIBPROC} ${LIBELF}
-WITHOUT_MAN=
+MAN=
.include <bsd.prog.mk>