There is a lot of commented out code here which applies to future work

for userland tracing.

For now we need the basic functions to be in place so that DTrace can
be used for kernel tracing.
This commit is contained in:
John Birrell 2008-04-26 04:56:46 +00:00
parent 84098f48c6
commit 5ec5669275

View File

@ -32,7 +32,9 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <ctype.h> #include <ctype.h>
#if defined(sun)
#include <alloca.h> #include <alloca.h>
#endif
#include <libgen.h> #include <libgen.h>
#include <stddef.h> #include <stddef.h>
@ -66,10 +68,14 @@ typedef struct dt_pid_probe {
static void static void
dt_pid_objname(char *buf, size_t len, Lmid_t lmid, const char *obj) dt_pid_objname(char *buf, size_t len, Lmid_t lmid, const char *obj)
{ {
#if defined(sun)
if (lmid == LM_ID_BASE) if (lmid == LM_ID_BASE)
(void) strncpy(buf, obj, len); (void) strncpy(buf, obj, len);
else else
(void) snprintf(buf, len, "LM%lx`%s", lmid, obj); (void) snprintf(buf, len, "LM%lx`%s", lmid, obj);
#else
(void) strncpy(buf, obj, len);
#endif
} }
static int static int
@ -114,7 +120,11 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
int isdash = strcmp("-", func) == 0; int isdash = strcmp("-", func) == 0;
pid_t pid; pid_t pid;
#if defined(sun)
pid = Pstatus(pp->dpp_pr)->pr_pid; pid = Pstatus(pp->dpp_pr)->pr_pid;
#else
pid = proc_getpid(pp->dpp_pr);
#endif
dt_dprintf("creating probe pid%d:%s:%s:%s\n", (int)pid, pp->dpp_obj, dt_dprintf("creating probe pid%d:%s:%s:%s\n", (int)pid, pp->dpp_obj,
func, pp->dpp_name); func, pp->dpp_name);
@ -134,6 +144,7 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
pp->dpp_obj); pp->dpp_obj);
if (!isdash && gmatch("return", pp->dpp_name)) { if (!isdash && gmatch("return", pp->dpp_name)) {
#ifdef DOODAD
if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp, if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp,
pp->dpp_stret) < 0) { pp->dpp_stret) < 0) {
return (dt_pid_error(dtp, pcb, dpr, ftp, return (dt_pid_error(dtp, pcb, dpr, ftp,
@ -141,17 +152,20 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
"for '%s': %s", func, "for '%s': %s", func,
dtrace_errmsg(dtp, dtrace_errno(dtp)))); dtrace_errmsg(dtp, dtrace_errno(dtp))));
} }
#endif
nmatches++; nmatches++;
} }
if (!isdash && gmatch("entry", pp->dpp_name)) { if (!isdash && gmatch("entry", pp->dpp_name)) {
#ifdef DOODAD
if (dt_pid_create_entry_probe(pp->dpp_pr, dtp, ftp, symp) < 0) { if (dt_pid_create_entry_probe(pp->dpp_pr, dtp, ftp, symp) < 0) {
return (dt_pid_error(dtp, pcb, dpr, ftp, return (dt_pid_error(dtp, pcb, dpr, ftp,
D_PROC_CREATEFAIL, "failed to create entry probe " D_PROC_CREATEFAIL, "failed to create entry probe "
"for '%s': %s", func, "for '%s': %s", func,
dtrace_errmsg(dtp, dtrace_errno(dtp)))); dtrace_errmsg(dtp, dtrace_errno(dtp))));
} }
#endif
nmatches++; nmatches++;
} }
@ -170,8 +184,10 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
(u_longlong_t)off, func)); (u_longlong_t)off, func));
} }
#ifdef DOODAD
err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp, err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp,
symp, off); symp, off);
#endif
if (err == DT_PROC_ERR) { if (err == DT_PROC_ERR) {
return (dt_pid_error(dtp, pcb, dpr, ftp, return (dt_pid_error(dtp, pcb, dpr, ftp,
@ -189,6 +205,7 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
nmatches++; nmatches++;
} else if (glob && !isdash) { } else if (glob && !isdash) {
#ifdef DOODAD
if (dt_pid_create_glob_offset_probes(pp->dpp_pr, if (dt_pid_create_glob_offset_probes(pp->dpp_pr,
pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) { pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) {
return (dt_pid_error(dtp, pcb, dpr, ftp, return (dt_pid_error(dtp, pcb, dpr, ftp,
@ -196,6 +213,7 @@ 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, "failed to create offset probes in '%s': %s", func,
dtrace_errmsg(dtp, dtrace_errno(dtp)))); dtrace_errmsg(dtp, dtrace_errno(dtp))));
} }
#endif
nmatches++; nmatches++;
} }
@ -254,13 +272,17 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
if (obj == NULL) if (obj == NULL)
return (0); return (0);
#if defined(sun)
(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
#endif
if ((pp->dpp_obj = strrchr(obj, '/')) == NULL) if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)
pp->dpp_obj = obj; pp->dpp_obj = obj;
else else
pp->dpp_obj++; pp->dpp_obj++;
#if defined(sun)
if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret1", &sym, if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret1", &sym,
NULL) == 0) NULL) == 0)
pp->dpp_stret[0] = sym.st_value; pp->dpp_stret[0] = sym.st_value;
@ -284,6 +306,27 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
pp->dpp_stret[3] = sym.st_value; pp->dpp_stret[3] = sym.st_value;
else else
pp->dpp_stret[3] = 0; 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;
#endif
dt_dprintf("%s stret %llx %llx %llx %llx\n", obj, dt_dprintf("%s stret %llx %llx %llx %llx\n", obj,
(u_longlong_t)pp->dpp_stret[0], (u_longlong_t)pp->dpp_stret[1], (u_longlong_t)pp->dpp_stret[0], (u_longlong_t)pp->dpp_stret[1],
@ -304,16 +347,24 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
* just fail silently in the hopes that some other object will * just fail silently in the hopes that some other object will
* contain the desired symbol. * contain the desired symbol.
*/ */
#if defined(sun)
if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj,
pp->dpp_func, &sym, NULL) != 0) { 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) { if (strcmp("-", pp->dpp_func) == 0) {
sym.st_name = 0; sym.st_name = 0;
sym.st_info = sym.st_info =
GELF_ST_INFO(STB_LOCAL, STT_FUNC); GELF_ST_INFO(STB_LOCAL, STT_FUNC);
sym.st_other = 0; sym.st_other = 0;
sym.st_value = 0; sym.st_value = 0;
#if defined(sun)
sym.st_size = Pstatus(pp->dpp_pr)->pr_dmodel == sym.st_size = Pstatus(pp->dpp_pr)->pr_dmodel ==
PR_MODEL_ILP32 ? -1U : -1ULL; PR_MODEL_ILP32 ? -1U : -1ULL;
#else
sym.st_size = ~((Elf64_Xword) 0);
#endif
} else if (!strisglob(pp->dpp_mod)) { } else if (!strisglob(pp->dpp_mod)) {
return (dt_pid_error(dtp, pcb, dpr, NULL, return (dt_pid_error(dtp, pcb, dpr, NULL,
@ -336,14 +387,21 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
* We don't instrument PLTs -- they're dynamically rewritten, * We don't instrument PLTs -- they're dynamically rewritten,
* and, so, inherently dicey to instrument. * and, so, inherently dicey to instrument.
*/ */
#ifdef DOODAD
if (Ppltdest(pp->dpp_pr, sym.st_value) != NULL) if (Ppltdest(pp->dpp_pr, sym.st_value) != NULL)
return (0); return (0);
#endif
#if defined(sun)
(void) Plookup_by_addr(pp->dpp_pr, sym.st_value, pp->dpp_func, (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); DTRACE_FUNCNAMELEN, &sym);
return (dt_pid_per_sym(pp, &sym, pp->dpp_func)); return (dt_pid_per_sym(pp, &sym, pp->dpp_func));
} else { } else {
#ifdef DOODAD
uint_t nmatches = pp->dpp_nmatches; uint_t nmatches = pp->dpp_nmatches;
if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB, if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB,
@ -359,6 +417,7 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1) BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)
return (1); return (1);
} }
#endif
} }
return (0); return (0);
@ -373,7 +432,11 @@ dt_pid_mod_filt(void *arg, const prmap_t *pmp, const char *obj)
if (gmatch(obj, pp->dpp_mod)) if (gmatch(obj, pp->dpp_mod))
return (dt_pid_per_mod(pp, pmp, obj)); return (dt_pid_per_mod(pp, pmp, obj));
#if defined(sun)
(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
#else
pp->dpp_lmid = 0;
#endif
if ((pp->dpp_obj = strrchr(obj, '/')) == NULL) if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)
pp->dpp_obj = obj; pp->dpp_obj = obj;
@ -391,11 +454,14 @@ dt_pid_mod_filt(void *arg, const prmap_t *pmp, const char *obj)
static const prmap_t * static const prmap_t *
dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P) dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
{ {
#ifdef DOODAD
char m[MAXPATHLEN]; char m[MAXPATHLEN];
Lmid_t lmid = PR_LMID_EVERY; Lmid_t lmid = PR_LMID_EVERY;
const char *obj; const char *obj;
#endif
const prmap_t *pmp; const prmap_t *pmp;
#ifdef DOODAD
/* /*
* Pick apart the link map from the library name. * Pick apart the link map from the library name.
*/ */
@ -427,7 +493,11 @@ dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
obj++; obj++;
(void) Plmid(P, pmp->pr_vaddr, &lmid); (void) Plmid(P, pmp->pr_vaddr, &lmid);
dt_pid_objname(pdp->dtpd_mod, sizeof (pdp->dtpd_mod), lmid, obj); dt_pid_objname(pdp->dtpd_mod, sizeof (pdp->dtpd_mod), lmid, obj);
#else
pmp = NULL;
#endif
return (pmp); return (pmp);
} }
@ -445,6 +515,7 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
pp.dpp_pr = dpr->dpr_proc; pp.dpp_pr = dpr->dpr_proc;
pp.dpp_pcb = pcb; pp.dpp_pcb = pcb;
#ifdef DOODAD
/* /*
* We can only trace dynamically-linked executables (since we've * We can only trace dynamically-linked executables (since we've
* hidden some magic in ld.so.1 as well as libc.so.1). * hidden some magic in ld.so.1 as well as libc.so.1).
@ -454,6 +525,7 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
"process %s is not a dynamically-linked executable", "process %s is not a dynamically-linked executable",
&pdp->dtpd_provider[3])); &pdp->dtpd_provider[3]));
} }
#endif
pp.dpp_mod = pdp->dtpd_mod[0] != '\0' ? pdp->dtpd_mod : "*"; pp.dpp_mod = pdp->dtpd_mod[0] != '\0' ? pdp->dtpd_mod : "*";
pp.dpp_func = pdp->dtpd_func[0] != '\0' ? pdp->dtpd_func : "*"; pp.dpp_func = pdp->dtpd_func[0] != '\0' ? pdp->dtpd_func : "*";
@ -467,8 +539,13 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
pp.dpp_mod = pdp->dtpd_mod; pp.dpp_mod = pdp->dtpd_mod;
(void) strcpy(pdp->dtpd_mod, "a.out"); (void) strcpy(pdp->dtpd_mod, "a.out");
} else if (strisglob(pp.dpp_mod) || } else if (strisglob(pp.dpp_mod) ||
#if defined(sun)
(aout = Pname_to_map(pp.dpp_pr, "a.out")) == NULL || (aout = Pname_to_map(pp.dpp_pr, "a.out")) == NULL ||
(pmp = Pname_to_map(pp.dpp_pr, pp.dpp_mod)) == 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) { aout->pr_vaddr != pmp->pr_vaddr) {
return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_LIB, return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_LIB,
"only the a.out module is valid with the " "only the a.out module is valid with the "
@ -487,6 +564,7 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
* to iterate over each module and compare its name against the * to iterate over each module and compare its name against the
* pattern. An empty module name is treated as '*'. * pattern. An empty module name is treated as '*'.
*/ */
#ifdef DOODAD
if (strisglob(pp.dpp_mod)) { if (strisglob(pp.dpp_mod)) {
ret = Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp); ret = Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp);
} else { } else {
@ -507,6 +585,7 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
ret = dt_pid_per_mod(&pp, pmp, obj); ret = dt_pid_per_mod(&pp, pmp, obj);
} }
} }
#endif
return (ret); return (ret);
} }
@ -516,7 +595,9 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
{ {
struct ps_prochandle *P = data; struct ps_prochandle *P = data;
GElf_Sym sym; GElf_Sym sym;
#if defined(sun)
prsyminfo_t sip; prsyminfo_t sip;
#endif
dof_helper_t dh; dof_helper_t dh;
GElf_Half e_type; GElf_Half e_type;
const char *mname; const char *mname;
@ -530,8 +611,12 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
* run the code to instantiate these providers. * run the code to instantiate these providers.
*/ */
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
#if defined(sun)
if (Pxlookup_by_name(P, PR_LMID_EVERY, oname, syms[i], &sym, if (Pxlookup_by_name(P, PR_LMID_EVERY, oname, syms[i], &sym,
&sip) != 0) { &sip) != 0) {
#else
if (proc_name2sym(P, oname, syms[i], &sym) != 0) {
#endif
continue; continue;
} }
@ -542,18 +627,25 @@ 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); 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 + if (Pread(P, &e_type, sizeof (e_type), pmp->pr_vaddr +
offsetof(Elf64_Ehdr, e_type)) != sizeof (e_type)) { offsetof(Elf64_Ehdr, e_type)) != sizeof (e_type)) {
dt_dprintf("read of ELF header failed"); dt_dprintf("read of ELF header failed");
continue; continue;
} }
#endif
dh.dofhp_dof = sym.st_value; dh.dofhp_dof = sym.st_value;
dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr; dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr;
dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod), dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod),
#if defined(sun)
sip.prs_lmid, mname); sip.prs_lmid, mname);
#else
0, mname);
#endif
#ifdef DOODAD
if (fd == -1 && if (fd == -1 &&
(fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) { (fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) {
dt_dprintf("pr_open of helper device failed: %s\n", dt_dprintf("pr_open of helper device failed: %s\n",
@ -563,10 +655,13 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
if (pr_ioctl(P, fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0) if (pr_ioctl(P, fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0)
dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod); dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod);
#endif
} }
#ifdef DOODAD
if (fd != -1) if (fd != -1)
(void) pr_close(P, fd); (void) pr_close(P, fd);
#endif
return (0); return (0);
} }
@ -580,13 +675,19 @@ dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
assert(DT_MUTEX_HELD(&dpr->dpr_lock)); assert(DT_MUTEX_HELD(&dpr->dpr_lock));
#ifdef DOODAD
(void) Pupdate_maps(P); (void) Pupdate_maps(P);
if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) { if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) {
ret = -1; ret = -1;
(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT, (void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT,
"failed to instantiate probes for pid %d: %s", "failed to instantiate probes for pid %d: %s",
#if defined(sun)
(int)Pstatus(P)->pr_pid, strerror(errno)); (int)Pstatus(P)->pr_pid, strerror(errno));
#else
(int)proc_getpid(P), strerror(errno));
#endif
} }
#endif
/* /*
* Put the module name in its canonical form. * Put the module name in its canonical form.
@ -667,7 +768,13 @@ dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
assert(dpr != NULL); assert(dpr != NULL);
(void) pthread_mutex_lock(&dpr->dpr_lock); (void) pthread_mutex_lock(&dpr->dpr_lock);
err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr); if ((err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr)) == 0) {
/*
* Alert other retained enablings which may match
* against the newly created probes.
*/
(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
}
(void) pthread_mutex_unlock(&dpr->dpr_lock); (void) pthread_mutex_unlock(&dpr->dpr_lock);
dt_proc_release(dtp, P); dt_proc_release(dtp, P);
@ -702,6 +809,7 @@ dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
int int
dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr) dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
{ {
dtrace_enable_io_t args;
dtrace_prog_t *pgp; dtrace_prog_t *pgp;
dt_stmt_t *stp; dt_stmt_t *stp;
dtrace_probedesc_t *pdp, pd; dtrace_probedesc_t *pdp, pd;
@ -746,7 +854,9 @@ dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
* Give DTrace a shot to the ribs to get it to check * Give DTrace a shot to the ribs to get it to check
* out the newly created probes. * out the newly created probes.
*/ */
(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL); args.dof = NULL;
args.n_matched = 0;
(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, &args);
} }
return (ret); return (ret);