Path: blob/main/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
39562 views
/*1* CDDL HEADER START2*3* The contents of this file are subject to the terms of the4* Common Development and Distribution License (the "License").5* You may not use this file except in compliance with the License.6*7* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE8* or http://www.opensolaris.org/os/licensing.9* See the License for the specific language governing permissions10* and limitations under the License.11*12* When distributing Covered Code, include this CDDL HEADER in each13* file and include the License file at usr/src/OPENSOLARIS.LICENSE.14* If applicable, add the following below this CDDL HEADER, with the15* fields enclosed by brackets "[]" replaced with your own identifying16* information: Portions Copyright [yyyy] [name of copyright owner]17*18* CDDL HEADER END19*/2021/*22* Copyright 2010 Sun Microsystems, Inc. All rights reserved.23* Use is subject to license terms.24*/25/*26* Copyright (c) 2013, Joyent, Inc. All rights reserved.27*/2829#include <assert.h>30#include <strings.h>31#include <stdlib.h>32#include <stdio.h>33#include <errno.h>34#include <ctype.h>35#ifdef illumos36#include <alloca.h>37#endif38#include <libgen.h>39#include <stddef.h>40#include <sys/sysmacros.h>4142#include <dt_impl.h>43#include <dt_program.h>44#include <dt_pid.h>45#include <dt_string.h>46#include <dt_module.h>4748#ifndef illumos49#include <sys/sysctl.h>50#include <unistd.h>51#include <libproc_compat.h>52#include <libelf.h>53#include <gelf.h>54#endif5556typedef struct dt_pid_probe {57dtrace_hdl_t *dpp_dtp;58dt_pcb_t *dpp_pcb;59dt_proc_t *dpp_dpr;60struct ps_prochandle *dpp_pr;61const char *dpp_mod;62char *dpp_func;63const char *dpp_name;64const char *dpp_obj;65uintptr_t dpp_pc;66size_t dpp_size;67Lmid_t dpp_lmid;68uint_t dpp_nmatches;69uint64_t dpp_stret[4];70GElf_Sym dpp_last;71uint_t dpp_last_taken;72} dt_pid_probe_t;7374/*75* Compose the lmid and object name into the canonical representation. We76* omit the lmid for the default link map for convenience.77*/78static void79dt_pid_objname(char *buf, size_t len, Lmid_t lmid, const char *obj)80{81#ifdef illumos82if (lmid == LM_ID_BASE)83(void) strncpy(buf, obj, len);84else85(void) snprintf(buf, len, "LM%lx`%s", lmid, obj);86#else87(void) strncpy(buf, obj, len);88#endif89}9091static int92dt_pid_error(dtrace_hdl_t *dtp, dt_pcb_t *pcb, dt_proc_t *dpr,93fasttrap_probe_spec_t *ftp, dt_errtag_t tag, const char *fmt, ...)94{95va_list ap;96int len;9798if (ftp != NULL)99dt_free(dtp, ftp);100101va_start(ap, fmt);102if (pcb == NULL) {103assert(dpr != NULL);104len = vsnprintf(dpr->dpr_errmsg, sizeof (dpr->dpr_errmsg),105fmt, ap);106assert(len >= 2);107if (dpr->dpr_errmsg[len - 2] == '\n')108dpr->dpr_errmsg[len - 2] = '\0';109} else {110dt_set_errmsg(dtp, dt_errtag(tag), pcb->pcb_region,111pcb->pcb_filetag, pcb->pcb_fileptr ? yylineno : 0, fmt, ap);112}113va_end(ap);114115return (1);116}117118static int119dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)120{121dtrace_hdl_t *dtp = pp->dpp_dtp;122dt_pcb_t *pcb = pp->dpp_pcb;123dt_proc_t *dpr = pp->dpp_dpr;124fasttrap_probe_spec_t *ftp;125uint64_t off;126char *end;127uint_t nmatches = 0;128ulong_t sz;129int glob, err;130int isdash = strcmp("-", func) == 0;131pid_t pid;132133#ifdef illumos134pid = Pstatus(pp->dpp_pr)->pr_pid;135#else136pid = proc_getpid(pp->dpp_pr);137#endif138139dt_dprintf("creating probe pid%d:%s:%s:%s\n", (int)pid, pp->dpp_obj,140func, pp->dpp_name);141142sz = sizeof (fasttrap_probe_spec_t) + (isdash ? 4 :143(symp->st_size - 1) * sizeof (ftp->ftps_offs[0]));144145if ((ftp = dt_alloc(dtp, sz)) == NULL) {146dt_dprintf("proc_per_sym: dt_alloc(%lu) failed\n", sz);147return (1); /* errno is set for us */148}149150ftp->ftps_pid = pid;151(void) strncpy(ftp->ftps_func, func, sizeof (ftp->ftps_func));152153dt_pid_objname(ftp->ftps_mod, sizeof (ftp->ftps_mod), pp->dpp_lmid,154pp->dpp_obj);155156if (!isdash && gmatch("return", pp->dpp_name)) {157if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp,158pp->dpp_stret) < 0) {159return (dt_pid_error(dtp, pcb, dpr, ftp,160D_PROC_CREATEFAIL, "failed to create return probe "161"for '%s': %s", func,162dtrace_errmsg(dtp, dtrace_errno(dtp))));163}164165nmatches++;166}167168if (!isdash && gmatch("entry", pp->dpp_name)) {169if (dt_pid_create_entry_probe(pp->dpp_pr, dtp, ftp, symp) < 0) {170return (dt_pid_error(dtp, pcb, dpr, ftp,171D_PROC_CREATEFAIL, "failed to create entry probe "172"for '%s': %s", func,173dtrace_errmsg(dtp, dtrace_errno(dtp))));174}175176nmatches++;177}178179glob = strisglob(pp->dpp_name);180if (!glob && nmatches == 0) {181off = strtoull(pp->dpp_name, &end, 16);182if (*end != '\0') {183return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_NAME,184"'%s' is an invalid probe name", pp->dpp_name));185}186187if (off >= symp->st_size) {188return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_OFF,189"offset 0x%llx outside of function '%s'",190(u_longlong_t)off, func));191}192193err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp,194symp, off);195196if (err == DT_PROC_ERR) {197return (dt_pid_error(dtp, pcb, dpr, ftp,198D_PROC_CREATEFAIL, "failed to create probe at "199"'%s+0x%llx': %s", func, (u_longlong_t)off,200dtrace_errmsg(dtp, dtrace_errno(dtp))));201}202203if (err == DT_PROC_ALIGN) {204return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_ALIGN,205"offset 0x%llx is not aligned on an instruction",206(u_longlong_t)off));207}208209nmatches++;210211} else if (glob && !isdash) {212if (dt_pid_create_glob_offset_probes(pp->dpp_pr,213pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) {214return (dt_pid_error(dtp, pcb, dpr, ftp,215D_PROC_CREATEFAIL,216"failed to create offset probes in '%s': %s", func,217dtrace_errmsg(dtp, dtrace_errno(dtp))));218}219220nmatches++;221}222223pp->dpp_nmatches += nmatches;224225dt_free(dtp, ftp);226227return (0);228}229230static int231dt_pid_sym_filt(void *arg, const GElf_Sym *symp, const char *func)232{233dt_pid_probe_t *pp = arg;234235if (symp->st_shndx == SHN_UNDEF)236return (0);237238if (symp->st_size == 0) {239dt_dprintf("st_size of %s is zero\n", func);240return (0);241}242243if (pp->dpp_last_taken == 0 ||244symp->st_value != pp->dpp_last.st_value ||245symp->st_size != pp->dpp_last.st_size) {246/*247* Due to 4524008, _init and _fini may have a bloated st_size.248* While this bug has been fixed for a while, old binaries249* may exist that still exhibit this problem. As a result, we250* don't match _init and _fini though we allow users to251* specify them explicitly.252*/253if (strcmp(func, "_init") == 0 || strcmp(func, "_fini") == 0)254return (0);255256if ((pp->dpp_last_taken = gmatch(func, pp->dpp_func)) != 0) {257pp->dpp_last = *symp;258return (dt_pid_per_sym(pp, symp, func));259}260}261262return (0);263}264265static int266dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)267{268dt_pid_probe_t *pp = arg;269dtrace_hdl_t *dtp = pp->dpp_dtp;270dt_pcb_t *pcb = pp->dpp_pcb;271dt_proc_t *dpr = pp->dpp_dpr;272GElf_Sym sym;273274if (obj == NULL)275return (0);276277#ifdef illumos278(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);279#endif280281282if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)283pp->dpp_obj = obj;284else285pp->dpp_obj++;286#ifdef illumos287if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret1", &sym,288NULL) == 0)289pp->dpp_stret[0] = sym.st_value;290else291pp->dpp_stret[0] = 0;292293if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret2", &sym,294NULL) == 0)295pp->dpp_stret[1] = sym.st_value;296else297pp->dpp_stret[1] = 0;298299if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret4", &sym,300NULL) == 0)301pp->dpp_stret[2] = sym.st_value;302else303pp->dpp_stret[2] = 0;304305if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret8", &sym,306NULL) == 0)307pp->dpp_stret[3] = sym.st_value;308else309pp->dpp_stret[3] = 0;310#else311pp->dpp_stret[0] = 0;312pp->dpp_stret[1] = 0;313pp->dpp_stret[2] = 0;314pp->dpp_stret[3] = 0;315#endif316317dt_dprintf("%s stret %llx %llx %llx %llx\n", obj,318(u_longlong_t)pp->dpp_stret[0], (u_longlong_t)pp->dpp_stret[1],319(u_longlong_t)pp->dpp_stret[2], (u_longlong_t)pp->dpp_stret[3]);320321/*322* If pp->dpp_func contains any globbing meta-characters, we need323* to iterate over the symbol table and compare each function name324* against the pattern.325*/326if (!strisglob(pp->dpp_func)) {327/*328* If we fail to lookup the symbol, try interpreting the329* function as the special "-" function that indicates that the330* probe name should be interpreted as a absolute virtual331* address. If that fails and we were matching a specific332* function in a specific module, report the error, otherwise333* just fail silently in the hopes that some other object will334* contain the desired symbol.335*/336if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj,337pp->dpp_func, &sym, NULL) != 0) {338if (strcmp("-", pp->dpp_func) == 0) {339sym.st_name = 0;340sym.st_info =341GELF_ST_INFO(STB_LOCAL, STT_FUNC);342sym.st_other = 0;343sym.st_value = 0;344#ifdef illumos345sym.st_size = Pstatus(pp->dpp_pr)->pr_dmodel ==346PR_MODEL_ILP32 ? -1U : -1ULL;347#else348sym.st_size = ~((Elf64_Xword) 0);349#endif350351} else if (!strisglob(pp->dpp_mod)) {352return (dt_pid_error(dtp, pcb, dpr, NULL,353D_PROC_FUNC,354"failed to lookup '%s' in module '%s'",355pp->dpp_func, pp->dpp_mod));356} else {357return (0);358}359}360361/*362* Only match defined functions of non-zero size.363*/364if (GELF_ST_TYPE(sym.st_info) != STT_FUNC ||365sym.st_shndx == SHN_UNDEF || sym.st_size == 0)366return (0);367368/*369* We don't instrument PLTs -- they're dynamically rewritten,370* and, so, inherently dicey to instrument.371*/372#ifdef DOODAD373if (Ppltdest(pp->dpp_pr, sym.st_value) != NULL)374return (0);375#endif376377(void) Plookup_by_addr(pp->dpp_pr, sym.st_value, pp->dpp_func,378DTRACE_FUNCNAMELEN, &sym);379380return (dt_pid_per_sym(pp, &sym, pp->dpp_func));381} else {382uint_t nmatches = pp->dpp_nmatches;383384if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB,385BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)386return (1);387388if (nmatches == pp->dpp_nmatches) {389/*390* If we didn't match anything in the PR_SYMTAB, try391* the PR_DYNSYM.392*/393if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_DYNSYM,394BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)395return (1);396}397}398399return (0);400}401402static int403dt_pid_mod_filt(void *arg, const prmap_t *pmp, const char *obj)404{405char name[DTRACE_MODNAMELEN];406dt_pid_probe_t *pp = arg;407408if (gmatch(obj, pp->dpp_mod))409return (dt_pid_per_mod(pp, pmp, obj));410411#ifdef illumos412(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);413#else414pp->dpp_lmid = 0;415#endif416417if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)418pp->dpp_obj = obj;419else420pp->dpp_obj++;421422if (gmatch(pp->dpp_obj, pp->dpp_mod))423return (dt_pid_per_mod(pp, pmp, obj));424425#ifdef illumos426(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);427#endif428429dt_pid_objname(name, sizeof (name), pp->dpp_lmid, pp->dpp_obj);430431if (gmatch(name, pp->dpp_mod))432return (dt_pid_per_mod(pp, pmp, obj));433434return (0);435}436437static const prmap_t *438dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)439{440char m[MAXPATHLEN];441Lmid_t lmid = PR_LMID_EVERY;442const char *obj;443const prmap_t *pmp;444445/*446* Pick apart the link map from the library name.447*/448if (strchr(pdp->dtpd_mod, '`') != NULL) {449char *end;450451if (strncmp(pdp->dtpd_mod, "LM", 2) != 0 ||452!isdigit(pdp->dtpd_mod[2]))453return (NULL);454455lmid = strtoul(&pdp->dtpd_mod[2], &end, 16);456457obj = end + 1;458459if (*end != '`' || strchr(obj, '`') != NULL)460return (NULL);461462} else {463obj = pdp->dtpd_mod;464}465466if ((pmp = Plmid_to_map(P, lmid, obj)) == NULL)467return (NULL);468469(void) Pobjname(P, pmp->pr_vaddr, m, sizeof (m));470if ((obj = strrchr(m, '/')) == NULL)471obj = &m[0];472else473obj++;474475#ifdef illumos476(void) Plmid(P, pmp->pr_vaddr, &lmid);477#endif478479dt_pid_objname(pdp->dtpd_mod, sizeof (pdp->dtpd_mod), lmid, obj);480481return (pmp);482}483484485static int486dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,487dt_pcb_t *pcb, dt_proc_t *dpr)488{489dt_pid_probe_t pp;490int ret = 0;491492pp.dpp_dtp = dtp;493pp.dpp_dpr = dpr;494pp.dpp_pr = dpr->dpr_proc;495pp.dpp_pcb = pcb;496497#ifdef DOODAD498/*499* We can only trace dynamically-linked executables (since we've500* hidden some magic in ld.so.1 as well as libc.so.1).501*/502if (Pname_to_map(pp.dpp_pr, PR_OBJ_LDSO) == NULL) {503return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_DYN,504"process %s is not a dynamically-linked executable",505&pdp->dtpd_provider[3]));506}507#endif508509pp.dpp_mod = pdp->dtpd_mod[0] != '\0' ? pdp->dtpd_mod : "*";510pp.dpp_func = pdp->dtpd_func[0] != '\0' ? pdp->dtpd_func : "*";511pp.dpp_name = pdp->dtpd_name[0] != '\0' ? pdp->dtpd_name : "*";512pp.dpp_last_taken = 0;513514if (strcmp(pp.dpp_func, "-") == 0) {515const prmap_t *aout, *pmp;516517if (pdp->dtpd_mod[0] == '\0') {518pp.dpp_mod = pdp->dtpd_mod;519(void) strcpy(pdp->dtpd_mod, "a.out");520} else if (strisglob(pp.dpp_mod) ||521(aout = Pname_to_map(pp.dpp_pr, "a.out")) == NULL ||522(pmp = Pname_to_map(pp.dpp_pr, pp.dpp_mod)) == NULL ||523aout->pr_vaddr != pmp->pr_vaddr) {524return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_LIB,525"only the a.out module is valid with the "526"'-' function"));527}528529if (strisglob(pp.dpp_name)) {530return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_NAME,531"only individual addresses may be specified "532"with the '-' function"));533}534}535536/*537* If pp.dpp_mod contains any globbing meta-characters, we need538* to iterate over each module and compare its name against the539* pattern. An empty module name is treated as '*'.540*/541if (strisglob(pp.dpp_mod)) {542ret = Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp);543} else {544const prmap_t *pmp;545char *obj;546547/*548* If we can't find a matching module, don't sweat it -- either549* we'll fail the enabling because the probes don't exist or550* we'll wait for that module to come along.551*/552if ((pmp = dt_pid_fix_mod(pdp, pp.dpp_pr)) != NULL) {553if ((obj = strchr(pdp->dtpd_mod, '`')) == NULL)554obj = pdp->dtpd_mod;555else556obj++;557558ret = dt_pid_per_mod(&pp, pmp, obj);559}560}561562return (ret);563}564565static int566dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)567{568struct ps_prochandle *P = data;569GElf_Sym sym;570prsyminfo_t sip;571dof_helper_t dh;572GElf_Half e_type;573const char *mname;574const char *syms[] = { "___SUNW_dof", "__SUNW_dof" };575int i, fd = -1;576577/*578* The symbol ___SUNW_dof is for lazy-loaded DOF sections, and579* __SUNW_dof is for actively-loaded DOF sections. We try to force580* in both types of DOF section since the process may not yet have581* run the code to instantiate these providers.582*/583for (i = 0; i < 2; i++) {584if (Pxlookup_by_name(P, PR_LMID_EVERY, oname, syms[i], &sym,585&sip) != 0) {586continue;587}588589if ((mname = strrchr(oname, '/')) == NULL)590mname = oname;591else592mname++;593594dt_dprintf("lookup of %s succeeded for %s\n", syms[i], mname);595596if (Pread(P, &e_type, sizeof (e_type), pmp->pr_vaddr +597offsetof(Elf64_Ehdr, e_type)) != sizeof (e_type)) {598dt_dprintf("read of ELF header failed");599continue;600}601602dh.dofhp_dof = sym.st_value;603dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr;604605dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod),606sip.prs_lmid, mname);607608#ifdef __FreeBSD__609dh.dofhp_pid = proc_getpid(P);610611if (fd == -1 &&612(fd = open("/dev/dtrace/helper", O_RDWR, 0)) < 0) {613dt_dprintf("open of helper device failed: %s\n",614strerror(errno));615return (-1); /* errno is set for us */616}617618if (ioctl(fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0)619dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod);620#else621if (fd == -1 &&622(fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) {623dt_dprintf("pr_open of helper device failed: %s\n",624strerror(errno));625return (-1); /* errno is set for us */626}627628if (pr_ioctl(P, fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0)629dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod);630#endif631}632633if (fd != -1)634#ifdef __FreeBSD__635(void) close(fd);636#else637(void) pr_close(P, fd);638#endif639640return (0);641}642643static int644dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,645dt_pcb_t *pcb, dt_proc_t *dpr)646{647struct ps_prochandle *P = dpr->dpr_proc;648int ret = 0;649650assert(DT_MUTEX_HELD(&dpr->dpr_lock));651(void) Pupdate_maps(P);652if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) {653ret = -1;654(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT,655"failed to instantiate probes for pid %d: %s",656#ifdef illumos657(int)Pstatus(P)->pr_pid, strerror(errno));658#else659(int)proc_getpid(P), strerror(errno));660#endif661}662663/*664* Put the module name in its canonical form.665*/666(void) dt_pid_fix_mod(pdp, P);667668return (ret);669}670671static pid_t672dt_pid_get_pid(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb,673dt_proc_t *dpr)674{675pid_t pid;676char *c, *last = NULL, *end;677678for (c = &pdp->dtpd_provider[0]; *c != '\0'; c++) {679if (!isdigit(*c))680last = c;681}682683if (last == NULL || (*(++last) == '\0')) {684(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPROV,685"'%s' is not a valid provider", pdp->dtpd_provider);686return (-1);687}688689errno = 0;690pid = strtol(last, &end, 10);691692if (errno != 0 || end == last || end[0] != '\0' || pid <= 0) {693(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPID,694"'%s' does not contain a valid pid", pdp->dtpd_provider);695return (-1);696}697698return (pid);699}700701int702dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)703{704char provname[DTRACE_PROVNAMELEN];705struct ps_prochandle *P;706dt_proc_t *dpr;707pid_t pid;708int err = 0;709710assert(pcb != NULL);711712if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1)713return (-1);714715if (dtp->dt_ftfd == -1) {716if (dtp->dt_fterr == ENOENT) {717(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,718"pid provider is not installed on this system");719} else {720(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,721"pid provider is not available: %s",722strerror(dtp->dt_fterr));723}724725return (-1);726}727728(void) snprintf(provname, sizeof (provname), "pid%d", (int)pid);729730if (gmatch(provname, pdp->dtpd_provider) != 0) {731#ifdef __FreeBSD__732if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL)733#else734if ((P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE,7350)) == NULL)736#endif737{738(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,739"failed to grab process %d", (int)pid);740return (-1);741}742743dpr = dt_proc_lookup(dtp, P, 0);744assert(dpr != NULL);745(void) pthread_mutex_lock(&dpr->dpr_lock);746747if ((err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr)) == 0) {748/*749* Alert other retained enablings which may match750* against the newly created probes.751*/752(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);753}754755(void) pthread_mutex_unlock(&dpr->dpr_lock);756dt_proc_release(dtp, P);757}758759/*760* If it's not strictly a pid provider, we might match a USDT provider.761*/762if (strcmp(provname, pdp->dtpd_provider) != 0) {763if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL) {764(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,765"failed to grab process %d", (int)pid);766return (-1);767}768769dpr = dt_proc_lookup(dtp, P, 0);770assert(dpr != NULL);771(void) pthread_mutex_lock(&dpr->dpr_lock);772773if (!dpr->dpr_usdt) {774err = dt_pid_create_usdt_probes(pdp, dtp, pcb, dpr);775dpr->dpr_usdt = B_TRUE;776}777778(void) pthread_mutex_unlock(&dpr->dpr_lock);779dt_proc_release(dtp, P);780}781782return (err ? -1 : 0);783}784785int786dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)787{788dtrace_enable_io_t args;789dtrace_prog_t *pgp;790dt_stmt_t *stp;791dtrace_probedesc_t *pdp, pd;792pid_t pid;793int ret = 0, found = B_FALSE;794char provname[DTRACE_PROVNAMELEN];795796(void) snprintf(provname, sizeof (provname), "pid%d",797(int)dpr->dpr_pid);798799for (pgp = dt_list_next(&dtp->dt_programs); pgp != NULL;800pgp = dt_list_next(pgp)) {801802for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL;803stp = dt_list_next(stp)) {804805pdp = &stp->ds_desc->dtsd_ecbdesc->dted_probe;806pid = dt_pid_get_pid(pdp, dtp, NULL, dpr);807if (pid != dpr->dpr_pid)808continue;809810found = B_TRUE;811812pd = *pdp;813814if (gmatch(provname, pdp->dtpd_provider) != 0 &&815dt_pid_create_pid_probes(&pd, dtp, NULL, dpr) != 0)816ret = 1;817818/*819* If it's not strictly a pid provider, we might match820* a USDT provider.821*/822if (strcmp(provname, pdp->dtpd_provider) != 0 &&823dt_pid_create_usdt_probes(&pd, dtp, NULL, dpr) != 0)824ret = 1;825}826}827828if (found) {829/*830* Give DTrace a shot to the ribs to get it to check831* out the newly created probes.832*/833args.dof = NULL;834args.n_matched = 0;835(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, &args);836}837838return (ret);839}840841/*842* libdtrace has a backroom deal with us to ask us for type information on843* behalf of pid provider probes when fasttrap doesn't return any type844* information. Instead we'll look up the module and see if there is type845* information available. However, if there is no type information available due846* to a lack of CTF data, then we want to make sure that DTrace still carries on847* in face of that. As such we don't have a meaningful exit code about failure.848* We emit information about why we failed to the dtrace debug log so someone849* can figure it out by asking nicely for DTRACE_DEBUG.850*/851void852dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,853dtrace_argdesc_t *adp, int *nargs)854{855dt_module_t *dmp;856ctf_file_t *fp;857ctf_funcinfo_t f;858ctf_id_t argv[32];859GElf_Sym sym;860prsyminfo_t si;861struct ps_prochandle *p;862int i, args;863char buf[DTRACE_ARGTYPELEN];864const char *mptr;865char *eptr;866int ret = 0;867int argc = sizeof (argv) / sizeof (ctf_id_t);868Lmid_t lmid;869870/* Set up a potential outcome */871args = *nargs;872*nargs = 0;873874/*875* If we don't have an entry or return probe then we can just stop right876* now as we don't have arguments for offset probes.877*/878if (strcmp(pdp->dtpd_name, "entry") != 0 &&879strcmp(pdp->dtpd_name, "return") != 0)880return;881882dmp = dt_module_create(dtp, pdp->dtpd_provider);883if (dmp == NULL) {884dt_dprintf("failed to find module for %s\n",885pdp->dtpd_provider);886return;887}888if (dt_module_load(dtp, dmp) != 0) {889dt_dprintf("failed to load module for %s\n",890pdp->dtpd_provider);891return;892}893894/*895* We may be working with a module that doesn't have ctf. If that's the896* case then we just return now and move on with life.897*/898fp = dt_module_getctflib(dtp, dmp, pdp->dtpd_mod);899if (fp == NULL) {900dt_dprintf("no ctf container for %s\n",901pdp->dtpd_mod);902return;903}904p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);905if (p == NULL) {906dt_dprintf("failed to grab pid\n");907return;908}909dt_proc_lock(dtp, p);910911/*912* Check to see if the D module has a link map ID and separate that out913* for properly interrogating libproc.914*/915if ((mptr = strchr(pdp->dtpd_mod, '`')) != NULL) {916if (strlen(pdp->dtpd_mod) < 3) {917dt_dprintf("found weird modname with linkmap, "918"aborting: %s\n", pdp->dtpd_mod);919goto out;920}921if (pdp->dtpd_mod[0] != 'L' || pdp->dtpd_mod[1] != 'M') {922dt_dprintf("missing leading 'LM', "923"aborting: %s\n", pdp->dtpd_mod);924goto out;925}926errno = 0;927lmid = strtol(pdp->dtpd_mod + 2, &eptr, 16);928if (errno == ERANGE || eptr != mptr) {929dt_dprintf("failed to parse out lmid, aborting: %s\n",930pdp->dtpd_mod);931goto out;932}933mptr++;934} else {935mptr = pdp->dtpd_mod;936lmid = 0;937}938939if (Pxlookup_by_name(p, lmid, mptr, pdp->dtpd_func,940&sym, &si) != 0) {941dt_dprintf("failed to find function %s in %s`%s\n",942pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);943goto out;944}945if (ctf_func_info(fp, si.prs_id, &f) == CTF_ERR) {946dt_dprintf("failed to get ctf information for %s in %s`%s\n",947pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);948goto out;949}950951(void) snprintf(buf, sizeof (buf), "%s`%s", pdp->dtpd_provider,952pdp->dtpd_mod);953954if (strcmp(pdp->dtpd_name, "return") == 0) {955if (args < 2)956goto out;957958bzero(adp, sizeof (dtrace_argdesc_t));959adp->dtargd_ndx = 0;960adp->dtargd_id = pdp->dtpd_id;961adp->dtargd_mapping = adp->dtargd_ndx;962/*963* We explicitly leave out the library here, we only care that964* it is some int. We are assuming that there is no ctf965* container in here that is lying about what an int is.966*/967(void) snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,968"user %s`%s", pdp->dtpd_provider, "int");969adp++;970bzero(adp, sizeof (dtrace_argdesc_t));971adp->dtargd_ndx = 1;972adp->dtargd_id = pdp->dtpd_id;973adp->dtargd_mapping = adp->dtargd_ndx;974ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,975"userland ");976(void) ctf_type_qname(fp, f.ctc_return, adp->dtargd_native +977ret, DTRACE_ARGTYPELEN - ret, buf);978*nargs = 2;979} else {980if (ctf_func_args(fp, si.prs_id, argc, argv) == CTF_ERR)981goto out;982983*nargs = MIN(args, f.ctc_argc);984for (i = 0; i < *nargs; i++, adp++) {985bzero(adp, sizeof (dtrace_argdesc_t));986adp->dtargd_ndx = i;987adp->dtargd_id = pdp->dtpd_id;988adp->dtargd_mapping = adp->dtargd_ndx;989ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,990"userland ");991(void) ctf_type_qname(fp, argv[i], adp->dtargd_native +992ret, DTRACE_ARGTYPELEN - ret, buf);993}994}995out:996dt_proc_unlock(dtp, p);997dt_proc_release(dtp, p);998}99910001001