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)) return (dt_pid_per_mod(pp, pmp, obj)); #if defined(sun) (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); #else pp->dpp_lmid = 0; #endif if ((pp->dpp_obj = strrchr(obj, '/')) == NULL) pp->dpp_obj = obj; else pp->dpp_obj++; if (gmatch(pp->dpp_obj, pp->dpp_mod)) return (dt_pid_per_mod(pp, pmp, obj)); #if defined(sun) (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); #endif dt_pid_objname(name, sizeof (name), pp->dpp_lmid, pp->dpp_obj); if (gmatch(name, pp->dpp_mod)) return (dt_pid_per_mod(pp, pmp, obj)); return (0); }
static const prmap_t * dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P) { char m[MAXPATHLEN]; #if defined(sun) Lmid_t lmid = PR_LMID_EVERY; #else Lmid_t lmid = 0; #endif const char *obj; const prmap_t *pmp; #if defined(sun) /* * Pick apart the link map from the library name. */ if (strchr(pdp->dtpd_mod, '`') != NULL) { char *end; if (strncmp(pdp->dtpd_mod, "LM", 2) != 0 || !isdigit(pdp->dtpd_mod[2])) return (NULL); lmid = strtoul(&pdp->dtpd_mod[2], &end, 16); obj = end + 1; if (*end != '`' || strchr(obj, '`') != NULL) return (NULL); } 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]; else obj++; (void) Plmid(P, pmp->pr_vaddr, &lmid); #endif dt_pid_objname(pdp->dtpd_mod, sizeof (pdp->dtpd_mod), lmid, obj); return (pmp); }
/* ARGSUSED */ static int dt_module_load_proc_build(void *arg, const prmap_t *prmap, const char *obj) { ctf_file_t *fp; char buf[MAXPATHLEN], *p; dt_module_cb_arg_t *dcp = arg; int count = dcp->dpa_count; Lmid_t lmid; fp = Pname_to_ctf(dcp->dpa_proc, obj); if (fp == NULL) return (0); fp = ctf_dup(fp); if (fp == NULL) return (0); dcp->dpa_dmp->dm_libctfp[count] = fp; /* * While it'd be nice to simply use objname here, because of our prior * actions we'll always get a resolved object name to its on disk file. * Like the pid provider, we need to tell a bit of a lie here. The type * that the user thinks of is in terms of the libraries they requested, * eg. libc.so.1, they don't care about the fact that it's * libc_hwcap.so.1. */ (void) Pobjname(dcp->dpa_proc, prmap->pr_vaddr, buf, sizeof (buf)); if ((p = strrchr(buf, '/')) == NULL) p = buf; else p++; /* * If for some reason we can't find a link map id for this module, which * would be really quite weird. We instead just say the link map id is * zero. */ if (Plmid(dcp->dpa_proc, prmap->pr_vaddr, &lmid) != 0) lmid = 0; if (lmid == 0) dcp->dpa_dmp->dm_libctfn[count] = strdup(p); else (void) asprintf(&dcp->dpa_dmp->dm_libctfn[count], "LM%x`%s", lmid, p); if (dcp->dpa_dmp->dm_libctfn[count] == NULL) return (1); ctf_setspecific(fp, dcp->dpa_dmp); dcp->dpa_count++; return (0); }
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 (0); #if defined(sun) (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); #endif if ((pp->dpp_obj = strrchr(obj, '/')) == NULL) 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) pp->dpp_stret[0] = sym.st_value; else pp->dpp_stret[0] = 0; if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret2", &sym, NULL) == 0) pp->dpp_stret[1] = sym.st_value; else pp->dpp_stret[1] = 0; if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret4", &sym, NULL) == 0) pp->dpp_stret[2] = sym.st_value; else pp->dpp_stret[2] = 0; if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret8", &sym, NULL) == 0) pp->dpp_stret[3] = sym.st_value; else pp->dpp_stret[3] = 0; #else 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, (u_longlong_t)pp->dpp_stret[0], (u_longlong_t)pp->dpp_stret[1], (u_longlong_t)pp->dpp_stret[2], (u_longlong_t)pp->dpp_stret[3]); /* * If pp->dpp_func contains any globbing meta-characters, we need * to iterate over the symbol table and compare each function name * against the pattern. */ if (!strisglob(pp->dpp_func)) { /* * If we fail to lookup the symbol, try interpreting the * function as the special "-" function that indicates that the * probe name should be interpreted as a absolute virtual * address. If that fails and we were matching a specific * function in a specific module, report the error, otherwise * just fail silently in the hopes that some other object will * contain the desired symbol. */ if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, pp->dpp_func, &sym, NULL) != 0) { if (strcmp("-", pp->dpp_func) == 0) { sym.st_name = 0; sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_FUNC); sym.st_other = 0; sym.st_value = 0; #if defined(sun) sym.st_size = Pstatus(pp->dpp_pr)->pr_dmodel == PR_MODEL_ILP32 ? -1U : -1ULL; #else sym.st_size = ~((Elf64_Xword) 0); #endif } else if (!strisglob(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 (0); } } /* * Only match defined functions of non-zero size. */ if (GELF_ST_TYPE(sym.st_info) != STT_FUNC || sym.st_shndx == SHN_UNDEF || sym.st_size == 0) return (0); /* * We don't instrument PLTs -- they're dynamically rewritten, * and, so, inherently dicey to instrument. */ #ifdef DOODAD if (Ppltdest(pp->dpp_pr, sym.st_value) != NULL) return (0); #endif (void) Plookup_by_addr(pp->dpp_pr, sym.st_value, pp->dpp_func, DTRACE_FUNCNAMELEN, &sym); return (dt_pid_per_sym(pp, &sym, pp->dpp_func)); } else { uint_t nmatches = pp->dpp_nmatches; 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. */ 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); }