Add libdtrace support for tracing userland programs.
Summary of changes: * Implement a compatibility shim between Solaris libproc and our libproc and remove several ifdefs because of this. * Port the drti to FreeBSD. * Implement the missing DOODAD sections * Link with libproc and librtld_db * Support for ustack, jstack and uregs (by sson@) * Misc bugfixing When writing the SUWN_dof section, we had to resort to building the ELF file layout by "hand". This is the job of libelf, but our libelf doesn't support this yet. When libelf is fixed, we can remove the code under #ifdef BROKEN_LIBELF. Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
e0be1c75f0
commit
0f2bd1e89d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=211554
@ -773,19 +773,27 @@ compile_str(dtrace_cmd_t *dcp)
|
||||
static void
|
||||
prochandler(struct ps_prochandle *P, const char *msg, void *arg)
|
||||
{
|
||||
fatal("DOODAD in function %s, file %s, line %d\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
#if defined(sun)
|
||||
const psinfo_t *prp = Ppsinfo(P);
|
||||
int pid = Pstatus(P)->pr_pid;
|
||||
char name[SIG2STR_MAX];
|
||||
#else
|
||||
int wstatus = proc_getwstat(P);
|
||||
int pid = proc_getpid(P);
|
||||
#endif
|
||||
|
||||
if (msg != NULL) {
|
||||
notice("pid %d: %s\n", pid, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(sun)
|
||||
switch (Pstate(P)) {
|
||||
#else
|
||||
switch (proc_state(P)) {
|
||||
#endif
|
||||
case PS_UNDEAD:
|
||||
#if defined(sun)
|
||||
/*
|
||||
* Ideally we would like to always report pr_wstat here, but it
|
||||
* isn't possible given current /proc semantics. If we grabbed
|
||||
@ -798,9 +806,20 @@ fatal("DOODAD in function %s, file %s, line %d\n",__FUNCTION__,__FILE__,__LINE__
|
||||
notice("pid %d terminated by %s\n", pid,
|
||||
proc_signame(WTERMSIG(prp->pr_wstat),
|
||||
name, sizeof (name)));
|
||||
#else
|
||||
if (WIFSIGNALED(wstatus)) {
|
||||
notice("pid %d terminated by %d\n", pid,
|
||||
WTERMSIG(wstatus));
|
||||
#endif
|
||||
#if defined(sun)
|
||||
} else if (prp != NULL && WEXITSTATUS(prp->pr_wstat) != 0) {
|
||||
notice("pid %d exited with status %d\n",
|
||||
pid, WEXITSTATUS(prp->pr_wstat));
|
||||
#else
|
||||
} else if (WEXITSTATUS(wstatus) != 0) {
|
||||
notice("pid %d exited with status %d\n",
|
||||
pid, WEXITSTATUS(wstatus));
|
||||
#endif
|
||||
} else {
|
||||
notice("pid %d has exited\n", pid);
|
||||
}
|
||||
@ -812,7 +831,6 @@ fatal("DOODAD in function %s, file %s, line %d\n",__FUNCTION__,__FILE__,__LINE__
|
||||
g_pslive--;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <libelf.h>
|
||||
#include <gelf.h>
|
||||
|
||||
/*
|
||||
* In Solaris 10 GA, the only mechanism for communicating helper information
|
||||
@ -53,12 +55,16 @@
|
||||
*/
|
||||
|
||||
static const char *devnamep = "/dev/dtrace/helper";
|
||||
#if defined(sun)
|
||||
static const char *olddevname = "/devices/pseudo/dtrace@0:helper";
|
||||
#endif
|
||||
|
||||
static const char *modname; /* Name of this load object */
|
||||
static int gen; /* DOF helper generation */
|
||||
#if defined(sun)
|
||||
extern dof_hdr_t __SUNW_dof; /* DOF defined in the .SUNW_dof section */
|
||||
static boolean_t dof_init_debug = B_FALSE; /* From DTRACE_DOF_INIT_DEBUG */
|
||||
#endif
|
||||
static boolean_t dof_init_debug = B_TRUE; /* From DTRACE_DOF_INIT_DEBUG */
|
||||
|
||||
static void
|
||||
dprintf(int debug, const char *fmt, ...)
|
||||
@ -83,6 +89,36 @@ dprintf(int debug, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#if !defined(sun)
|
||||
static void
|
||||
fixsymbol(Elf *e, Elf_Data *data, size_t idx, int nprobes, char *buf,
|
||||
dof_sec_t *sec, int *fixedprobes, char *dofstrtab)
|
||||
{
|
||||
GElf_Sym sym;
|
||||
char *s;
|
||||
unsigned char *funcname;
|
||||
dof_probe_t *prb;
|
||||
int j = 0;
|
||||
int ndx;
|
||||
|
||||
while (gelf_getsym(data, j++, &sym) != NULL) {
|
||||
prb = (dof_probe_t *)(buf + sec->dofs_offset);
|
||||
|
||||
for (ndx = nprobes; ndx; ndx--, prb += 1) {
|
||||
funcname = dofstrtab + prb->dofpr_func;
|
||||
s = elf_strptr(e, idx, sym.st_name);
|
||||
if (strcmp(s, funcname) == 0) {
|
||||
dprintf(1, "fixing %s() symbol\n", s);
|
||||
prb->dofpr_addr = sym.st_value;
|
||||
(*fixedprobes)++;
|
||||
}
|
||||
}
|
||||
if (*fixedprobes == nprobes)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(sun)
|
||||
#pragma init(dtrace_dof_init)
|
||||
#else
|
||||
@ -92,22 +128,39 @@ static void dtrace_dof_init(void) __attribute__ ((constructor));
|
||||
static void
|
||||
dtrace_dof_init(void)
|
||||
{
|
||||
#if defined(sun)
|
||||
dof_hdr_t *dof = &__SUNW_dof;
|
||||
#else
|
||||
dof_hdr_t *dof = NULL;
|
||||
#endif
|
||||
#ifdef _LP64
|
||||
Elf64_Ehdr *elf;
|
||||
#else
|
||||
Elf32_Ehdr *elf;
|
||||
#endif
|
||||
dof_helper_t dh;
|
||||
#if defined(sun)
|
||||
Link_map *lmp;
|
||||
#if defined(sun)
|
||||
Lmid_t lmid;
|
||||
#else
|
||||
struct link_map *lmp;
|
||||
u_long lmid = 0;
|
||||
dof_sec_t *sec;
|
||||
size_t i;
|
||||
#endif
|
||||
int fd;
|
||||
const char *p;
|
||||
#if !defined(sun)
|
||||
Elf *e;
|
||||
Elf_Scn *scn = NULL;
|
||||
Elf_Data *symtabdata = NULL, *dynsymdata = NULL;
|
||||
GElf_Shdr shdr;
|
||||
int efd, nprobes;
|
||||
char *s;
|
||||
size_t shstridx, symtabidx = 0, dynsymidx = 0;
|
||||
unsigned char *dofstrtab = NULL;
|
||||
unsigned char *buf;
|
||||
int fixedprobes = 0;
|
||||
#endif
|
||||
|
||||
if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
|
||||
return;
|
||||
@ -127,10 +180,46 @@ dtrace_dof_init(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if ((modname = strrchr(lmp->l_name, '/')) == NULL)
|
||||
modname = lmp->l_name;
|
||||
else
|
||||
modname++;
|
||||
#if !defined(sun)
|
||||
elf_version(EV_CURRENT);
|
||||
if ((efd = open(lmp->l_name, O_RDONLY, 0)) < 0) {
|
||||
dprintf(1, "couldn't open file for reading\n");
|
||||
return;
|
||||
}
|
||||
if ((e = elf_begin(efd, ELF_C_READ, NULL)) == NULL) {
|
||||
dprintf(1, "elf_begin failed\n");
|
||||
close(efd);
|
||||
return;
|
||||
}
|
||||
elf_getshdrstrndx(e, &shstridx);
|
||||
dof = NULL;
|
||||
while ((scn = elf_nextscn(e, scn)) != NULL) {
|
||||
gelf_getshdr(scn, &shdr);
|
||||
if (shdr.sh_type == SHT_SYMTAB) {
|
||||
symtabidx = shdr.sh_link;
|
||||
symtabdata = elf_getdata(scn, NULL);
|
||||
} else if (shdr.sh_type == SHT_DYNSYM) {
|
||||
dynsymidx = shdr.sh_link;
|
||||
dynsymdata = elf_getdata(scn, NULL);
|
||||
} else if (shdr.sh_type == SHT_PROGBITS) {
|
||||
s = elf_strptr(e, shstridx, shdr.sh_name);
|
||||
if (s && strcmp(s, ".SUNW_dof") == 0) {
|
||||
dof = elf_getdata(scn, NULL)->d_buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dof == NULL) {
|
||||
dprintf(1, "SUNW_dof section not found\n");
|
||||
elf_end(e);
|
||||
close(efd);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
|
||||
dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
|
||||
@ -158,7 +247,7 @@ dtrace_dof_init(void)
|
||||
|
||||
if ((fd = open64(devnamep, O_RDWR)) < 0) {
|
||||
dprintf(1, "failed to open helper device %s", devnamep);
|
||||
|
||||
#if defined(sun)
|
||||
/*
|
||||
* If the device path wasn't explicitly set, try again with
|
||||
* the old device path.
|
||||
@ -172,14 +261,79 @@ dtrace_dof_init(void)
|
||||
dprintf(1, "failed to open helper device %s", devnamep);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(sun)
|
||||
/*
|
||||
* We need to fix the base address of each probe since this wasn't
|
||||
* done by ld(1). (ld(1) needs to grow support for parsing the
|
||||
* SUNW_dof section).
|
||||
*
|
||||
* The complexity of this is not that great. The first for loop
|
||||
* iterates over the sections inside the DOF file. There are usually
|
||||
* 10 sections here. We asume the STRTAB section comes first and the
|
||||
* PROBES section comes after. Since we are only interested in fixing
|
||||
* data inside the PROBES section we quit the for loop after processing
|
||||
* the PROBES section. It's usually the case that the first section
|
||||
* is the STRTAB section and the second section is the PROBES section,
|
||||
* so this for loop is not meaningful when doing complexity analysis.
|
||||
*
|
||||
* After finding the probes section, we iterate over the symbols
|
||||
* in the symtab section. When we find a symbol name that matches
|
||||
* the probe function name, we fix it. If we have fixed all the
|
||||
* probes, we exit all the loops and we are done.
|
||||
* The number of probes is given by the variable 'nprobes' and this
|
||||
* depends entirely on the user, but some optimizations were done.
|
||||
*
|
||||
* We are assuming the number of probes is less than the number of
|
||||
* symbols (libc can have 4k symbols, for example).
|
||||
*/
|
||||
sec = (dof_sec_t *)(dof + 1);
|
||||
buf = (char *)dof;
|
||||
for (i = 0; i < dof->dofh_secnum; i++, sec++) {
|
||||
if (sec->dofs_type == DOF_SECT_STRTAB)
|
||||
dofstrtab = (unsigned char *)(buf + sec->dofs_offset);
|
||||
else if (sec->dofs_type == DOF_SECT_PROBES && dofstrtab)
|
||||
break;
|
||||
|
||||
}
|
||||
nprobes = sec->dofs_size / sec->dofs_entsize;
|
||||
fixsymbol(e, symtabdata, symtabidx, nprobes, buf, sec, &fixedprobes,
|
||||
dofstrtab);
|
||||
if (fixedprobes != nprobes) {
|
||||
/*
|
||||
* If we haven't fixed all the probes using the
|
||||
* symtab section, look inside the dynsym
|
||||
* section.
|
||||
*/
|
||||
fixsymbol(e, dynsymdata, dynsymidx, nprobes, buf, sec,
|
||||
&fixedprobes, dofstrtab);
|
||||
}
|
||||
if (fixedprobes != nprobes) {
|
||||
fprintf(stderr, "WARNING: number of probes "
|
||||
"fixed does not match the number of "
|
||||
"defined probes (%d != %d, "
|
||||
"respectively)\n", fixedprobes, nprobes);
|
||||
fprintf(stderr, "WARNING: some probes might "
|
||||
"not fire or your program might crash\n");
|
||||
}
|
||||
#endif
|
||||
if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
|
||||
dprintf(1, "DTrace ioctl failed for DOF at %p", dof);
|
||||
else
|
||||
else {
|
||||
dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof);
|
||||
#if !defined(sun)
|
||||
gen = dh.gen;
|
||||
#endif
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
#if !defined(sun)
|
||||
elf_end(e);
|
||||
(void) close(efd);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(sun)
|
||||
@ -198,7 +352,7 @@ dtrace_dof_fini(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((gen = ioctl(fd, DTRACEHIOC_REMOVE, gen)) == -1)
|
||||
if ((gen = ioctl(fd, DTRACEHIOC_REMOVE, &gen)) == -1)
|
||||
dprintf(1, "DTrace ioctl failed to remove DOF (%d)\n", gen);
|
||||
else
|
||||
dprintf(1, "DTrace ioctl removed DOF (%d)\n", gen);
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#include <sys/sysctl.h>
|
||||
#include <libproc_compat.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
@ -264,11 +265,7 @@ dt_aggregate_usym(dtrace_hdl_t *dtp, uint64_t *data)
|
||||
|
||||
dt_proc_lock(dtp, P);
|
||||
|
||||
#if defined(sun)
|
||||
if (Plookup_by_addr(P, *pc, NULL, 0, &sym) == 0)
|
||||
#else
|
||||
if (proc_addr2sym(P, *pc, NULL, 0, &sym) == 0)
|
||||
#endif
|
||||
*pc = sym.st_value;
|
||||
|
||||
dt_proc_unlock(dtp, P);
|
||||
@ -291,11 +288,7 @@ dt_aggregate_umod(dtrace_hdl_t *dtp, uint64_t *data)
|
||||
|
||||
dt_proc_lock(dtp, P);
|
||||
|
||||
#if defined(sun)
|
||||
if ((map = Paddr_to_map(P, *pc)) != NULL)
|
||||
#else
|
||||
if ((map = proc_addr2map(P, *pc)) != NULL)
|
||||
#endif
|
||||
*pc = map->pr_vaddr;
|
||||
|
||||
dt_proc_unlock(dtp, P);
|
||||
|
@ -34,6 +34,9 @@
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
#include <dt_impl.h>
|
||||
#if !defined(sun)
|
||||
#include <libproc_compat.h>
|
||||
#endif
|
||||
|
||||
#define DT_MASK_LO 0x00000000FFFFFFFFULL
|
||||
|
||||
@ -952,17 +955,9 @@ dt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
|
||||
if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
|
||||
break;
|
||||
|
||||
#if defined(sun)
|
||||
if (P != NULL && Plookup_by_addr(P, pc[i],
|
||||
#else
|
||||
if (P != NULL && proc_addr2sym(P, pc[i],
|
||||
#endif
|
||||
name, sizeof (name), &sym) == 0) {
|
||||
#if defined(sun)
|
||||
(void) Pobjname(P, pc[i], objname, sizeof (objname));
|
||||
#else
|
||||
(void) proc_objname(P, pc[i], objname, sizeof (objname));
|
||||
#endif
|
||||
|
||||
if (pc[i] > sym.st_value) {
|
||||
(void) snprintf(c, sizeof (c),
|
||||
@ -973,12 +968,8 @@ dt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
|
||||
"%s`%s", dt_basename(objname), name);
|
||||
}
|
||||
} else if (str != NULL && str[0] != '\0' && str[0] != '@' &&
|
||||
#if defined(sun)
|
||||
(P != NULL && ((map = Paddr_to_map(P, pc[i])) == NULL ||
|
||||
(map->pr_mflags & MA_WRITE)))) {
|
||||
#else
|
||||
(P != NULL && ((map = proc_addr2map(P, pc[i])) == NULL))) {
|
||||
#endif
|
||||
/*
|
||||
* If the current string pointer in the string table
|
||||
* does not point to an empty string _and_ the program
|
||||
@ -994,11 +985,7 @@ dt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
|
||||
*/
|
||||
(void) snprintf(c, sizeof (c), "%s", str);
|
||||
} else {
|
||||
#if defined(sun)
|
||||
if (P != NULL && Pobjname(P, pc[i], objname,
|
||||
#else
|
||||
if (P != NULL && proc_objname(P, pc[i], objname,
|
||||
#endif
|
||||
sizeof (objname)) != 0) {
|
||||
(void) snprintf(c, sizeof (c), "%s`0x%llx",
|
||||
dt_basename(objname), (u_longlong_t)pc[i]);
|
||||
@ -1068,11 +1055,7 @@ dt_print_usym(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, dtrace_actkind_t act)
|
||||
|
||||
dt_proc_lock(dtp, P);
|
||||
|
||||
#if defined(sun)
|
||||
if (Plookup_by_addr(P, pc, NULL, 0, &sym) == 0)
|
||||
#else
|
||||
if (proc_addr2sym(P, pc, NULL, 0, &sym) == 0)
|
||||
#endif
|
||||
pc = sym.st_value;
|
||||
|
||||
dt_proc_unlock(dtp, P);
|
||||
@ -1115,11 +1098,7 @@ dt_print_umod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr)
|
||||
if (P != NULL)
|
||||
dt_proc_lock(dtp, P); /* lock handle while we perform lookups */
|
||||
|
||||
#if defined(sun)
|
||||
if (P != NULL && Pobjname(P, pc, objname, sizeof (objname)) != 0) {
|
||||
#else
|
||||
if (P != NULL && proc_objname(P, pc, objname, sizeof (objname)) != 0) {
|
||||
#endif
|
||||
(void) snprintf(c, sizeof (c), "%s", dt_basename(objname));
|
||||
} else {
|
||||
(void) snprintf(c, sizeof (c), "0x%llx", (u_longlong_t)pc);
|
||||
|
@ -51,6 +51,9 @@
|
||||
#include <wait.h>
|
||||
#else
|
||||
#include <sys/wait.h>
|
||||
#include <libelf.h>
|
||||
#include <gelf.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <sys/ipc.h>
|
||||
@ -412,7 +415,6 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
|
||||
s = &dofs[dofrh->dofr_tgtsec];
|
||||
|
||||
for (j = 0; j < nrel; j++) {
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
#if defined(__arm__)
|
||||
/* XXX */
|
||||
@ -1519,14 +1521,29 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
|
||||
|
||||
off = rela.r_offset - fsym.st_value;
|
||||
if (dt_modtext(dtp, data_tgt->d_buf, eprobe,
|
||||
&rela, &off) != 0) {
|
||||
&rela, &off) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dt_probe_define(pvp, prp, s, r, off, eprobe) != 0) {
|
||||
return (dt_link_error(dtp, elf, fd, bufs,
|
||||
"failed to allocate space for probe"));
|
||||
}
|
||||
#if !defined(sun)
|
||||
/*
|
||||
* Our linker doesn't understand the SUNW_IGNORE ndx and
|
||||
* will try to use this relocation when we build the
|
||||
* final executable. Since we are done processing this
|
||||
* relocation, mark it as inexistant and let libelf
|
||||
* remove it from the file.
|
||||
* If this wasn't done, we would have garbage added to
|
||||
* the executable file as the symbol is going to be
|
||||
* change from UND to ABS.
|
||||
*/
|
||||
rela.r_offset = 0;
|
||||
rela.r_info = 0;
|
||||
rela.r_addend = 0;
|
||||
(void) gelf_update_rela(data_rel, i, &rela);
|
||||
#endif
|
||||
|
||||
mod = 1;
|
||||
(void) elf_flagdata(data_tgt, ELF_C_SET, ELF_F_DIRTY);
|
||||
@ -1538,13 +1555,13 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
|
||||
* already been processed by an earlier link
|
||||
* invocation.
|
||||
*/
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
#if !defined(sun)
|
||||
#define SHN_SUNW_IGNORE SHN_ABS
|
||||
#endif
|
||||
if (rsym.st_shndx != SHN_SUNW_IGNORE) {
|
||||
rsym.st_shndx = SHN_SUNW_IGNORE;
|
||||
(void) gelf_update_sym(data_sym, ndx, &rsym);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1554,6 +1571,9 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
(void) elf_end(elf);
|
||||
(void) close(fd);
|
||||
|
||||
#if !defined(sun)
|
||||
if (nsym > 0)
|
||||
#endif
|
||||
while ((pair = bufs) != NULL) {
|
||||
bufs = pair->dlp_next;
|
||||
dt_free(dtp, pair->dlp_str);
|
||||
@ -1574,6 +1594,19 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
|
||||
{
|
||||
#if !defined(sun)
|
||||
char tfile[PATH_MAX];
|
||||
Elf *e;
|
||||
Elf_Scn *scn;
|
||||
Elf_Data *data;
|
||||
GElf_Shdr shdr;
|
||||
int efd;
|
||||
size_t stridx;
|
||||
unsigned char *buf;
|
||||
char *s;
|
||||
int loc;
|
||||
GElf_Ehdr ehdr;
|
||||
Elf_Scn *scn0;
|
||||
GElf_Shdr shdr0;
|
||||
uint64_t off, rc;
|
||||
#endif
|
||||
char drti[PATH_MAX];
|
||||
dof_hdr_t *dof;
|
||||
@ -1697,12 +1730,17 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
|
||||
(void) unlink(file);
|
||||
#endif
|
||||
|
||||
#if defined(sun)
|
||||
if (dtp->dt_oflags & DTRACE_O_LP64)
|
||||
status = dump_elf64(dtp, dof, fd);
|
||||
else
|
||||
status = dump_elf32(dtp, dof, fd);
|
||||
|
||||
if (status != 0 || lseek(fd, 0, SEEK_SET) != 0) {
|
||||
#else
|
||||
/* We don't write the ELF header, just the DOF section */
|
||||
if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz) {
|
||||
#endif
|
||||
return (dt_link_error(dtp, NULL, -1, NULL,
|
||||
"failed to write %s: %s", file, strerror(errno)));
|
||||
}
|
||||
@ -1726,7 +1764,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
|
||||
|
||||
(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, fd, drti);
|
||||
#else
|
||||
const char *fmt = "%s -o %s -r %s %s";
|
||||
const char *fmt = "%s -o %s -r %s";
|
||||
|
||||
#if defined(__amd64__)
|
||||
/*
|
||||
@ -1748,11 +1786,14 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
|
||||
len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile,
|
||||
drti) + 1;
|
||||
|
||||
#if !defined(sun)
|
||||
len *= 2;
|
||||
#endif
|
||||
cmd = alloca(len);
|
||||
|
||||
(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, tfile, drti);
|
||||
(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file,
|
||||
drti);
|
||||
#endif
|
||||
|
||||
if ((status = system(cmd)) == -1) {
|
||||
ret = dt_link_error(dtp, NULL, -1, NULL,
|
||||
"failed to run %s: %s", dtp->dt_ld_path,
|
||||
@ -1760,8 +1801,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
|
||||
goto done;
|
||||
}
|
||||
|
||||
(void) close(fd); /* release temporary file */
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
ret = dt_link_error(dtp, NULL, -1, NULL,
|
||||
"failed to link %s: %s failed due to signal %d",
|
||||
@ -1775,6 +1814,138 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
|
||||
file, dtp->dt_ld_path, WEXITSTATUS(status));
|
||||
goto done;
|
||||
}
|
||||
#if !defined(sun)
|
||||
#define BROKEN_LIBELF
|
||||
/*
|
||||
* FreeBSD's ld(1) is not instructed to interpret and add
|
||||
* correctly the SUNW_dof section present in tfile.
|
||||
* We use libelf to add this section manually and hope the next
|
||||
* ld invocation won't remove it.
|
||||
*/
|
||||
elf_version(EV_CURRENT);
|
||||
if ((efd = open(file, O_RDWR, 0)) < 0) {
|
||||
ret = dt_link_error(dtp, NULL, -1, NULL,
|
||||
"failed to open file %s: %s",
|
||||
file, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
if ((e = elf_begin(efd, ELF_C_RDWR, NULL)) == NULL) {
|
||||
close(efd);
|
||||
ret = dt_link_error(dtp, NULL, -1, NULL,
|
||||
"failed to open elf file: %s",
|
||||
elf_errmsg(elf_errno()));
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* Add the string '.SUWN_dof' to the shstrtab section.
|
||||
*/
|
||||
#ifdef BROKEN_LIBELF
|
||||
elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
|
||||
#endif
|
||||
elf_getshdrstrndx(e, &stridx);
|
||||
scn = elf_getscn(e, stridx);
|
||||
gelf_getshdr(scn, &shdr);
|
||||
data = elf_newdata(scn);
|
||||
data->d_off = shdr.sh_size;
|
||||
data->d_buf = ".SUNW_dof";
|
||||
data->d_size = 10;
|
||||
data->d_type = ELF_T_BYTE;
|
||||
loc = shdr.sh_size;
|
||||
shdr.sh_size += data->d_size;
|
||||
gelf_update_shdr(scn, &shdr);
|
||||
#ifdef BROKEN_LIBELF
|
||||
off = shdr.sh_offset;
|
||||
rc = shdr.sh_offset + shdr.sh_size;
|
||||
gelf_getehdr(e, &ehdr);
|
||||
if (ehdr.e_shoff > off) {
|
||||
off = ehdr.e_shoff + ehdr.e_shnum * ehdr.e_shentsize;
|
||||
rc = roundup(rc, 8);
|
||||
ehdr.e_shoff = rc;
|
||||
gelf_update_ehdr(e, &ehdr);
|
||||
rc += ehdr.e_shnum * ehdr.e_shentsize;
|
||||
}
|
||||
for (;;) {
|
||||
scn0 = NULL;
|
||||
scn = NULL;
|
||||
while ((scn = elf_nextscn(e, scn)) != NULL) {
|
||||
gelf_getshdr(scn, &shdr);
|
||||
if (shdr.sh_type == SHT_NOBITS ||
|
||||
shdr.sh_offset < off)
|
||||
continue;
|
||||
/* Find the immediately adjcent section. */
|
||||
if (scn0 == NULL ||
|
||||
shdr.sh_offset < shdr0.sh_offset) {
|
||||
scn0 = scn;
|
||||
gelf_getshdr(scn0, &shdr0);
|
||||
}
|
||||
}
|
||||
if (scn0 == NULL)
|
||||
break;
|
||||
/* Load section data to work around another bug */
|
||||
elf_getdata(scn0, NULL);
|
||||
/* Update section header, assure section alignment */
|
||||
off = shdr0.sh_offset + shdr0.sh_size;
|
||||
rc = roundup(rc, shdr0.sh_addralign);
|
||||
shdr0.sh_offset = rc;
|
||||
gelf_update_shdr(scn0, &shdr0);
|
||||
rc += shdr0.sh_size;
|
||||
}
|
||||
if (elf_update(e, ELF_C_WRITE) < 0) {
|
||||
ret = dt_link_error(dtp, NULL, -1, NULL,
|
||||
"failed to add append the shstrtab section: %s",
|
||||
elf_errmsg(elf_errno()));
|
||||
elf_end(e);
|
||||
close(efd);
|
||||
goto done;
|
||||
}
|
||||
elf_end(e);
|
||||
e = elf_begin(efd, ELF_C_RDWR, NULL);
|
||||
#endif
|
||||
/*
|
||||
* Construct the .SUNW_dof section.
|
||||
*/
|
||||
scn = elf_newscn(e);
|
||||
data = elf_newdata(scn);
|
||||
buf = mmap(NULL, dof->dofh_filesz, PROT_READ, MAP_SHARED,
|
||||
fd, 0);
|
||||
if (buf == MAP_FAILED) {
|
||||
ret = dt_link_error(dtp, NULL, -1, NULL,
|
||||
"failed to mmap buffer %s", strerror(errno));
|
||||
elf_end(e);
|
||||
close(efd);
|
||||
goto done;
|
||||
}
|
||||
data->d_buf = buf;
|
||||
data->d_align = 4;
|
||||
data->d_size = dof->dofh_filesz;
|
||||
data->d_version = EV_CURRENT;
|
||||
gelf_getshdr(scn, &shdr);
|
||||
shdr.sh_name = loc;
|
||||
shdr.sh_flags = SHF_ALLOC;
|
||||
/*
|
||||
* Actually this should be SHT_SUNW_dof, but FreeBSD's ld(1)
|
||||
* will remove this 'unknown' section when we try to create an
|
||||
* executable using the object we are modifying, so we stop
|
||||
* playing by the rules and use SHT_PROGBITS.
|
||||
* Also, note that our drti has modifications to handle this.
|
||||
*/
|
||||
shdr.sh_type = SHT_PROGBITS;
|
||||
shdr.sh_addralign = 4;
|
||||
gelf_update_shdr(scn, &shdr);
|
||||
if (elf_update(e, ELF_C_WRITE) < 0) {
|
||||
ret = dt_link_error(dtp, NULL, -1, NULL,
|
||||
"failed to add the SUNW_dof section: %s",
|
||||
elf_errmsg(elf_errno()));
|
||||
munmap(buf, dof->dofh_filesz);
|
||||
elf_end(e);
|
||||
close(efd);
|
||||
goto done;
|
||||
}
|
||||
munmap(buf, dof->dofh_filesz);
|
||||
elf_end(e);
|
||||
close(efd);
|
||||
#endif
|
||||
(void) close(fd); /* release temporary file */
|
||||
} else {
|
||||
(void) close(fd);
|
||||
}
|
||||
|
@ -283,10 +283,8 @@ static const dt_ident_t _dtrace_globals[] = {
|
||||
DT_VERS_1_5, &dt_idops_func, "string(int, void *)" },
|
||||
{ "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0,
|
||||
&dt_idops_type, "uint_t" },
|
||||
#if defined(sun)
|
||||
{ "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
|
||||
&dt_idops_func, "stack(...)" },
|
||||
#endif
|
||||
{ "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
|
||||
&dt_idops_func, "string(int64_t)" },
|
||||
{ "lquantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_LQUANTIZE,
|
||||
@ -465,8 +463,10 @@ static const dt_ident_t _dtrace_globals[] = {
|
||||
#if defined(sun)
|
||||
{ "uaddr", DT_IDENT_ACTFUNC, 0, DT_ACT_UADDR, DT_ATTR_STABCMN,
|
||||
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
|
||||
#endif
|
||||
{ "ucaller", DT_IDENT_SCALAR, 0, DIF_VAR_UCALLER, DT_ATTR_STABCMN,
|
||||
DT_VERS_1_2, &dt_idops_type, "uint64_t" },
|
||||
#if defined(sun)
|
||||
{ "ufunc", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
|
||||
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
|
||||
#endif
|
||||
@ -475,6 +475,7 @@ static const dt_ident_t _dtrace_globals[] = {
|
||||
#if defined(sun)
|
||||
{ "umod", DT_IDENT_ACTFUNC, 0, DT_ACT_UMOD, DT_ATTR_STABCMN,
|
||||
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
|
||||
#endif
|
||||
{ "uregs", DT_IDENT_ARRAY, 0, DIF_VAR_UREGS, DT_ATTR_STABCMN, DT_VERS_1_0,
|
||||
&dt_idops_regs, NULL },
|
||||
{ "ustack", DT_IDENT_ACTFUNC, 0, DT_ACT_USTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
|
||||
@ -482,6 +483,7 @@ static const dt_ident_t _dtrace_globals[] = {
|
||||
{ "ustackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_USTACKDEPTH,
|
||||
DT_ATTR_STABCMN, DT_VERS_1_2,
|
||||
&dt_idops_type, "uint32_t" },
|
||||
#if defined(sun)
|
||||
{ "usym", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
|
||||
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
|
||||
#endif
|
||||
@ -760,9 +762,7 @@ int _dtrace_argmax = 32; /* default maximum number of probe arguments */
|
||||
|
||||
int _dtrace_debug = 0; /* debug messages enabled (off) */
|
||||
const char *const _dtrace_version = DT_VERS_STRING; /* API version string */
|
||||
#if defined(sun)
|
||||
int _dtrace_rdvers = RD_VERSION; /* rtld_db feature version */
|
||||
#endif
|
||||
|
||||
typedef struct dt_fdlist {
|
||||
int *df_fds; /* array of provider driver file descriptors */
|
||||
@ -780,12 +780,10 @@ _dtrace_init(void)
|
||||
{
|
||||
_dtrace_debug = getenv("DTRACE_DEBUG") != NULL;
|
||||
|
||||
#if defined(sun)
|
||||
for (; _dtrace_rdvers > 0; _dtrace_rdvers--) {
|
||||
if (rd_init(_dtrace_rdvers) == RD_OK)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(__i386__)
|
||||
/* make long doubles 64 bits -sson */
|
||||
(void) fpsetprec(FP_PE);
|
||||
@ -1102,7 +1100,11 @@ dt_vopen(int version, int flags, int *errp,
|
||||
|
||||
bzero(dtp, sizeof (dtrace_hdl_t));
|
||||
dtp->dt_oflags = flags;
|
||||
#if defined(sun)
|
||||
dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
|
||||
#else
|
||||
dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
|
||||
#endif
|
||||
dtp->dt_linkmode = DT_LINK_KERNEL;
|
||||
dtp->dt_linktype = DT_LTYP_ELF;
|
||||
dtp->dt_xlatemode = DT_XL_STATIC;
|
||||
|
@ -40,6 +40,9 @@
|
||||
#include <dt_program.h>
|
||||
#include <dt_pid.h>
|
||||
#include <dt_string.h>
|
||||
#if !defined(sun)
|
||||
#include <libproc_compat.h>
|
||||
#endif
|
||||
|
||||
typedef struct dt_pid_probe {
|
||||
dtrace_hdl_t *dpp_dtp;
|
||||
@ -142,7 +145,6 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
|
||||
pp->dpp_obj);
|
||||
|
||||
if (!isdash && gmatch("return", pp->dpp_name)) {
|
||||
#ifdef DOODAD
|
||||
if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp,
|
||||
pp->dpp_stret) < 0) {
|
||||
return (dt_pid_error(dtp, pcb, dpr, ftp,
|
||||
@ -150,20 +152,17 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
|
||||
"for '%s': %s", func,
|
||||
dtrace_errmsg(dtp, dtrace_errno(dtp))));
|
||||
}
|
||||
#endif
|
||||
|
||||
nmatches++;
|
||||
}
|
||||
|
||||
if (!isdash && gmatch("entry", pp->dpp_name)) {
|
||||
#ifdef DOODAD
|
||||
if (dt_pid_create_entry_probe(pp->dpp_pr, dtp, ftp, symp) < 0) {
|
||||
return (dt_pid_error(dtp, pcb, dpr, ftp,
|
||||
D_PROC_CREATEFAIL, "failed to create entry probe "
|
||||
"for '%s': %s", func,
|
||||
dtrace_errmsg(dtp, dtrace_errno(dtp))));
|
||||
}
|
||||
#endif
|
||||
|
||||
nmatches++;
|
||||
}
|
||||
@ -182,10 +181,8 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
|
||||
(u_longlong_t)off, func));
|
||||
}
|
||||
|
||||
#ifdef DOODAD
|
||||
err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp,
|
||||
symp, off);
|
||||
#endif
|
||||
|
||||
if (err == DT_PROC_ERR) {
|
||||
return (dt_pid_error(dtp, pcb, dpr, ftp,
|
||||
@ -203,7 +200,6 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
|
||||
nmatches++;
|
||||
|
||||
} else if (glob && !isdash) {
|
||||
#ifdef DOODAD
|
||||
if (dt_pid_create_glob_offset_probes(pp->dpp_pr,
|
||||
pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) {
|
||||
return (dt_pid_error(dtp, pcb, dpr, ftp,
|
||||
@ -211,7 +207,6 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
|
||||
"failed to create offset probes in '%s': %s", func,
|
||||
dtrace_errmsg(dtp, dtrace_errno(dtp))));
|
||||
}
|
||||
#endif
|
||||
|
||||
nmatches++;
|
||||
}
|
||||
@ -279,7 +274,6 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
|
||||
pp->dpp_obj = obj;
|
||||
else
|
||||
pp->dpp_obj++;
|
||||
|
||||
#if defined(sun)
|
||||
if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret1", &sym,
|
||||
NULL) == 0)
|
||||
@ -305,25 +299,10 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
|
||||
else
|
||||
pp->dpp_stret[3] = 0;
|
||||
#else
|
||||
if (proc_name2sym(pp->dpp_pr, obj, ".stret1", &sym) == 0)
|
||||
pp->dpp_stret[0] = sym.st_value;
|
||||
else
|
||||
pp->dpp_stret[0] = 0;
|
||||
|
||||
if (proc_name2sym(pp->dpp_pr, obj, ".stret2", &sym) == 0)
|
||||
pp->dpp_stret[1] = sym.st_value;
|
||||
else
|
||||
pp->dpp_stret[1] = 0;
|
||||
|
||||
if (proc_name2sym(pp->dpp_pr, obj, ".stret4", &sym) == 0)
|
||||
pp->dpp_stret[2] = sym.st_value;
|
||||
else
|
||||
pp->dpp_stret[2] = 0;
|
||||
|
||||
if (proc_name2sym(pp->dpp_pr, obj, ".stret8", &sym) == 0)
|
||||
pp->dpp_stret[3] = sym.st_value;
|
||||
else
|
||||
pp->dpp_stret[3] = 0;
|
||||
pp->dpp_stret[0] = 0;
|
||||
pp->dpp_stret[1] = 0;
|
||||
pp->dpp_stret[2] = 0;
|
||||
pp->dpp_stret[3] = 0;
|
||||
#endif
|
||||
|
||||
dt_dprintf("%s stret %llx %llx %llx %llx\n", obj,
|
||||
@ -345,12 +324,8 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
|
||||
* just fail silently in the hopes that some other object will
|
||||
* contain the desired symbol.
|
||||
*/
|
||||
#if defined(sun)
|
||||
if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj,
|
||||
pp->dpp_func, &sym, NULL) != 0) {
|
||||
#else
|
||||
if (proc_name2sym(pp->dpp_pr, obj, pp->dpp_func, &sym) != 0) {
|
||||
#endif
|
||||
if (strcmp("-", pp->dpp_func) == 0) {
|
||||
sym.st_name = 0;
|
||||
sym.st_info =
|
||||
@ -390,16 +365,11 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
#if defined(sun)
|
||||
(void) Plookup_by_addr(pp->dpp_pr, sym.st_value, pp->dpp_func,
|
||||
#else
|
||||
(void) proc_addr2sym(pp->dpp_pr, sym.st_value, pp->dpp_func,
|
||||
#endif
|
||||
DTRACE_FUNCNAMELEN, &sym);
|
||||
|
||||
return (dt_pid_per_sym(pp, &sym, pp->dpp_func));
|
||||
} else {
|
||||
#ifdef DOODAD
|
||||
uint_t nmatches = pp->dpp_nmatches;
|
||||
|
||||
if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB,
|
||||
@ -415,7 +385,6 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
|
||||
BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return (0);
|
||||
@ -459,14 +428,16 @@ dt_pid_mod_filt(void *arg, const prmap_t *pmp, const char *obj)
|
||||
static const prmap_t *
|
||||
dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
|
||||
{
|
||||
#ifdef DOODAD
|
||||
char m[MAXPATHLEN];
|
||||
#if defined(sun)
|
||||
Lmid_t lmid = PR_LMID_EVERY;
|
||||
const char *obj;
|
||||
#else
|
||||
Lmid_t lmid = 0;
|
||||
#endif
|
||||
const char *obj;
|
||||
const prmap_t *pmp;
|
||||
|
||||
#ifdef DOODAD
|
||||
#if defined(sun)
|
||||
/*
|
||||
* Pick apart the link map from the library name.
|
||||
*/
|
||||
@ -487,10 +458,14 @@ dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
|
||||
} else {
|
||||
obj = pdp->dtpd_mod;
|
||||
}
|
||||
#else
|
||||
obj = pdp->dtpd_mod;
|
||||
#endif
|
||||
|
||||
if ((pmp = Plmid_to_map(P, lmid, obj)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
#if defined(sun)
|
||||
(void) Pobjname(P, pmp->pr_vaddr, m, sizeof (m));
|
||||
if ((obj = strrchr(m, '/')) == NULL)
|
||||
obj = &m[0];
|
||||
@ -498,11 +473,9 @@ dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
|
||||
obj++;
|
||||
|
||||
(void) Plmid(P, pmp->pr_vaddr, &lmid);
|
||||
#endif
|
||||
|
||||
dt_pid_objname(pdp->dtpd_mod, sizeof (pdp->dtpd_mod), lmid, obj);
|
||||
#else
|
||||
pmp = NULL;
|
||||
#endif
|
||||
|
||||
return (pmp);
|
||||
}
|
||||
@ -544,13 +517,8 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
|
||||
pp.dpp_mod = pdp->dtpd_mod;
|
||||
(void) strcpy(pdp->dtpd_mod, "a.out");
|
||||
} else if (strisglob(pp.dpp_mod) ||
|
||||
#if defined(sun)
|
||||
(aout = Pname_to_map(pp.dpp_pr, "a.out")) == NULL ||
|
||||
(pmp = Pname_to_map(pp.dpp_pr, pp.dpp_mod)) == NULL ||
|
||||
#else
|
||||
(aout = proc_name2map(pp.dpp_pr, "a.out")) == NULL ||
|
||||
(pmp = proc_name2map(pp.dpp_pr, pp.dpp_mod)) == NULL ||
|
||||
#endif
|
||||
aout->pr_vaddr != pmp->pr_vaddr) {
|
||||
return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_LIB,
|
||||
"only the a.out module is valid with the "
|
||||
@ -569,7 +537,6 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
|
||||
* to iterate over each module and compare its name against the
|
||||
* pattern. An empty module name is treated as '*'.
|
||||
*/
|
||||
#ifdef DOODAD
|
||||
if (strisglob(pp.dpp_mod)) {
|
||||
ret = Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp);
|
||||
} else {
|
||||
@ -590,7 +557,6 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
|
||||
ret = dt_pid_per_mod(&pp, pmp, obj);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@ -616,12 +582,8 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
|
||||
* run the code to instantiate these providers.
|
||||
*/
|
||||
for (i = 0; i < 2; i++) {
|
||||
#if defined(sun)
|
||||
if (Pxlookup_by_name(P, PR_LMID_EVERY, oname, syms[i], &sym,
|
||||
&sip) != 0) {
|
||||
#else
|
||||
if (proc_name2sym(P, oname, syms[i], &sym) != 0) {
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -632,13 +594,11 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
|
||||
|
||||
dt_dprintf("lookup of %s succeeded for %s\n", syms[i], mname);
|
||||
|
||||
#ifdef DOODAD
|
||||
if (Pread(P, &e_type, sizeof (e_type), pmp->pr_vaddr +
|
||||
offsetof(Elf64_Ehdr, e_type)) != sizeof (e_type)) {
|
||||
dt_dprintf("read of ELF header failed");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
dh.dofhp_dof = sym.st_value;
|
||||
dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr;
|
||||
@ -650,7 +610,7 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
|
||||
0, mname);
|
||||
#endif
|
||||
|
||||
#ifdef DOODAD
|
||||
#if defined(sun)
|
||||
if (fd == -1 &&
|
||||
(fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) {
|
||||
dt_dprintf("pr_open of helper device failed: %s\n",
|
||||
@ -663,7 +623,7 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DOODAD
|
||||
#if defined(sun)
|
||||
if (fd != -1)
|
||||
(void) pr_close(P, fd);
|
||||
#endif
|
||||
@ -679,9 +639,9 @@ dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
|
||||
int ret = 0;
|
||||
|
||||
assert(DT_MUTEX_HELD(&dpr->dpr_lock));
|
||||
|
||||
#ifdef DOODAD
|
||||
#if defined(sun)
|
||||
(void) Pupdate_maps(P);
|
||||
#endif
|
||||
if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) {
|
||||
ret = -1;
|
||||
(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT,
|
||||
@ -692,7 +652,6 @@ dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
|
||||
(int)proc_getpid(P), strerror(errno));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Put the module name in its canonical form.
|
||||
|
@ -89,10 +89,15 @@
|
||||
#include <dt_pid.h>
|
||||
#include <dt_impl.h>
|
||||
|
||||
#if !defined(sun)
|
||||
#include <sys/syscall.h>
|
||||
#include <libproc_compat.h>
|
||||
#define SYS_forksys SYS_fork
|
||||
#endif
|
||||
|
||||
#define IS_SYS_EXEC(w) (w == SYS_execve)
|
||||
#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_forksys)
|
||||
|
||||
#ifdef DOODAD
|
||||
static dt_bkpt_t *
|
||||
dt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data)
|
||||
{
|
||||
@ -114,53 +119,62 @@ dt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data)
|
||||
|
||||
return (dbp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
dt_proc_bpdestroy(dt_proc_t *dpr, int delbkpts)
|
||||
{
|
||||
#if defined(sun)
|
||||
int state = Pstate(dpr->dpr_proc);
|
||||
#else
|
||||
int state = proc_state(dpr->dpr_proc);
|
||||
#endif
|
||||
dt_bkpt_t *dbp, *nbp;
|
||||
|
||||
assert(DT_MUTEX_HELD(&dpr->dpr_lock));
|
||||
|
||||
for (dbp = dt_list_next(&dpr->dpr_bps); dbp != NULL; dbp = nbp) {
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
if (delbkpts && dbp->dbp_active &&
|
||||
state != PS_LOST && state != PS_UNDEAD) {
|
||||
(void) Pdelbkpt(dpr->dpr_proc,
|
||||
dbp->dbp_addr, dbp->dbp_instr);
|
||||
}
|
||||
#endif
|
||||
nbp = dt_list_next(dbp);
|
||||
dt_list_delete(&dpr->dpr_bps, dbp);
|
||||
dt_free(dpr->dpr_hdl, dbp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DOODAD
|
||||
static void
|
||||
dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr)
|
||||
{
|
||||
#if defined(sun)
|
||||
const lwpstatus_t *psp = &Pstatus(dpr->dpr_proc)->pr_lwp;
|
||||
#else
|
||||
unsigned long pc;
|
||||
#endif
|
||||
dt_bkpt_t *dbp;
|
||||
|
||||
assert(DT_MUTEX_HELD(&dpr->dpr_lock));
|
||||
|
||||
#if !defined(sun)
|
||||
proc_regget(dpr->dpr_proc, REG_PC, &pc);
|
||||
proc_bkptregadj(&pc);
|
||||
#endif
|
||||
|
||||
for (dbp = dt_list_next(&dpr->dpr_bps);
|
||||
dbp != NULL; dbp = dt_list_next(dbp)) {
|
||||
#if defined(sun)
|
||||
if (psp->pr_reg[R_PC] == dbp->dbp_addr)
|
||||
break;
|
||||
#else
|
||||
if (pc == dbp->dbp_addr)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dbp == NULL) {
|
||||
dt_dprintf("pid %d: spurious breakpoint wakeup for %lx\n",
|
||||
#if defined(sun)
|
||||
(int)dpr->dpr_pid, (ulong_t)psp->pr_reg[R_PC]);
|
||||
#else
|
||||
(int)dpr->dpr_pid, pc);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -170,7 +184,6 @@ dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr)
|
||||
dbp->dbp_func(dtp, dpr, dbp->dbp_data);
|
||||
(void) Pxecbkpt(dpr->dpr_proc, dbp->dbp_instr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
dt_proc_bpenable(dt_proc_t *dpr)
|
||||
@ -181,12 +194,9 @@ dt_proc_bpenable(dt_proc_t *dpr)
|
||||
|
||||
for (dbp = dt_list_next(&dpr->dpr_bps);
|
||||
dbp != NULL; dbp = dt_list_next(dbp)) {
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
if (!dbp->dbp_active && Psetbkpt(dpr->dpr_proc,
|
||||
dbp->dbp_addr, &dbp->dbp_instr) == 0)
|
||||
dbp->dbp_active = B_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
dt_dprintf("breakpoints enabled\n");
|
||||
@ -201,12 +211,9 @@ dt_proc_bpdisable(dt_proc_t *dpr)
|
||||
|
||||
for (dbp = dt_list_next(&dpr->dpr_bps);
|
||||
dbp != NULL; dbp = dt_list_next(dbp)) {
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
if (dbp->dbp_active && Pdelbkpt(dpr->dpr_proc,
|
||||
dbp->dbp_addr, dbp->dbp_instr) == 0)
|
||||
dbp->dbp_active = B_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
dt_dprintf("breakpoints disabled\n");
|
||||
@ -279,7 +286,6 @@ dt_proc_bpmain(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *fname)
|
||||
dt_proc_stop(dpr, DT_PROC_STOP_MAIN);
|
||||
}
|
||||
|
||||
#if defined(sun)
|
||||
static void
|
||||
dt_proc_rdevent(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *evname)
|
||||
{
|
||||
@ -336,7 +342,12 @@ dt_proc_rdwatch(dt_proc_t *dpr, rd_event_e event, const char *evname)
|
||||
}
|
||||
|
||||
(void) dt_proc_bpcreate(dpr, rdn.u.bptaddr,
|
||||
#if defined(sun)
|
||||
(dt_bkpt_f *)dt_proc_rdevent, (void *)evname);
|
||||
#else
|
||||
/* XXX ugly */
|
||||
(dt_bkpt_f *)dt_proc_rdevent, __DECONST(void *, evname));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -346,25 +357,34 @@ dt_proc_rdwatch(dt_proc_t *dpr, rd_event_e event, const char *evname)
|
||||
static void
|
||||
dt_proc_attach(dt_proc_t *dpr, int exec)
|
||||
{
|
||||
#if defined(sun)
|
||||
const pstatus_t *psp = Pstatus(dpr->dpr_proc);
|
||||
#endif
|
||||
rd_err_e err;
|
||||
GElf_Sym sym;
|
||||
|
||||
assert(DT_MUTEX_HELD(&dpr->dpr_lock));
|
||||
|
||||
if (exec) {
|
||||
#if defined(sun)
|
||||
if (psp->pr_lwp.pr_errno != 0)
|
||||
return; /* exec failed: nothing needs to be done */
|
||||
#endif
|
||||
|
||||
dt_proc_bpdestroy(dpr, B_FALSE);
|
||||
#if defined(sun)
|
||||
Preset_maps(dpr->dpr_proc);
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((dpr->dpr_rtld = Prd_agent(dpr->dpr_proc)) != NULL &&
|
||||
(err = rd_event_enable(dpr->dpr_rtld, B_TRUE)) == RD_OK) {
|
||||
#if defined(sun)
|
||||
dt_proc_rdwatch(dpr, RD_PREINIT, "RD_PREINIT");
|
||||
#endif
|
||||
dt_proc_rdwatch(dpr, RD_POSTINIT, "RD_POSTINIT");
|
||||
#if defined(sun)
|
||||
dt_proc_rdwatch(dpr, RD_DLACTIVITY, "RD_DLACTIVITY");
|
||||
#endif
|
||||
} else {
|
||||
dt_dprintf("pid %d: failed to enable rtld events: %s\n",
|
||||
(int)dpr->dpr_pid, dpr->dpr_rtld ? rd_errstr(err) :
|
||||
@ -406,6 +426,8 @@ dt_proc_attach(dt_proc_t *dpr, int exec)
|
||||
static void
|
||||
dt_proc_waitrun(dt_proc_t *dpr)
|
||||
{
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
struct ps_prochandle *P = dpr->dpr_proc;
|
||||
const lwpstatus_t *psp = &Pstatus(P)->pr_lwp;
|
||||
|
||||
@ -455,8 +477,8 @@ dt_proc_waitrun(dt_proc_t *dpr)
|
||||
}
|
||||
|
||||
(void) pthread_mutex_lock(&dpr->dpr_lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct dt_proc_control_data {
|
||||
dtrace_hdl_t *dpcd_hdl; /* DTrace handle */
|
||||
@ -533,13 +555,18 @@ dt_proc_control(void *arg)
|
||||
(void) Psysexit(P, SYS_forksys, B_TRUE);
|
||||
|
||||
Psync(P); /* enable all /proc changes */
|
||||
#endif
|
||||
dt_proc_attach(dpr, B_FALSE); /* enable rtld breakpoints */
|
||||
|
||||
/*
|
||||
* If PR_KLC is set, we created the process; otherwise we grabbed it.
|
||||
* Check for an appropriate stop request and wait for dt_proc_continue.
|
||||
*/
|
||||
#if defined(sun)
|
||||
if (Pstatus(P)->pr_flags & PR_KLC)
|
||||
#else
|
||||
if (proc_getflags(P) & PR_KLC)
|
||||
#endif
|
||||
dt_proc_stop(dpr, DT_PROC_STOP_CREATE);
|
||||
else
|
||||
dt_proc_stop(dpr, DT_PROC_STOP_GRAB);
|
||||
@ -548,20 +575,6 @@ dt_proc_control(void *arg)
|
||||
dt_dprintf("pid %d: failed to set running: %s\n",
|
||||
(int)dpr->dpr_pid, strerror(errno));
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* If PR_KLC is set, we created the process; otherwise we grabbed it.
|
||||
* Check for an appropriate stop request and wait for dt_proc_continue.
|
||||
*/
|
||||
if (proc_getflags(P) & PR_KLC)
|
||||
dt_proc_stop(dpr, DT_PROC_STOP_CREATE);
|
||||
else
|
||||
dt_proc_stop(dpr, DT_PROC_STOP_GRAB);
|
||||
|
||||
if (proc_continue(P) != 0)
|
||||
dt_dprintf("pid %d: failed to set running: %s\n",
|
||||
(int)dpr->dpr_pid, strerror(errno));
|
||||
#endif
|
||||
|
||||
(void) pthread_mutex_unlock(&dpr->dpr_lock);
|
||||
|
||||
@ -575,14 +588,16 @@ dt_proc_control(void *arg)
|
||||
* Pwait() (which will return immediately) and do our processing.
|
||||
*/
|
||||
while (!dpr->dpr_quit) {
|
||||
#if defined(sun)
|
||||
const lwpstatus_t *psp;
|
||||
|
||||
#if defined(sun)
|
||||
if (write(pfd, &wstop, sizeof (wstop)) == -1 && errno == EINTR)
|
||||
continue; /* check dpr_quit and continue waiting */
|
||||
#else
|
||||
/* Wait for the process to report status. */
|
||||
proc_wstatus(P);
|
||||
if (errno == EINTR)
|
||||
continue; /* check dpr_quit and continue waiting */
|
||||
#endif
|
||||
|
||||
(void) pthread_mutex_lock(&dpr->dpr_lock);
|
||||
@ -595,14 +610,13 @@ dt_proc_control(void *arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(sun)
|
||||
switch (Pstate(P)) {
|
||||
#else
|
||||
switch (proc_state(P)) {
|
||||
#endif
|
||||
case PS_STOP:
|
||||
#ifdef DOODAD
|
||||
#if defined(sun)
|
||||
psp = &Pstatus(P)->pr_lwp;
|
||||
#else
|
||||
psp = proc_getlwpstatus(P);
|
||||
#endif
|
||||
|
||||
dt_dprintf("pid %d: proc stopped showing %d/%d\n",
|
||||
pid, psp->pr_why, psp->pr_what);
|
||||
@ -644,7 +658,6 @@ dt_proc_control(void *arg)
|
||||
else if (psp->pr_why == PR_SYSEXIT &&
|
||||
IS_SYS_EXEC(psp->pr_what))
|
||||
dt_proc_attach(dpr, B_TRUE);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PS_LOST:
|
||||
@ -667,12 +680,10 @@ dt_proc_control(void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(sun)
|
||||
if (Pstate(P) != PS_UNDEAD && Psetrun(P, 0, 0) == -1) {
|
||||
dt_dprintf("pid %d: failed to set running: %s\n",
|
||||
(int)dpr->dpr_pid, strerror(errno));
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) pthread_mutex_unlock(&dpr->dpr_lock);
|
||||
}
|
||||
@ -712,11 +723,7 @@ dt_proc_error(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *format, ...)
|
||||
va_end(ap);
|
||||
|
||||
if (dpr->dpr_proc != NULL)
|
||||
#if defined(sun)
|
||||
Prelease(dpr->dpr_proc, 0);
|
||||
#else
|
||||
proc_detach(dpr->dpr_proc, 0);
|
||||
#endif
|
||||
|
||||
dt_free(dtp, dpr);
|
||||
(void) dt_set_errno(dtp, EDT_COMPILER);
|
||||
@ -804,7 +811,7 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P)
|
||||
#if defined(sun)
|
||||
(void) _lwp_kill(dpr->dpr_tid, SIGCANCEL);
|
||||
#else
|
||||
(void) pthread_kill(dpr->dpr_tid, SIGUSR1);
|
||||
pthread_kill(dpr->dpr_tid, SIGUSR1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -853,11 +860,7 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P)
|
||||
}
|
||||
|
||||
dt_list_delete(&dph->dph_lrulist, dpr);
|
||||
#if defined(sun)
|
||||
Prelease(dpr->dpr_proc, rflag);
|
||||
#else
|
||||
proc_detach(dpr->dpr_proc, rflag);
|
||||
#endif
|
||||
dt_free(dtp, dpr);
|
||||
}
|
||||
|
||||
@ -912,18 +915,15 @@ dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop)
|
||||
#if defined(sun)
|
||||
const psinfo_t *prp = Ppsinfo(dpr->dpr_proc);
|
||||
int stat = prp ? prp->pr_wstat : 0;
|
||||
#endif
|
||||
int pid = dpr->dpr_pid;
|
||||
|
||||
#if defined(sun)
|
||||
if (Pstate(dpr->dpr_proc) == PS_LOST) {
|
||||
#else
|
||||
if (proc_state(dpr->dpr_proc) == PS_LOST) {
|
||||
int stat = proc_getwstat(dpr->dpr_proc);
|
||||
int pid = proc_getpid(dpr->dpr_proc);
|
||||
#endif
|
||||
if (proc_state(dpr->dpr_proc) == PS_LOST) {
|
||||
(void) dt_proc_error(dpr->dpr_hdl, dpr,
|
||||
"failed to control pid %d: process exec'd "
|
||||
"set-id or unobservable program\n", pid);
|
||||
#if defined(sun)
|
||||
} else if (WIFSIGNALED(stat)) {
|
||||
(void) dt_proc_error(dpr->dpr_hdl, dpr,
|
||||
"failed to control pid %d: process died "
|
||||
@ -932,7 +932,6 @@ dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop)
|
||||
(void) dt_proc_error(dpr->dpr_hdl, dpr,
|
||||
"failed to control pid %d: process exited "
|
||||
"with status %d\n", pid, WEXITSTATUS(stat));
|
||||
#endif
|
||||
}
|
||||
|
||||
err = ESRCH; /* cause grab() or create() to fail */
|
||||
@ -965,30 +964,25 @@ dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv,
|
||||
|
||||
#if defined(sun)
|
||||
if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) {
|
||||
#else
|
||||
if ((err = proc_create(file, argv, pcf, child_arg,
|
||||
&dpr->dpr_proc)) != 0) {
|
||||
#endif
|
||||
return (dt_proc_error(dtp, dpr,
|
||||
"failed to execute %s: %s\n", file, Pcreate_error(err)));
|
||||
}
|
||||
|
||||
dpr->dpr_hdl = dtp;
|
||||
#if defined(sun)
|
||||
dpr->dpr_pid = Pstatus(dpr->dpr_proc)->pr_pid;
|
||||
|
||||
(void) Punsetflags(dpr->dpr_proc, PR_RLC);
|
||||
(void) Psetflags(dpr->dpr_proc, PR_KLC);
|
||||
#else
|
||||
(void) proc_clearflags(dpr->dpr_proc, PR_RLC);
|
||||
(void) proc_setflags(dpr->dpr_proc, PR_KLC);
|
||||
if ((err = proc_create(file, argv, pcf, child_arg, &dpr->dpr_proc)) != 0)
|
||||
return (dt_proc_error(dtp, dpr,
|
||||
"failed to execute %s: %s\n", file, strerror(err)));
|
||||
dpr->dpr_hdl = dtp;
|
||||
dpr->dpr_pid = proc_getpid(dpr->dpr_proc);
|
||||
#endif
|
||||
|
||||
#if defined(sun)
|
||||
(void) Punsetflags(dpr->dpr_proc, PR_RLC);
|
||||
(void) Psetflags(dpr->dpr_proc, PR_KLC);
|
||||
|
||||
if (dt_proc_create_thread(dtp, dpr, dtp->dt_prcmode) != 0)
|
||||
#else
|
||||
if (dt_proc_create_thread(dtp, dpr, DT_PROC_STOP_IDLE) != 0)
|
||||
#endif
|
||||
return (NULL); /* dt_proc_error() has been called for us */
|
||||
|
||||
dpr->dpr_hash = dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)];
|
||||
@ -1046,25 +1040,18 @@ dt_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags, int nomonitor)
|
||||
|
||||
#if defined(sun)
|
||||
if ((dpr->dpr_proc = Pgrab(pid, flags, &err)) == NULL) {
|
||||
#else
|
||||
if ((err = proc_attach(pid, flags, &dpr->dpr_proc)) != 0) {
|
||||
#endif
|
||||
return (dt_proc_error(dtp, dpr,
|
||||
"failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err)));
|
||||
}
|
||||
#else
|
||||
if ((err = proc_attach(pid, flags, &dpr->dpr_proc)) != 0)
|
||||
return (dt_proc_error(dtp, dpr,
|
||||
"failed to grab pid %d: %s\n", (int) pid, strerror(err)));
|
||||
#endif
|
||||
|
||||
dpr->dpr_hdl = dtp;
|
||||
dpr->dpr_pid = pid;
|
||||
|
||||
#if defined(sun)
|
||||
(void) Punsetflags(dpr->dpr_proc, PR_KLC);
|
||||
(void) Psetflags(dpr->dpr_proc, PR_RLC);
|
||||
#else
|
||||
(void) proc_clearflags(dpr->dpr_proc, PR_KLC);
|
||||
(void) proc_setflags(dpr->dpr_proc, PR_RLC);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we are attempting to grab the process without a monitor
|
||||
@ -1185,12 +1172,13 @@ dtrace_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv,
|
||||
dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target");
|
||||
struct ps_prochandle *P = dt_proc_create(dtp, file, argv, pcf, child_arg);
|
||||
|
||||
if (P != NULL && idp != NULL && idp->di_id == 0)
|
||||
if (P != NULL && idp != NULL && idp->di_id == 0) {
|
||||
#if defined(sun)
|
||||
idp->di_id = Pstatus(P)->pr_pid; /* $target = created pid */
|
||||
#else
|
||||
idp->di_id = proc_getpid(P); /* $target = created pid */
|
||||
#endif
|
||||
}
|
||||
|
||||
return (P);
|
||||
}
|
||||
|
@ -44,9 +44,7 @@ typedef struct dt_proc {
|
||||
dtrace_hdl_t *dpr_hdl; /* back pointer to libdtrace handle */
|
||||
struct ps_prochandle *dpr_proc; /* proc handle for libproc calls */
|
||||
char dpr_errmsg[BUFSIZ]; /* error message */
|
||||
#if defined(sun)
|
||||
rd_agent_t *dpr_rtld; /* rtld handle for librtld_db calls */
|
||||
#endif
|
||||
pthread_mutex_t dpr_lock; /* lock for manipulating dpr_hdl */
|
||||
pthread_cond_t dpr_cv; /* cond for dpr_stop/quit/done */
|
||||
pid_t dpr_pid; /* pid of process */
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#include <sys/sysctl.h>
|
||||
#include <libproc_compat.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <libgen.h>
|
||||
@ -963,13 +964,8 @@ dtrace_uaddr2str(dtrace_hdl_t *dtp, pid_t pid,
|
||||
|
||||
dt_proc_lock(dtp, P);
|
||||
|
||||
#if defined(sun)
|
||||
if (Plookup_by_addr(P, addr, name, sizeof (name), &sym) == 0) {
|
||||
(void) Pobjname(P, addr, objname, sizeof (objname));
|
||||
#else
|
||||
if (proc_addr2sym(P, addr, name, sizeof (name), &sym) == 0) {
|
||||
(void) proc_objname(P, addr, objname, sizeof (objname));
|
||||
#endif
|
||||
|
||||
obj = dt_basename(objname);
|
||||
|
||||
@ -979,11 +975,7 @@ dtrace_uaddr2str(dtrace_hdl_t *dtp, pid_t pid,
|
||||
} else {
|
||||
(void) snprintf(c, sizeof (c), "%s`%s", obj, name);
|
||||
}
|
||||
#if defined(sun)
|
||||
} else if (Pobjname(P, addr, objname, sizeof (objname)) != 0) {
|
||||
#else
|
||||
} else if (proc_objname(P, addr, objname, sizeof (objname)) != 0) {
|
||||
#endif
|
||||
(void) snprintf(c, sizeof (c), "%s`0x%llx",
|
||||
dt_basename(objname), addr);
|
||||
} else {
|
||||
|
@ -34,6 +34,9 @@
|
||||
#include <stdio.h>
|
||||
#include <gelf.h>
|
||||
#include <libproc.h>
|
||||
#if !defined(sun)
|
||||
#include <rtld_db.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -35,6 +35,12 @@
|
||||
|
||||
#include <dis_tables.h>
|
||||
|
||||
#if !defined(sun)
|
||||
#define PR_MODEL_ILP32 1
|
||||
#define PR_MODEL_LP64 2
|
||||
#include <libproc_compat.h>
|
||||
#endif
|
||||
|
||||
#define DT_POPL_EBP 0x5d
|
||||
#define DT_RET 0xc3
|
||||
#define DT_RET16 0xc2
|
||||
@ -78,8 +84,17 @@ dt_pid_has_jump_table(struct ps_prochandle *P, dtrace_hdl_t *dtp,
|
||||
{
|
||||
ulong_t i;
|
||||
int size;
|
||||
#if defined(sun)
|
||||
pid_t pid = Pstatus(P)->pr_pid;
|
||||
char dmodel = Pstatus(P)->pr_dmodel;
|
||||
#else
|
||||
pid_t pid = proc_getpid(P);
|
||||
#if __i386__
|
||||
char dmodel = PR_MODEL_ILP32;
|
||||
#elif __amd64__
|
||||
char dmodel = PR_MODEL_LP64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Take a pass through the function looking for a register-dependant
|
||||
@ -98,6 +113,7 @@ dt_pid_has_jump_table(struct ps_prochandle *P, dtrace_hdl_t *dtp,
|
||||
return (1);
|
||||
}
|
||||
|
||||
#ifdef notyet
|
||||
/*
|
||||
* Register-dependant jmp instructions start with a 0xff byte
|
||||
* and have the modrm.reg field set to 4. They can have an
|
||||
@ -110,6 +126,7 @@ dt_pid_has_jump_table(struct ps_prochandle *P, dtrace_hdl_t *dtp,
|
||||
ftp->ftps_func, i);
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return (0);
|
||||
@ -123,8 +140,17 @@ dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
|
||||
uint8_t *text;
|
||||
ulong_t i, end;
|
||||
int size;
|
||||
#if defined(sun)
|
||||
pid_t pid = Pstatus(P)->pr_pid;
|
||||
char dmodel = Pstatus(P)->pr_dmodel;
|
||||
#else
|
||||
pid_t pid = proc_getpid(P);
|
||||
#if __i386__
|
||||
char dmodel = PR_MODEL_ILP32;
|
||||
#elif __amd64__
|
||||
char dmodel = PR_MODEL_LP64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We allocate a few extra bytes at the end so we don't have to check
|
||||
@ -275,8 +301,17 @@ dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
|
||||
uint8_t *text;
|
||||
ulong_t i;
|
||||
int size;
|
||||
#if defined(sun)
|
||||
pid_t pid = Pstatus(P)->pr_pid;
|
||||
char dmodel = Pstatus(P)->pr_dmodel;
|
||||
#else
|
||||
pid_t pid = proc_getpid(P);
|
||||
#if __i386__
|
||||
char dmodel = PR_MODEL_ILP32;
|
||||
#elif __amd64__
|
||||
char dmodel = PR_MODEL_LP64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ((text = malloc(symp->st_size)) == NULL) {
|
||||
dt_dprintf("mr sparkle: malloc() failed\n");
|
||||
@ -349,8 +384,17 @@ dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
|
||||
uint8_t *text;
|
||||
int size;
|
||||
ulong_t i, end = symp->st_size;
|
||||
#if defined(sun)
|
||||
pid_t pid = Pstatus(P)->pr_pid;
|
||||
char dmodel = Pstatus(P)->pr_dmodel;
|
||||
#else
|
||||
pid_t pid = proc_getpid(P);
|
||||
#if __i386__
|
||||
char dmodel = PR_MODEL_ILP32;
|
||||
#elif __amd64__
|
||||
char dmodel = PR_MODEL_LP64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ftp->ftps_type = DTFTP_OFFSETS;
|
||||
ftp->ftps_pc = (uintptr_t)symp->st_value;
|
||||
|
@ -18,6 +18,7 @@ SRCS= dt_aggregate.c \
|
||||
dt_grammar.y \
|
||||
dt_handle.c \
|
||||
dt_ident.c \
|
||||
dt_isadep.c \
|
||||
dt_inttab.c \
|
||||
dt_lex.l \
|
||||
dt_link.c \
|
||||
@ -41,7 +42,8 @@ SRCS= dt_aggregate.c \
|
||||
dt_subr.c \
|
||||
dt_work.c \
|
||||
dt_xlator.c \
|
||||
gmatch.c
|
||||
gmatch.c \
|
||||
dis_tables.c
|
||||
|
||||
DSRCS= errno.d \
|
||||
psinfo.d \
|
||||
@ -50,7 +52,8 @@ DSRCS= errno.d \
|
||||
|
||||
WARNS?= 1
|
||||
|
||||
CFLAGS+= -I${.OBJDIR} \
|
||||
CFLAGS+= -I${.OBJDIR} -I${.CURDIR} \
|
||||
-I${.CURDIR}/../../../sys/cddl/dev/dtrace/${MACHINE_ARCH} \
|
||||
-I${.CURDIR}/../../../sys/cddl/compat/opensolaris \
|
||||
-I${.CURDIR}/../../../cddl/compat/opensolaris/include \
|
||||
-I${OPENSOLARIS_USR_DISTDIR}/head \
|
||||
@ -61,14 +64,21 @@ CFLAGS+= -I${.OBJDIR} \
|
||||
#CFLAGS+= -DYYDEBUG
|
||||
|
||||
.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64"
|
||||
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel
|
||||
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel -DDIS_MEM
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/i386
|
||||
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/${MACHINE_ARCH}
|
||||
.elif ${MACHINE_ARCH} == "sparc64"
|
||||
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/sparc
|
||||
.else
|
||||
# temporary hack
|
||||
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64"
|
||||
DSRCS+= regs_x86.d
|
||||
.endif
|
||||
|
||||
LFLAGS+=-l
|
||||
|
||||
YFLAGS+=-d
|
||||
|
62
cddl/lib/libdtrace/libproc_compat.h
Normal file
62
cddl/lib/libdtrace/libproc_compat.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2010 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by Rui Paulo under sponsorship from the
|
||||
* FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compatibility functions between Solaris libproc and FreeBSD libproc.
|
||||
* Functions sorted alphabetically.
|
||||
*/
|
||||
#define PR_LMID_EVERY 0
|
||||
#define Psetrun(p, a1, a2) proc_continue((p))
|
||||
#define Pxlookup_by_addr(p, a, n, s, sym, i) \
|
||||
proc_addr2sym(p, a, n, s, sym)
|
||||
#define Pxlookup_by_name(p, l, s1, s2, sym, a) \
|
||||
proc_name2sym((p), (s1), (s2), (sym))
|
||||
#define Paddr_to_map proc_addr2map
|
||||
#define Pcreate_error strerror
|
||||
#define Pdelbkpt proc_bkptdel
|
||||
#define Pgrab_error strerror
|
||||
#define Plmid_to_map(p, l, o) proc_obj2map((p), (o))
|
||||
#define Plookup_by_addr proc_addr2sym
|
||||
#define Pname_to_map proc_name2map
|
||||
#define Pobject_iter proc_iter_objs
|
||||
#define Pobjname proc_objname
|
||||
#define Pread proc_read
|
||||
#define Prd_agent proc_rdagent
|
||||
#define Prelease proc_detach
|
||||
#define Psetbkpt proc_bkptset
|
||||
#define Psetflags proc_setflags
|
||||
#define Pstate proc_state
|
||||
#define Pstate proc_state
|
||||
#define Psymbol_iter_by_addr proc_iter_symbyaddr
|
||||
#define Punsetflags proc_clearflags
|
||||
#define Pupdate_maps(p) do { } while (0)
|
||||
#define Pupdate_syms proc_updatesyms
|
||||
#define Pxecbkpt proc_bkptexec
|
121
cddl/lib/libdtrace/regs_x86.d
Normal file
121
cddl/lib/libdtrace/regs_x86.d
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*
|
||||
* Portions Copyright 2009 Stacey Son sson@FreeBSD.org
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/*
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "@(#)regs.d.in 1.1 04/09/28 SMI"
|
||||
|
||||
inline int R_GS = 0;
|
||||
#pragma D binding "1.0" R_GS
|
||||
inline int R_FS = 1;
|
||||
#pragma D binding "1.0" R_FS
|
||||
inline int R_ES = 2;
|
||||
#pragma D binding "1.0" R_ES
|
||||
inline int R_DS = 3;
|
||||
#pragma D binding "1.0" R_DS
|
||||
|
||||
inline int R_EDI = 4;
|
||||
#pragma D binding "1.0" R_EDI
|
||||
inline int R_ESI = 5;
|
||||
#pragma D binding "1.0" R_ESI
|
||||
inline int R_EBP = 6;
|
||||
#pragma D binding "1.0" R_EBP
|
||||
inline int R_ESP = 7;
|
||||
#pragma D binding "1.0" R_ESP
|
||||
inline int R_EBX = 8;
|
||||
#pragma D binding "1.0" R_EBX
|
||||
inline int R_EDX = 9;
|
||||
#pragma D binding "1.0" R_EDX
|
||||
inline int R_ECX = 10;
|
||||
#pragma D binding "1.0" R_ECX
|
||||
inline int R_EAX = 11;
|
||||
#pragma D binding "1.0" R_EAX
|
||||
|
||||
inline int R_TRAPNO = 12;
|
||||
#pragma D binding "1.0" R_TRAPNO
|
||||
inline int R_ERR = 13;
|
||||
#pragma D binding "1.0" R_ERR
|
||||
inline int R_EIP = 14;
|
||||
#pragma D binding "1.0" R_EIP
|
||||
inline int R_CS = 15;
|
||||
#pragma D binding "1.0" R_CS
|
||||
inline int R_EFL = 16;
|
||||
#pragma D binding "1.0" R_EFL
|
||||
inline int R_UESP = 17;
|
||||
#pragma D binding "1.0" R_UESP
|
||||
inline int R_SS = 18;
|
||||
#pragma D binding "1.0" R_SS
|
||||
|
||||
inline int R_PC = R_EIP;
|
||||
#pragma D binding "1.0" R_PC
|
||||
inline int R_SP = R_UESP;
|
||||
#pragma D binding "1.0" R_SP
|
||||
inline int R_PS = R_EFL;
|
||||
#pragma D binding "1.0" R_PS
|
||||
inline int R_R0 = R_EAX;
|
||||
#pragma D binding "1.0" R_R0
|
||||
inline int R_R1 = R_EBX;
|
||||
#pragma D binding "1.0" R_R1
|
||||
|
||||
inline int R_RSP = 18 + 1 + 20;
|
||||
#pragma D binding "1.0" R_RSP
|
||||
inline int R_RFL = 18 + 1 + 19;
|
||||
#pragma D binding "1.0" R_RFL
|
||||
inline int R_RIP = 18 + 1 + 17;
|
||||
#pragma D binding "1.0" R_RIP
|
||||
inline int R_RAX = 18 + 1 + 14;
|
||||
#pragma D binding "1.0" R_RAX
|
||||
inline int R_RCX = 18 + 1 + 13;
|
||||
#pragma D binding "1.0" R_RCX
|
||||
inline int R_RDX = 18 + 1 + 12;
|
||||
#pragma D binding "1.0" R_RDX
|
||||
inline int R_RBX = 18 + 1 + 11;
|
||||
#pragma D binding "1.0" R_RBX
|
||||
inline int R_RBP = 18 + 1 + 10;
|
||||
#pragma D binding "1.0" R_RBP
|
||||
inline int R_RSI = 18 + 1 + 9;
|
||||
#pragma D binding "1.0" R_RSI
|
||||
inline int R_RDI = 18 + 1 + 8;
|
||||
#pragma D binding "1.0" R_RDI
|
||||
inline int R_R8 = 18 + 1 + 7;
|
||||
#pragma D binding "1.0" R_R8
|
||||
inline int R_R9 = 18 + 1 + 6;
|
||||
#pragma D binding "1.0" R_R9
|
||||
inline int R_R10 = 18 + 1 + 5;
|
||||
#pragma D binding "1.0" R_R10
|
||||
inline int R_R11 = 18 + 1 + 4;
|
||||
#pragma D binding "1.0" R_R11
|
||||
inline int R_R12 = 18 + 1 + 3;
|
||||
#pragma D binding "1.0" R_R12
|
||||
inline int R_R13 = 18 + 1 + 2;
|
||||
#pragma D binding "1.0" R_R13
|
||||
inline int R_R14 = 18 + 1 + 1;
|
||||
#pragma D binding "1.0" R_R14
|
||||
inline int R_R15 = 18 + 1 + 0;
|
||||
#pragma D binding "1.0" R_R15
|
||||
|
Loading…
Reference in New Issue
Block a user