diff options
author | ahl <none@none> | 2006-02-08 10:03:09 -0800 |
---|---|---|
committer | ahl <none@none> | 2006-02-08 10:03:09 -0800 |
commit | 900524f30cbbebc670e146a87587f355b9f633ee (patch) | |
tree | 81a3f2e4cc774c698d8a4880e5c6d3098bcd5b28 /usr/src/lib/libdtrace/common | |
parent | c877ffe618c3f6a0f995ed6b3d5feed148e6d49f (diff) | |
download | illumos-gate-900524f30cbbebc670e146a87587f355b9f633ee.tar.gz |
4864945 spelling error in usage message
6299947 ustack() needs to ignore the top 32 bits for 32-bit processes
6305794 libdtrace misses rtld notifications
6309681 USDT headergen
6349088 dtrace command, Assertion failed: dpr->dpr_refs != 0, file ../common/dt_proc.c, line 976
6375841 USDT providers shouldn't be allowed to end in a digit
--HG--
rename : usr/src/cmd/abi/apptrace/amd64/Makefile => deleted_files/usr/src/cmd/abi/apptrace/amd64/Makefile
Diffstat (limited to 'usr/src/lib/libdtrace/common')
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_cc.c | 13 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_parser.c | 8 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_pid.c | 409 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_pid.h | 8 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_proc.c | 97 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_proc.h | 16 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_program.c | 215 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_work.c | 21 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dtrace.h | 9 |
9 files changed, 553 insertions, 243 deletions
diff --git a/usr/src/lib/libdtrace/common/dt_cc.c b/usr/src/lib/libdtrace/common/dt_cc.c index e4272187dd..9d95f480c1 100644 --- a/usr/src/lib/libdtrace/common/dt_cc.c +++ b/usr/src/lib/libdtrace/common/dt_cc.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1434,10 +1435,14 @@ dt_setcontext(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp) /* * If the provider name ends with what could be interpreted as a * number, we assume that it's a pid and that we may need to - * dynamically create those probes for that process. + * dynamically create those probes for that process. On an error, + * dt_pid_create_probes() will set the error message and tag -- + * we just have to longjmp() out of here. */ - if (isdigit(pdp->dtpd_provider[strlen(pdp->dtpd_provider) - 1])) - dt_pid_create_probes(pdp, dtp); + if (isdigit(pdp->dtpd_provider[strlen(pdp->dtpd_provider) - 1]) && + dt_pid_create_probes(pdp, dtp, yypcb) != 0) { + longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); + } /* * Call dt_probe_info() to get the probe arguments and attributes. If diff --git a/usr/src/lib/libdtrace/common/dt_parser.c b/usr/src/lib/libdtrace/common/dt_parser.c index 07db59982e..9aabc18565 100644 --- a/usr/src/lib/libdtrace/common/dt_parser.c +++ b/usr/src/lib/libdtrace/common/dt_parser.c @@ -2498,6 +2498,7 @@ dt_node_provider(char *name, dt_node_t *probes) dtrace_hdl_t *dtp = yypcb->pcb_hdl; dt_node_t *dnp = dt_node_alloc(DT_NODE_PROVIDER); dt_node_t *lnp; + size_t len; dnp->dn_provname = name; dnp->dn_probes = probes; @@ -2507,11 +2508,16 @@ dt_node_provider(char *name, dt_node_t *probes) "contain scoping operator: %s\n", name); } - if (strlen(name) >= DTRACE_PROVNAMELEN) { + if ((len = strlen(name)) >= DTRACE_PROVNAMELEN) { dnerror(dnp, D_PROV_BADNAME, "provider name may not exceed %d " "characters: %s\n", DTRACE_PROVNAMELEN - 1, name); } + if (isdigit(name[len - 1])) { + dnerror(dnp, D_PROV_BADNAME, "provider name may not " + "end with a digit: %s\n", name); + } + /* * Check to see if the provider is already defined or visible through * dtrace(7D). If so, set dn_provred to treat it as a re-declaration. diff --git a/usr/src/lib/libdtrace/common/dt_pid.c b/usr/src/lib/libdtrace/common/dt_pid.c index b91cf6ef56..35f51ec1c3 100644 --- a/usr/src/lib/libdtrace/common/dt_pid.c +++ b/usr/src/lib/libdtrace/common/dt_pid.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,19 +43,21 @@ #include <dt_string.h> typedef struct dt_pid_probe { - dtrace_hdl_t *dpp_dtp; - struct ps_prochandle *dpp_pr; - const char *dpp_mod; - char *dpp_func; - const char *dpp_name; - const char *dpp_obj; - uintptr_t dpp_pc; - size_t dpp_size; - Lmid_t dpp_lmid; - uint_t dpp_nmatches; - uint64_t dpp_stret[4]; - GElf_Sym dpp_last; - uint_t dpp_last_taken; + dtrace_hdl_t *dpp_dtp; + dt_pcb_t *dpp_pcb; + dt_proc_t *dpp_dpr; + struct ps_prochandle *dpp_pr; + const char *dpp_mod; + char *dpp_func; + const char *dpp_name; + const char *dpp_obj; + uintptr_t dpp_pc; + size_t dpp_size; + Lmid_t dpp_lmid; + uint_t dpp_nmatches; + uint64_t dpp_stret[4]; + GElf_Sym dpp_last; + uint_t dpp_last_taken; } dt_pid_probe_t; /* @@ -70,19 +73,39 @@ dt_pid_objname(char *buf, size_t len, Lmid_t lmid, const char *obj) (void) snprintf(buf, len, "LM%lx`%s", lmid, obj); } -static void -dt_pid_error(dtrace_hdl_t *dtp, dt_errtag_t tag, const char *fmt, ...) +static int +dt_pid_error(dtrace_hdl_t *dtp, dt_pcb_t *pcb, dt_proc_t *dpr, + fasttrap_probe_spec_t *ftp, dt_errtag_t tag, const char *fmt, ...) { va_list ap; + int len; + + if (ftp != NULL) + dt_free(dtp, ftp); va_start(ap, fmt); - dt_set_errmsg(dtp, dt_errtag(tag), NULL, NULL, 0, fmt, ap); + if (pcb == NULL) { + assert(dpr != NULL); + len = vsnprintf(dpr->dpr_errmsg, sizeof (dpr->dpr_errmsg), + fmt, ap); + assert(len >= 2); + if (dpr->dpr_errmsg[len - 2] == '\n') + dpr->dpr_errmsg[len - 2] = '\0'; + } else { + dt_set_errmsg(dtp, dt_errtag(tag), pcb->pcb_region, + pcb->pcb_filetag, pcb->pcb_fileptr ? yylineno : 0, fmt, ap); + } va_end(ap); + + return (1); } -static void +static int dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func) { + dtrace_hdl_t *dtp = pp->dpp_dtp; + dt_pcb_t *pcb = pp->dpp_pcb; + dt_proc_t *dpr = pp->dpp_dpr; fasttrap_probe_spec_t *ftp; uint64_t off; char *end; @@ -100,12 +123,9 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func) sz = sizeof (fasttrap_probe_spec_t) + (isdash ? 4 : (symp->st_size - 1) * sizeof (ftp->ftps_offs[0])); - if (sz < 4000) { - ftp = alloca(sz); - sz = 0; - } else if ((ftp = malloc(sz)) == NULL) { - dt_dprintf("proc_per_sym: malloc(%lu) failed\n", sz); - return; + if ((ftp = dt_alloc(dtp, sz)) == NULL) { + dt_dprintf("proc_per_sym: dt_alloc(%lu) failed\n", sz); + return (1); /* errno is set for us */ } ftp->ftps_pid = pid; @@ -115,17 +135,24 @@ 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)) { - if (dt_pid_create_return_probe(pp->dpp_pr, pp->dpp_dtp, - ftp, symp, pp->dpp_stret) < 0) - goto create_err; + if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp, + pp->dpp_stret) < 0) { + return (dt_pid_error(dtp, pcb, dpr, ftp, + D_PROC_CREATEFAIL, "failed to create return probe " + "for '%s': %s", func, + dtrace_errmsg(dtp, dtrace_errno(dtp)))); + } nmatches++; } if (!isdash && gmatch("entry", pp->dpp_name)) { - if (dt_pid_create_entry_probe(pp->dpp_pr, pp->dpp_dtp, - ftp, symp) < 0) - goto create_err; + 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)))); + } nmatches++; } @@ -134,65 +161,51 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func) if (!glob && nmatches == 0) { off = strtoull(pp->dpp_name, &end, 16); if (*end != '\0') { - if (sz != 0) - free(ftp); - dt_proc_release(pp->dpp_dtp, pp->dpp_pr); - xyerror(D_PROC_NAME, "'%s' is an invalid probe name\n", - pp->dpp_name); + return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_NAME, + "'%s' is an invalid probe name", pp->dpp_name)); } if (off >= symp->st_size) { - dt_pid_error(pp->dpp_dtp, D_PROC_OFF, "offset " - "0x%llx outside of function '%s'\n", - (u_longlong_t)off, func); - goto out; + return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_OFF, + "offset 0x%llx outside of function '%s'", + (u_longlong_t)off, func)); } err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp, symp, off); - if (err == DT_PROC_ERR) - goto create_err; + if (err == DT_PROC_ERR) { + return (dt_pid_error(dtp, pcb, dpr, ftp, + D_PROC_CREATEFAIL, "failed to create probe at " + "'%s+0x%llx': %s", func, (u_longlong_t)off, + dtrace_errmsg(dtp, dtrace_errno(dtp)))); + } + if (err == DT_PROC_ALIGN) { -#ifdef __sparc - if (sz != 0) - free(ftp); - dt_proc_release(pp->dpp_dtp, pp->dpp_pr); - xyerror(D_PROC_ALIGN, "offset 0x%llx is not properly " - "aligned\n", (u_longlong_t)off); -#else - dt_pid_error(pp->dpp_dtp, D_PROC_ALIGN, "offset " - "0x%llx is not aligned on an instruction\n", - (u_longlong_t)off); - goto out; -#endif + return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_ALIGN, + "offset 0x%llx is not aligned on an instruction", + (u_longlong_t)off)); } nmatches++; } else if (glob && !isdash) { if (dt_pid_create_glob_offset_probes(pp->dpp_pr, - pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) - goto create_err; + pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) { + return (dt_pid_error(dtp, pcb, dpr, ftp, + D_PROC_CREATEFAIL, + "failed to create offset probes in '%s': %s", func, + dtrace_errmsg(dtp, dtrace_errno(dtp)))); + } nmatches++; } pp->dpp_nmatches += nmatches; -out: - if (sz != 0) - free(ftp); - return; + dt_free(dtp, ftp); -create_err: - if (sz != 0) - free(ftp); - - dt_proc_release(pp->dpp_dtp, pp->dpp_pr); - dt_pid_error(pp->dpp_dtp, D_PROC_CREATEFAIL, "failed to create " - "probe in process %d: %s", (int)pid, - dtrace_errmsg(pp->dpp_dtp, dtrace_errno(pp->dpp_dtp))); + return (0); } static int @@ -208,7 +221,8 @@ dt_pid_sym_filt(void *arg, const GElf_Sym *symp, const char *func) return (0); } - if (symp->st_value != pp->dpp_last.st_value || + if (pp->dpp_last_taken == 0 || + symp->st_value != pp->dpp_last.st_value || symp->st_size != pp->dpp_last.st_size) { /* * Due to 4524008, _init and _fini may have a bloated st_size. @@ -220,25 +234,26 @@ dt_pid_sym_filt(void *arg, const GElf_Sym *symp, const char *func) if (strcmp(func, "_init") == 0 || strcmp(func, "_fini") == 0) return (0); - if (gmatch(func, pp->dpp_func)) { - dt_pid_per_sym(pp, symp, func); - pp->dpp_last_taken = 1; + if ((pp->dpp_last_taken = gmatch(func, pp->dpp_func)) != 0) { + pp->dpp_last = *symp; + return (dt_pid_per_sym(pp, symp, func)); } - - pp->dpp_last = *symp; } return (0); } -static void +static int dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj) { dt_pid_probe_t *pp = arg; + dtrace_hdl_t *dtp = pp->dpp_dtp; + dt_pcb_t *pcb = pp->dpp_pcb; + dt_proc_t *dpr = pp->dpp_dpr; GElf_Sym sym; if (obj == NULL) - return; + return (0); (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); @@ -302,12 +317,12 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj) PR_MODEL_ILP32 ? -1U : -1ULL; } else if (!strisglob(pp->dpp_mod)) { - dt_proc_release(pp->dpp_dtp, pp->dpp_pr); - xyerror(D_PROC_FUNC, "failed to lookup '%s' " - "in module '%s'\n", pp->dpp_func, - pp->dpp_mod); + return (dt_pid_error(dtp, pcb, dpr, NULL, + D_PROC_FUNC, + "failed to lookup '%s' in module '%s'", + pp->dpp_func, pp->dpp_mod)); } else { - return; + return (0); } } @@ -316,58 +331,60 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj) */ if (GELF_ST_TYPE(sym.st_info) != STT_FUNC || sym.st_shndx == SHN_UNDEF || sym.st_size == 0) - return; + return (0); /* * We don't instrument PLTs -- they're dynamically rewritten, * and, so, inherently dicey to instrument. */ if (Ppltdest(pp->dpp_pr, sym.st_value) != NULL) - return; + return (0); (void) Plookup_by_addr(pp->dpp_pr, sym.st_value, pp->dpp_func, DTRACE_FUNCNAMELEN, &sym); - dt_pid_per_sym(pp, &sym, pp->dpp_func); + return (dt_pid_per_sym(pp, &sym, pp->dpp_func)); } else { uint_t nmatches = pp->dpp_nmatches; - (void) Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB, - BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp); + if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB, + BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1) + return (1); if (nmatches == pp->dpp_nmatches) { /* * If we didn't match anything in the PR_SYMTAB, try * the PR_DYNSYM. */ - (void) Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_DYNSYM, - BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp); + if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_DYNSYM, + BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1) + return (1); } } + + return (0); } static int dt_pid_mod_filt(void *arg, const prmap_t *pmp, const char *obj) { + char name[DTRACE_MODNAMELEN]; dt_pid_probe_t *pp = arg; - if (gmatch(obj, pp->dpp_mod)) { - dt_pid_per_mod(pp, pmp, obj); - } else { - char name[DTRACE_MODNAMELEN]; + if (gmatch(obj, pp->dpp_mod)) + return (dt_pid_per_mod(pp, pmp, obj)); - (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); + (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); - if ((pp->dpp_obj = strrchr(obj, '/')) == NULL) - pp->dpp_obj = obj; - else - pp->dpp_obj++; + if ((pp->dpp_obj = strrchr(obj, '/')) == NULL) + pp->dpp_obj = obj; + else + pp->dpp_obj++; - dt_pid_objname(name, sizeof (name), pp->dpp_lmid, obj); + dt_pid_objname(name, sizeof (name), pp->dpp_lmid, obj); - if (gmatch(name, pp->dpp_mod)) - dt_pid_per_mod(pp, pmp, obj); - } + if (gmatch(name, pp->dpp_mod)) + return (dt_pid_per_mod(pp, pmp, obj)); return (0); } @@ -417,29 +434,38 @@ dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P) } -static void -dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, pid_t pid) +static int +dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, + dt_pcb_t *pcb, dt_proc_t *dpr) { dt_pid_probe_t pp; + int ret = 0; - pp.dpp_pr = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0); - if (pp.dpp_pr == NULL) - longjmp(dtp->dt_pcb->pcb_jmpbuf, EDT_COMPILER); + /* + * Disable breakpoints so they don't interfere with our disassembly. + */ + dt_proc_bpdisable(dpr); + + pp.dpp_dtp = dtp; + pp.dpp_dpr = dpr; + pp.dpp_pr = dpr->dpr_proc; + pp.dpp_pcb = pcb; /* * We can only trace dynamically-linked executables (since we've * hidden some magic in ld.so.1 as well as libc.so.1). */ if (Pname_to_map(pp.dpp_pr, PR_OBJ_LDSO) == NULL) { - dt_proc_release(dtp, pp.dpp_pr); - xyerror(D_PROC_DYN, "process %s is not a dynamically-linked " - "executable\n", &pdp->dtpd_provider[3]); + dt_proc_bpenable(dpr); + return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_DYN, + "process %s is not a dynamically-linked executable", + &pdp->dtpd_provider[3])); } - pp.dpp_dtp = dtp; pp.dpp_mod = pdp->dtpd_mod[0] != '\0' ? pdp->dtpd_mod : "*"; pp.dpp_func = pdp->dtpd_func[0] != '\0' ? pdp->dtpd_func : "*"; pp.dpp_name = pdp->dtpd_name[0] != '\0' ? pdp->dtpd_name : "*"; + pp.dpp_last_taken = 0; if (strcmp(pp.dpp_func, "-") == 0) { const prmap_t *aout, *pmp; @@ -451,15 +477,17 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, pid_t pid) (aout = Pname_to_map(pp.dpp_pr, "a.out")) == NULL || (pmp = Pname_to_map(pp.dpp_pr, pp.dpp_mod)) == NULL || aout->pr_vaddr != pmp->pr_vaddr) { - dt_proc_release(dtp, pp.dpp_pr); - xyerror(D_PROC_LIB, "only the a.out module is valid " - "with the '-' function\n"); + dt_proc_bpenable(dpr); + return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_LIB, + "only the a.out module is valid with the " + "'-' function")); } if (strisglob(pp.dpp_name)) { - dt_proc_release(dtp, pp.dpp_pr); - xyerror(D_PROC_NAME, "only individual addresses may " - "be specified with the '-' function\n"); + dt_proc_bpenable(dpr); + return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_NAME, + "only individual addresses may be specified " + "with the '-' function")); } } @@ -469,13 +497,13 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, pid_t pid) * pattern. An empty module name is treated as '*'. */ if (strisglob(pp.dpp_mod)) { - (void) Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp); + ret = Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp); } else { const prmap_t *pmp; char *obj; /* - * If can't find a matching module, don't sweat it -- either + * If we can't find a matching module, don't sweat it -- either * we'll fail the enabling because the probes don't exist or * we'll wait for that module to come along. */ @@ -485,11 +513,13 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, pid_t pid) else obj++; - dt_pid_per_mod(&pp, pmp, obj); + ret = dt_pid_per_mod(&pp, pmp, obj); } } - dt_proc_release(dtp, pp.dpp_pr); + dt_proc_bpenable(dpr); + + return (ret); } static int @@ -498,12 +528,11 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname) struct ps_prochandle *P = data; GElf_Sym sym; prsyminfo_t sip; - int fd; dof_helper_t dh; GElf_Half e_type; const char *mname; const char *syms[] = { "___SUNW_dof", "__SUNW_dof" }; - int i; + int i, fd = -1; /* * The symbol ___SUNW_dof is for lazy-loaded DOF sections, and @@ -536,42 +565,51 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname) dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod), sip.prs_lmid, mname); - if ((fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) { + if (fd == -1 && + (fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) { dt_dprintf("pr_open of helper device failed: %s\n", strerror(errno)); - return (errno); + return (-1); /* errno is set for us */ } - (void) pr_ioctl(P, fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)); - - if (pr_close(P, fd) != 0) - return (errno); + if (pr_ioctl(P, fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0) + dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod); } + if (fd != -1) + (void) pr_close(P, fd); + return (0); } static int -dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dt_proc_t *dpr) +dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, + dt_pcb_t *pcb, dt_proc_t *dpr) { struct ps_prochandle *P = dpr->dpr_proc; - int err; + int ret = 0; assert(DT_MUTEX_HELD(&dpr->dpr_lock)); (void) Pupdate_maps(P); - err = Pobject_iter(P, dt_pid_usdt_mapping, P); + if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) { + ret = -1; + (void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT, + "failed to instantiate probes for pid %d: %s", + (int)Pstatus(P)->pr_pid, strerror(errno)); + } /* * Put the module name in its canonical form. */ (void) dt_pid_fix_mod(pdp, P); - return (err); + return (ret); } static pid_t -dt_pid_get_pid(dtrace_probedesc_t *pdp, int *errp) +dt_pid_get_pid(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb, + dt_proc_t *dpr) { pid_t pid; char *c, *last = NULL, *end; @@ -582,89 +620,100 @@ dt_pid_get_pid(dtrace_probedesc_t *pdp, int *errp) } if (last == NULL || (*(++last) == '\0')) { - if (errp != NULL) { - *errp = D_PROC_BADPROV; - return (-1); - } - xyerror(D_PROC_BADPROV, "%s is not a valid provider\n", - pdp->dtpd_provider); + (void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPROV, + "'%s' is not a valid provider", pdp->dtpd_provider); + return (-1); } errno = 0; pid = strtol(last, &end, 10); if (errno != 0 || end == last || end[0] != '\0' || pid <= 0) { - if (errp != NULL) { - *errp = D_PROC_BADPID; - return (-1); - } - xyerror(D_PROC_BADPID, "%s does not contain a valid pid\n", - pdp->dtpd_provider); + (void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPID, + "'%s' does not contain a valid pid", pdp->dtpd_provider); + return (-1); } - if (errp != NULL) - *errp = 0; - return (pid); } -void -dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp) +int +dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb) { - pid_t pid = dt_pid_get_pid(pdp, NULL); char provname[DTRACE_PROVNAMELEN]; struct ps_prochandle *P; dt_proc_t *dpr; - int err = 0; + pid_t pid; + int err; + + assert(pcb != NULL); + + if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1) + return (-1); if (dtp->dt_ftfd == -1) { if (dtp->dt_fterr == ENOENT) { - xyerror(D_PROC_NODEV, "pid provider is not " - "installed on this system\n"); + (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV, + "pid provider is not installed on this system"); } else { - xyerror(D_PROC_NODEV, "pid provider is not " - "available: %s\n", strerror(dtp->dt_fterr)); + (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV, + "pid provider is not available: %s", + strerror(dtp->dt_fterr)); } + + return (-1); } (void) snprintf(provname, sizeof (provname), "pid%d", (int)pid); if (strcmp(provname, pdp->dtpd_provider) == 0) { - dt_pid_create_pid_probes(pdp, dtp, pid); - } else { - if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL) - longjmp(dtp->dt_pcb->pcb_jmpbuf, EDT_COMPILER); + if ((P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, + 0)) == NULL) { + (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB, + "failed to grab process %d", (int)pid); + return (-1); + } dpr = dt_proc_lookup(dtp, P, 0); assert(dpr != NULL); + (void) pthread_mutex_lock(&dpr->dpr_lock); + + err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr); + (void) pthread_mutex_unlock(&dpr->dpr_lock); + dt_proc_release(dtp, P); + + } else { + if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL) { + (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB, + "failed to grab process %d", (int)pid); + return (-1); + } + + dpr = dt_proc_lookup(dtp, P, 0); + assert(dpr != NULL); (void) pthread_mutex_lock(&dpr->dpr_lock); if (!dpr->dpr_usdt) { - err = dt_pid_create_usdt_probes(pdp, dpr); + err = dt_pid_create_usdt_probes(pdp, dtp, pcb, dpr); dpr->dpr_usdt = B_TRUE; } (void) pthread_mutex_unlock(&dpr->dpr_lock); - dt_proc_release(dtp, P); - - if (err != 0) - dt_pid_error(dtp, D_PROC_USDT, "failed to instantiate " - "probes for PID %d: %s", (int)pid, strerror(err)); } + + return (err ? -1 : 0); } -void +int dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr) { dtrace_prog_t *pgp; dt_stmt_t *stp; - char provname[DTRACE_PROVNAMELEN]; dtrace_probedesc_t *pdp, pd; pid_t pid; - int err; - int found = B_FALSE; + int ret = 0, found = B_FALSE; for (pgp = dt_list_next(&dtp->dt_programs); pgp != NULL; pgp = dt_list_next(pgp)) { @@ -673,21 +722,23 @@ dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr) stp = dt_list_next(stp)) { pdp = &stp->ds_desc->dtsd_ecbdesc->dted_probe; - pid = dt_pid_get_pid(pdp, &err); - if (err != 0 || pid != dpr->dpr_pid) + pid = dt_pid_get_pid(pdp, dtp, NULL, dpr); + if (pid != dpr->dpr_pid) continue; found = B_TRUE; pd = *pdp; - (void) snprintf(provname, sizeof (provname), "pid%d", - (int)pid); - - if (strcmp(provname, pdp->dtpd_provider) == 0) - dt_pid_create_pid_probes(&pd, dtp, pid); - else - (void) dt_pid_create_usdt_probes(&pd, dpr); + if (strncmp(pdp->dtpd_provider, "pid", 3) == 0) { + if (dt_pid_create_pid_probes(&pd, dtp, NULL, + dpr) != 0) + ret = 1; + } else { + if (dt_pid_create_usdt_probes(&pd, dtp, NULL, + dpr) != 0) + ret = 1; + } } } @@ -698,4 +749,6 @@ dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr) */ (void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL); } + + return (ret); } diff --git a/usr/src/lib/libdtrace/common/dt_pid.h b/usr/src/lib/libdtrace/common/dt_pid.h index 30be3c2932..886e33d833 100644 --- a/usr/src/lib/libdtrace/common/dt_pid.h +++ b/usr/src/lib/libdtrace/common/dt_pid.h @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -40,8 +41,9 @@ extern "C" { #define DT_PROC_ERR (-1) #define DT_PROC_ALIGN (-2) -extern void dt_pid_create_probes(dtrace_probedesc_t *, dtrace_hdl_t *); -extern void dt_pid_create_probes_module(dtrace_hdl_t *, dt_proc_t *); +extern int dt_pid_create_probes(dtrace_probedesc_t *, dtrace_hdl_t *, + dt_pcb_t *pcb); +extern int dt_pid_create_probes_module(dtrace_hdl_t *, dt_proc_t *); extern int dt_pid_create_entry_probe(struct ps_prochandle *, dtrace_hdl_t *, fasttrap_probe_spec_t *, const GElf_Sym *); diff --git a/usr/src/lib/libdtrace/common/dt_proc.c b/usr/src/lib/libdtrace/common/dt_proc.c index 0402c60cf1..66bc3aa011 100644 --- a/usr/src/lib/libdtrace/common/dt_proc.c +++ b/usr/src/lib/libdtrace/common/dt_proc.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -161,7 +162,7 @@ dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr) (void) Pxecbkpt(dpr->dpr_proc, dbp->dbp_instr); } -static void +void dt_proc_bpenable(dt_proc_t *dpr) { dt_bkpt_t *dbp; @@ -174,9 +175,11 @@ dt_proc_bpenable(dt_proc_t *dpr) dbp->dbp_addr, &dbp->dbp_instr) == 0) dbp->dbp_active = B_TRUE; } + + dt_dprintf("breakpoints enabled\n"); } -static void +void dt_proc_bpdisable(dt_proc_t *dpr) { dt_bkpt_t *dbp; @@ -189,6 +192,35 @@ dt_proc_bpdisable(dt_proc_t *dpr) dbp->dbp_addr, dbp->dbp_instr) == 0) dbp->dbp_active = B_FALSE; } + + dt_dprintf("breakpoints disabled\n"); +} + +static void +dt_proc_notify(dtrace_hdl_t *dtp, dt_proc_hash_t *dph, dt_proc_t *dpr, + const char *msg) +{ + dt_proc_notify_t *dprn = dt_alloc(dtp, sizeof (dt_proc_notify_t)); + + if (dprn == NULL) { + dt_dprintf("failed to allocate notification for %d %s\n", + (int)dpr->dpr_pid, msg); + } else { + dprn->dprn_dpr = dpr; + if (msg == NULL) + dprn->dprn_errmsg[0] = '\0'; + else + (void) strlcpy(dprn->dprn_errmsg, msg, + sizeof (dprn->dprn_errmsg)); + + (void) pthread_mutex_lock(&dph->dph_lock); + + dprn->dprn_next = dph->dph_notify; + dph->dph_notify = dprn; + + (void) pthread_cond_broadcast(&dph->dph_cv); + (void) pthread_mutex_unlock(&dph->dph_lock); + } } /* @@ -239,12 +271,14 @@ dt_proc_rdevent(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *evname) switch (rdm.type) { case RD_DLACTIVITY: - if (rdm.u.state == RD_CONSISTENT) { - Pupdate_syms(dpr->dpr_proc); - dt_proc_bpdisable(dpr); - dt_pid_create_probes_module(dtp, dpr); - dt_proc_bpenable(dpr); - } + if (rdm.u.state != RD_CONSISTENT) + break; + + Pupdate_syms(dpr->dpr_proc); + if (dt_pid_create_probes_module(dtp, dpr) != 0) + dt_proc_notify(dtp, dtp->dt_procs, dpr, + dpr->dpr_errmsg); + break; case RD_PREINIT: Pupdate_syms(dpr->dpr_proc); @@ -588,15 +622,8 @@ pwait_locked: * If the control thread detected PS_UNDEAD or PS_LOST, then enqueue * the dt_proc_t structure on the dt_proc_hash_t notification list. */ - if (notify) { - (void) pthread_mutex_lock(&dph->dph_lock); - - dpr->dpr_notify = dph->dph_notify; - dph->dph_notify = dpr; - - (void) pthread_mutex_unlock(&dph->dph_lock); - (void) pthread_cond_broadcast(&dph->dph_cv); - } + if (notify) + dt_proc_notify(dtp, dph, dpr, NULL); /* * Destroy and remove any remaining breakpoints, set dpr_done and clear @@ -609,8 +636,8 @@ pwait_locked: dpr->dpr_done = B_TRUE; dpr->dpr_tid = 0; - (void) pthread_mutex_unlock(&dpr->dpr_lock); (void) pthread_cond_broadcast(&dpr->dpr_cv); + (void) pthread_mutex_unlock(&dpr->dpr_lock); return (NULL); } @@ -661,7 +688,7 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P) { dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); dt_proc_hash_t *dph = dtp->dt_procs; - dt_proc_t *npr, **npp; + dt_proc_notify_t *npr, **npp; int rflag; assert(dpr != NULL); @@ -723,16 +750,13 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P) (void) dt_proc_lookup(dtp, P, B_TRUE); npp = &dph->dph_notify; - for (npr = *npp; npr != NULL; npr = npr->dpr_notify) { - if (npr != dpr) - npp = &npr->dpr_notify; - else - break; - } - - if (npr != NULL) { - *npp = npr->dpr_notify; - npr->dpr_notify = NULL; + while ((npr = *npp) != NULL) { + if (npr->dprn_dpr == dpr) { + *npp = npr->dprn_next; + dt_free(dtp, npr); + } else { + npp = &npr->dprn_next; + } } (void) pthread_mutex_unlock(&dph->dph_lock); @@ -814,15 +838,7 @@ dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop) } err = ESRCH; /* cause grab() or create() to fail */ - } else { - /* - * Disable breakpoints while the process is stopped so - * the pid provider can correctly disassemble all - * functions. - */ - dt_proc_bpdisable(dpr); } - } else { (void) dt_proc_error(dpr->dpr_hdl, dpr, "failed to create control thread for process-id %d: %s\n", @@ -988,11 +1004,6 @@ dt_proc_continue(dtrace_hdl_t *dtp, struct ps_prochandle *P) (void) pthread_mutex_lock(&dpr->dpr_lock); if (dpr->dpr_stop & DT_PROC_STOP_IDLE) { - /* - * Breakpoints are disabled while the process is stopped so - * the pid provider can correctly disassemble all functions. - */ - dt_proc_bpenable(dpr); dpr->dpr_stop &= ~DT_PROC_STOP_IDLE; (void) pthread_cond_broadcast(&dpr->dpr_cv); } diff --git a/usr/src/lib/libdtrace/common/dt_proc.h b/usr/src/lib/libdtrace/common/dt_proc.h index 2f2b0a67a7..fbc6f4aec1 100644 --- a/usr/src/lib/libdtrace/common/dt_proc.h +++ b/usr/src/lib/libdtrace/common/dt_proc.h @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,9 +42,9 @@ extern "C" { typedef struct dt_proc { dt_list_t dpr_list; /* prev/next pointers for lru chain */ struct dt_proc *dpr_hash; /* next pointer for pid hash chain */ - struct dt_proc *dpr_notify; /* next pointer for notification list */ 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 */ rd_agent_t *dpr_rtld; /* rtld handle for librtld_db calls */ pthread_mutex_t dpr_lock; /* lock for manipulating dpr_hdl */ pthread_cond_t dpr_cv; /* cond for dpr_stop/quit/done */ @@ -60,6 +61,12 @@ typedef struct dt_proc { dt_list_t dpr_bps; /* list of dt_bkpt_t structures */ } dt_proc_t; +typedef struct dt_proc_notify { + dt_proc_t *dprn_dpr; /* process associated with the event */ + char dprn_errmsg[BUFSIZ]; /* error message */ + struct dt_proc_notify *dprn_next; /* next pointer */ +} dt_proc_notify_t; + #define DT_PROC_STOP_IDLE 0x01 /* idle on owner's stop request */ #define DT_PROC_STOP_CREATE 0x02 /* wait on dpr_cv at process exec */ #define DT_PROC_STOP_GRAB 0x04 /* wait on dpr_cv at process grab */ @@ -82,7 +89,7 @@ typedef struct dt_bkpt { typedef struct dt_proc_hash { pthread_mutex_t dph_lock; /* lock protecting dph_notify list */ pthread_cond_t dph_cv; /* cond for waiting for dph_notify */ - dt_proc_t *dph_notify; /* list of pending proc notifications */ + dt_proc_notify_t *dph_notify; /* list of pending proc notifications */ dt_list_t dph_lrulist; /* list of dt_proc_t's in lru order */ uint_t dph_lrulim; /* limit on number of procs to hold */ uint_t dph_lrucnt; /* count of cached process handles */ @@ -100,6 +107,9 @@ extern void dt_proc_lock(dtrace_hdl_t *, struct ps_prochandle *); extern void dt_proc_unlock(dtrace_hdl_t *, struct ps_prochandle *); extern dt_proc_t *dt_proc_lookup(dtrace_hdl_t *, struct ps_prochandle *, int); +extern void dt_proc_bpenable(dt_proc_t *); +extern void dt_proc_bpdisable(dt_proc_t *); + extern void dt_proc_hash_create(dtrace_hdl_t *); extern void dt_proc_hash_destroy(dtrace_hdl_t *); diff --git a/usr/src/lib/libdtrace/common/dt_program.c b/usr/src/lib/libdtrace/common/dt_program.c index c87d86aa8e..e0d3ada107 100644 --- a/usr/src/lib/libdtrace/common/dt_program.c +++ b/usr/src/lib/libdtrace/common/dt_program.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,10 +32,13 @@ #include <stdlib.h> #include <errno.h> #include <assert.h> +#include <ctype.h> +#include <alloca.h> #include <dt_impl.h> #include <dt_program.h> #include <dt_printf.h> +#include <dt_provider.h> dtrace_prog_t * dt_program_create(dtrace_hdl_t *dtp) @@ -339,3 +343,212 @@ dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc); dt_free(dtp, sdp); } + +typedef struct dt_header_info { + dtrace_hdl_t *dthi_dtp; /* consumer handle */ + FILE *dthi_out; /* output file */ + char *dthi_pmname; /* provider macro name */ + char *dthi_pfname; /* provider function name */ +} dt_header_info_t; + + +static void +dt_header_fmt_macro(char *buf, const char *str) +{ + for (;;) { + if (islower(*str)) { + *buf++ = *str++ + 'A' - 'a'; + } else if (*str == '-') { + *buf++ = '_'; + str++; + } else if (*str == '.') { + *buf++ = '_'; + str++; + } else if ((*buf++ = *str++) == '\0') { + break; + } + } +} + +static void +dt_header_fmt_func(char *buf, const char *str) +{ + for (;;) { + if (*str == '-') { + *buf++ = '_'; + *buf++ = '_'; + str++; + } else if ((*buf++ = *str++) == '\0') { + break; + } + } +} + +/*ARGSUSED*/ +static int +dt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data) +{ + dt_header_info_t *infop = data; + dtrace_hdl_t *dtp = infop->dthi_dtp; + dt_probe_t *prp = idp->di_data; + dt_node_t *dnp; + char buf[DT_TYPE_NAMELEN]; + char *fname; + const char *p; + int i; + + p = prp->pr_name; + for (i = 0; (p = strchr(p, '-')) != NULL; i++) + p++; + + fname = alloca(strlen(prp->pr_name) + 1 + i); + dt_header_fmt_func(fname, prp->pr_name); + + if (fprintf(infop->dthi_out, "extern void __dtrace_%s___%s(", + infop->dthi_pfname, fname) < 0) + return (dt_set_errno(dtp, errno)); + + for (dnp = prp->pr_nargs, i = 0; dnp != NULL; dnp = dnp->dn_list, i++) { + if (fprintf(infop->dthi_out, "%s", + ctf_type_name(dnp->dn_ctfp, dnp->dn_type, + buf, sizeof (buf))) < 0) + return (dt_set_errno(dtp, errno)); + + if (i + 1 != prp->pr_nargc && + fprintf(infop->dthi_out, ", ") < 0) + return (dt_set_errno(dtp, errno)); + } + + if (i == 0 && fprintf(infop->dthi_out, "void") < 0) + return (dt_set_errno(dtp, errno)); + + if (fprintf(infop->dthi_out, ");\n") < 0) + return (dt_set_errno(dtp, errno)); + + return (0); +} + +/*ARGSUSED*/ +static int +dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) +{ + dt_header_info_t *infop = data; + dtrace_hdl_t *dtp = infop->dthi_dtp; + dt_probe_t *prp = idp->di_data; + char *mname, *fname; + const char *p; + int i; + + p = prp->pr_name; + for (i = 0; (p = strchr(p, '-')) != NULL; i++) + p++; + + mname = alloca(strlen(prp->pr_name) + 1); + dt_header_fmt_macro(mname, prp->pr_name); + + fname = alloca(strlen(prp->pr_name) + 1 + i); + dt_header_fmt_func(fname, prp->pr_name); + + if (fprintf(infop->dthi_out, "#define\t%s_%s(", + infop->dthi_pmname, mname) < 0) + return (dt_set_errno(dtp, errno)); + + for (i = 0; i < prp->pr_nargc; i++) { + if (fprintf(infop->dthi_out, "arg%d", i) < 0) + return (dt_set_errno(dtp, errno)); + + if (i + 1 != prp->pr_nargc && + fprintf(infop->dthi_out, ", ") < 0) + return (dt_set_errno(dtp, errno)); + } + + if (fprintf(infop->dthi_out, ") \\\n\t") < 0) + return (dt_set_errno(dtp, errno)); + + if (fprintf(infop->dthi_out, "__dtrace_%s___%s(", + infop->dthi_pfname, fname) < 0) + return (dt_set_errno(dtp, errno)); + + for (i = 0; i < prp->pr_nargc; i++) { + if (fprintf(infop->dthi_out, "arg%d", i) < 0) + return (dt_set_errno(dtp, errno)); + + if (i + 1 != prp->pr_nargc && + fprintf(infop->dthi_out, ", ") < 0) + return (dt_set_errno(dtp, errno)); + } + + if (fprintf(infop->dthi_out, ")\n") < 0) + return (dt_set_errno(dtp, errno)); + + return (0); +} + +static int +dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out) +{ + dt_header_info_t info; + const char *p; + int i; + + if (pvp->pv_flags & DT_PROVIDER_IMPL) + return (0); + + p = pvp->pv_desc.dtvd_name; + for (i = 0; (p = strchr(p, '-')) != NULL; i++) + p++; + + info.dthi_dtp = dtp; + info.dthi_out = out; + + info.dthi_pmname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1); + dt_header_fmt_macro(info.dthi_pmname, pvp->pv_desc.dtvd_name); + + info.dthi_pfname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1 + i); + dt_header_fmt_func(info.dthi_pfname, pvp->pv_desc.dtvd_name); + + + if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0) + return (-1); /* dt_errno is set for us */ + if (fprintf(out, "\n\n") < 0) + return (dt_set_errno(dtp, errno)); + if (dt_idhash_iter(pvp->pv_probes, dt_header_decl, &info) != 0) + return (-1); /* dt_errno is set for us */ + + return (0); +} + +int +dtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname) +{ + dt_provider_t *pvp; + char *mfname, *p; + + if (fname != NULL) { + if ((p = strrchr(fname, '/')) != NULL) + fname = p + 1; + + mfname = alloca(strlen(fname) + 1); + dt_header_fmt_macro(mfname, fname); + if (fprintf(out, "#ifndef\t_%s\n#define\t_%s\n\n", + mfname, mfname) < 0) + return (dt_set_errno(dtp, errno)); + } + + if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0) + return (-1); + + for (pvp = dt_list_next(&dtp->dt_provlist); + pvp != NULL; pvp = dt_list_next(pvp)) { + if (dt_header_provider(dtp, pvp, out) != 0) + return (-1); /* dt_errno is set for us */ + } + + if (fprintf(out, "\n#ifdef\t__cplusplus\n}\n#endif\n") < 0) + return (dt_set_errno(dtp, errno)); + + if (fname != NULL && fprintf(out, "\n#endif\t/* _%s */\n", mfname) < 0) + return (dt_set_errno(dtp, errno)); + + return (0); +} diff --git a/usr/src/lib/libdtrace/common/dt_work.c b/usr/src/lib/libdtrace/common/dt_work.c index 64cc8ff176..97a7f62d69 100644 --- a/usr/src/lib/libdtrace/common/dt_work.c +++ b/usr/src/lib/libdtrace/common/dt_work.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,7 +48,7 @@ dtrace_sleep(dtrace_hdl_t *dtp) { dt_proc_hash_t *dph = dtp->dt_procs; dtrace_optval_t policy = dtp->dt_options[DTRACEOPT_BUFPOLICY]; - dt_proc_t *dpr; + dt_proc_notify_t *dprn; hrtime_t earliest = INT64_MAX; struct timespec tv; @@ -91,12 +92,18 @@ dtrace_sleep(dtrace_hdl_t *dtp) */ (void) pthread_cond_reltimedwait_np(&dph->dph_cv, &dph->dph_lock, &tv); - while ((dpr = dph->dph_notify) != NULL) { - dph->dph_notify = dpr->dpr_notify; - dpr->dpr_notify = NULL; + while ((dprn = dph->dph_notify) != NULL) { + if (dtp->dt_prochdlr != NULL) { + char *err = dprn->dprn_errmsg; + if (*err == '\0') + err = NULL; + + dtp->dt_prochdlr(dprn->dprn_dpr->dpr_proc, err, + dtp->dt_procarg); + } - if (dtp->dt_prochdlr != NULL) - dtp->dt_prochdlr(dpr->dpr_proc, dtp->dt_procarg); + dph->dph_notify = dprn->dprn_next; + dt_free(dtp, dprn); } (void) pthread_mutex_unlock(&dph->dph_lock); diff --git a/usr/src/lib/libdtrace/common/dtrace.h b/usr/src/lib/libdtrace/common/dtrace.h index 3d5998cb2f..fb0738bf38 100644 --- a/usr/src/lib/libdtrace/common/dtrace.h +++ b/usr/src/lib/libdtrace/common/dtrace.h @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,7 +50,7 @@ extern "C" { * Please refer to the "Solaris Dynamic Tracing Guide" for more information. */ -#define DTRACE_VERSION 2 /* library ABI interface version */ +#define DTRACE_VERSION 3 /* library ABI interface version */ struct ps_prochandle; typedef struct dtrace_hdl dtrace_hdl_t; @@ -133,6 +134,8 @@ extern void dtrace_program_info(dtrace_hdl_t *, dtrace_prog_t *, extern int dtrace_program_link(dtrace_hdl_t *, dtrace_prog_t *, uint_t, const char *, int, char *const []); +extern int dtrace_program_header(dtrace_hdl_t *, FILE *, const char *); + extern void *dtrace_dof_create(dtrace_hdl_t *, dtrace_prog_t *, uint_t); extern void dtrace_dof_destroy(dtrace_hdl_t *, void *); @@ -294,7 +297,7 @@ typedef struct dtrace_dropdata { typedef int dtrace_handle_drop_f(const dtrace_dropdata_t *, void *); extern int dtrace_handle_drop(dtrace_hdl_t *, dtrace_handle_drop_f *, void *); -typedef void dtrace_handle_proc_f(struct ps_prochandle *, void *); +typedef void dtrace_handle_proc_f(struct ps_prochandle *, const char *, void *); extern int dtrace_handle_proc(dtrace_hdl_t *, dtrace_handle_proc_f *, void *); #define DTRACE_BUFDATA_AGGKEY 0x0001 /* aggregation key */ |