Home | History | Annotate | Download | only in common
      1     0    stevel /*
      2     0    stevel  * CDDL HEADER START
      3     0    stevel  *
      4     0    stevel  * The contents of this file are subject to the terms of the
      5  1593       ahl  * Common Development and Distribution License (the "License").
      6  1593       ahl  * You may not use this file except in compliance with the License.
      7     0    stevel  *
      8     0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0    stevel  * or http://www.opensolaris.org/os/licensing.
     10     0    stevel  * See the License for the specific language governing permissions
     11     0    stevel  * and limitations under the License.
     12     0    stevel  *
     13     0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0    stevel  *
     19     0    stevel  * CDDL HEADER END
     20     0    stevel  */
     21  1399       ahl 
     22     0    stevel /*
     23  5984   jhaslam  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24     0    stevel  * Use is subject to license terms.
     25     0    stevel  */
     26     0    stevel 
     27     0    stevel #include <assert.h>
     28     0    stevel #include <strings.h>
     29     0    stevel #include <stdlib.h>
     30     0    stevel #include <stdio.h>
     31     0    stevel #include <errno.h>
     32     0    stevel #include <ctype.h>
     33     0    stevel #include <alloca.h>
     34     0    stevel #include <libgen.h>
     35     0    stevel #include <stddef.h>
     36     0    stevel 
     37     0    stevel #include <dt_impl.h>
     38   265       mws #include <dt_program.h>
     39     0    stevel #include <dt_pid.h>
     40     0    stevel #include <dt_string.h>
     41     0    stevel 
     42     0    stevel typedef struct dt_pid_probe {
     43  1399       ahl 	dtrace_hdl_t *dpp_dtp;
     44  1399       ahl 	dt_pcb_t *dpp_pcb;
     45  1399       ahl 	dt_proc_t *dpp_dpr;
     46  1399       ahl 	struct ps_prochandle *dpp_pr;
     47  1399       ahl 	const char *dpp_mod;
     48  1399       ahl 	char *dpp_func;
     49  1399       ahl 	const char *dpp_name;
     50  1399       ahl 	const char *dpp_obj;
     51  1399       ahl 	uintptr_t dpp_pc;
     52  1399       ahl 	size_t dpp_size;
     53  1399       ahl 	Lmid_t dpp_lmid;
     54  1399       ahl 	uint_t dpp_nmatches;
     55  1399       ahl 	uint64_t dpp_stret[4];
     56  1399       ahl 	GElf_Sym dpp_last;
     57  1399       ahl 	uint_t dpp_last_taken;
     58     0    stevel } dt_pid_probe_t;
     59     0    stevel 
     60   630       ahl /*
     61   630       ahl  * Compose the lmid and object name into the canonical representation. We
     62   630       ahl  * omit the lmid for the default link map for convenience.
     63   630       ahl  */
     64   630       ahl static void
     65   630       ahl dt_pid_objname(char *buf, size_t len, Lmid_t lmid, const char *obj)
     66   630       ahl {
     67   630       ahl 	if (lmid == LM_ID_BASE)
     68   630       ahl 		(void) strncpy(buf, obj, len);
     69   630       ahl 	else
     70   630       ahl 		(void) snprintf(buf, len, "LM%lx`%s", lmid, obj);
     71   630       ahl }
     72   630       ahl 
     73  1399       ahl static int
     74  1399       ahl dt_pid_error(dtrace_hdl_t *dtp, dt_pcb_t *pcb, dt_proc_t *dpr,
     75  1399       ahl     fasttrap_probe_spec_t *ftp, dt_errtag_t tag, const char *fmt, ...)
     76   630       ahl {
     77   630       ahl 	va_list ap;
     78  1399       ahl 	int len;
     79  1399       ahl 
     80  1399       ahl 	if (ftp != NULL)
     81  1399       ahl 		dt_free(dtp, ftp);
     82   630       ahl 
     83   630       ahl 	va_start(ap, fmt);
     84  1399       ahl 	if (pcb == NULL) {
     85  1399       ahl 		assert(dpr != NULL);
     86  1399       ahl 		len = vsnprintf(dpr->dpr_errmsg, sizeof (dpr->dpr_errmsg),
     87  1399       ahl 		    fmt, ap);
     88  1399       ahl 		assert(len >= 2);
     89  1399       ahl 		if (dpr->dpr_errmsg[len - 2] == '\n')
     90  1399       ahl 			dpr->dpr_errmsg[len - 2] = '\0';
     91  1399       ahl 	} else {
     92  1399       ahl 		dt_set_errmsg(dtp, dt_errtag(tag), pcb->pcb_region,
     93  1399       ahl 		    pcb->pcb_filetag, pcb->pcb_fileptr ? yylineno : 0, fmt, ap);
     94  1399       ahl 	}
     95   630       ahl 	va_end(ap);
     96  1399       ahl 
     97  1399       ahl 	return (1);
     98   630       ahl }
     99   630       ahl 
    100  1399       ahl static int
    101     0    stevel dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
    102     0    stevel {
    103  1399       ahl 	dtrace_hdl_t *dtp = pp->dpp_dtp;
    104  1399       ahl 	dt_pcb_t *pcb = pp->dpp_pcb;
    105  1399       ahl 	dt_proc_t *dpr = pp->dpp_dpr;
    106     0    stevel 	fasttrap_probe_spec_t *ftp;
    107     0    stevel 	uint64_t off;
    108     0    stevel 	char *end;
    109     0    stevel 	uint_t nmatches = 0;
    110     0    stevel 	ulong_t sz;
    111     0    stevel 	int glob, err;
    112     0    stevel 	int isdash = strcmp("-", func) == 0;
    113     0    stevel 	pid_t pid;
    114     0    stevel 
    115     0    stevel 	pid = Pstatus(pp->dpp_pr)->pr_pid;
    116     0    stevel 
    117     0    stevel 	dt_dprintf("creating probe pid%d:%s:%s:%s\n", (int)pid, pp->dpp_obj,
    118     0    stevel 	    func, pp->dpp_name);
    119     0    stevel 
    120     0    stevel 	sz = sizeof (fasttrap_probe_spec_t) + (isdash ? 4 :
    121     0    stevel 	    (symp->st_size - 1) * sizeof (ftp->ftps_offs[0]));
    122     0    stevel 
    123  1399       ahl 	if ((ftp = dt_alloc(dtp, sz)) == NULL) {
    124  1399       ahl 		dt_dprintf("proc_per_sym: dt_alloc(%lu) failed\n", sz);
    125  1399       ahl 		return (1); /* errno is set for us */
    126     0    stevel 	}
    127     0    stevel 
    128     0    stevel 	ftp->ftps_pid = pid;
    129     0    stevel 	(void) strncpy(ftp->ftps_func, func, sizeof (ftp->ftps_func));
    130     0    stevel 
    131   630       ahl 	dt_pid_objname(ftp->ftps_mod, sizeof (ftp->ftps_mod), pp->dpp_lmid,
    132   630       ahl 	    pp->dpp_obj);
    133     0    stevel 
    134     0    stevel 	if (!isdash && gmatch("return", pp->dpp_name)) {
    135  1399       ahl 		if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp,
    136  1399       ahl 		    pp->dpp_stret) < 0) {
    137  1399       ahl 			return (dt_pid_error(dtp, pcb, dpr, ftp,
    138  1399       ahl 			    D_PROC_CREATEFAIL, "failed to create return probe "
    139  1399       ahl 			    "for '%s': %s", func,
    140  1399       ahl 			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
    141  1399       ahl 		}
    142     0    stevel 
    143     0    stevel 		nmatches++;
    144     0    stevel 	}
    145     0    stevel 
    146     0    stevel 	if (!isdash && gmatch("entry", pp->dpp_name)) {
    147  1399       ahl 		if (dt_pid_create_entry_probe(pp->dpp_pr, dtp, ftp, symp) < 0) {
    148  1399       ahl 			return (dt_pid_error(dtp, pcb, dpr, ftp,
    149  1399       ahl 			    D_PROC_CREATEFAIL, "failed to create entry probe "
    150  1399       ahl 			    "for '%s': %s", func,
    151  1399       ahl 			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
    152  1399       ahl 		}
    153     0    stevel 
    154     0    stevel 		nmatches++;
    155     0    stevel 	}
    156     0    stevel 
    157     0    stevel 	glob = strisglob(pp->dpp_name);
    158     0    stevel 	if (!glob && nmatches == 0) {
    159     0    stevel 		off = strtoull(pp->dpp_name, &end, 16);
    160     0    stevel 		if (*end != '\0') {
    161  1399       ahl 			return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_NAME,
    162  1399       ahl 			    "'%s' is an invalid probe name", pp->dpp_name));
    163     0    stevel 		}
    164     0    stevel 
    165     0    stevel 		if (off >= symp->st_size) {
    166  1399       ahl 			return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_OFF,
    167  1399       ahl 			    "offset 0x%llx outside of function '%s'",
    168  1399       ahl 			    (u_longlong_t)off, func));
    169     0    stevel 		}
    170     0    stevel 
    171     0    stevel 		err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp,
    172     0    stevel 		    symp, off);
    173     0    stevel 
    174  1399       ahl 		if (err == DT_PROC_ERR) {
    175  1399       ahl 			return (dt_pid_error(dtp, pcb, dpr, ftp,
    176  1399       ahl 			    D_PROC_CREATEFAIL, "failed to create probe at "
    177  1399       ahl 			    "'%s+0x%llx': %s", func, (u_longlong_t)off,
    178  1399       ahl 			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
    179  1399       ahl 		}
    180  1399       ahl 
    181     0    stevel 		if (err == DT_PROC_ALIGN) {
    182  1399       ahl 			return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_ALIGN,
    183  1399       ahl 			    "offset 0x%llx is not aligned on an instruction",
    184  1399       ahl 			    (u_longlong_t)off));
    185     0    stevel 		}
    186     0    stevel 
    187     0    stevel 		nmatches++;
    188     0    stevel 
    189     0    stevel 	} else if (glob && !isdash) {
    190     0    stevel 		if (dt_pid_create_glob_offset_probes(pp->dpp_pr,
    191  1399       ahl 		    pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) {
    192  1399       ahl 			return (dt_pid_error(dtp, pcb, dpr, ftp,
    193  1399       ahl 			    D_PROC_CREATEFAIL,
    194  1399       ahl 			    "failed to create offset probes in '%s': %s", func,
    195  1399       ahl 			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
    196  1399       ahl 		}
    197     0    stevel 
    198     0    stevel 		nmatches++;
    199     0    stevel 	}
    200     0    stevel 
    201     0    stevel 	pp->dpp_nmatches += nmatches;
    202     0    stevel 
    203  1399       ahl 	dt_free(dtp, ftp);
    204     0    stevel 
    205  1399       ahl 	return (0);
    206     0    stevel }
    207     0    stevel 
    208     0    stevel static int
    209     0    stevel dt_pid_sym_filt(void *arg, const GElf_Sym *symp, const char *func)
    210     0    stevel {
    211     0    stevel 	dt_pid_probe_t *pp = arg;
    212     0    stevel 
    213     0    stevel 	if (symp->st_shndx == SHN_UNDEF)
    214     0    stevel 		return (0);
    215     0    stevel 
    216     0    stevel 	if (symp->st_size == 0) {
    217     0    stevel 		dt_dprintf("st_size of %s is zero\n", func);
    218     0    stevel 		return (0);
    219     0    stevel 	}
    220     0    stevel 
    221  1399       ahl 	if (pp->dpp_last_taken == 0 ||
    222  1399       ahl 	    symp->st_value != pp->dpp_last.st_value ||
    223     0    stevel 	    symp->st_size != pp->dpp_last.st_size) {
    224     0    stevel 		/*
    225     0    stevel 		 * Due to 4524008, _init and _fini may have a bloated st_size.
    226     0    stevel 		 * While this bug has been fixed for a while, old binaries
    227     0    stevel 		 * may exist that still exhibit this problem. As a result, we
    228     0    stevel 		 * don't match _init and _fini though we allow users to
    229     0    stevel 		 * specify them explicitly.
    230     0    stevel 		 */
    231     0    stevel 		if (strcmp(func, "_init") == 0 || strcmp(func, "_fini") == 0)
    232     0    stevel 			return (0);
    233     0    stevel 
    234  1399       ahl 		if ((pp->dpp_last_taken = gmatch(func, pp->dpp_func)) != 0) {
    235  1399       ahl 			pp->dpp_last = *symp;
    236  1399       ahl 			return (dt_pid_per_sym(pp, symp, func));
    237     0    stevel 		}
    238     0    stevel 	}
    239     0    stevel 
    240     0    stevel 	return (0);
    241     0    stevel }
    242     0    stevel 
    243  1399       ahl static int
    244     0    stevel dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
    245     0    stevel {
    246     0    stevel 	dt_pid_probe_t *pp = arg;
    247  1399       ahl 	dtrace_hdl_t *dtp = pp->dpp_dtp;
    248  1399       ahl 	dt_pcb_t *pcb = pp->dpp_pcb;
    249  1399       ahl 	dt_proc_t *dpr = pp->dpp_dpr;
    250     0    stevel 	GElf_Sym sym;
    251     0    stevel 
    252     0    stevel 	if (obj == NULL)
    253  1399       ahl 		return (0);
    254     0    stevel 
    255     0    stevel 	(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
    256     0    stevel 
    257     0    stevel 	if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)
    258     0    stevel 		pp->dpp_obj = obj;
    259     0    stevel 	else
    260     0    stevel 		pp->dpp_obj++;
    261     0    stevel 
    262     0    stevel 	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret1", &sym,
    263     0    stevel 	    NULL) == 0)
    264     0    stevel 		pp->dpp_stret[0] = sym.st_value;
    265     0    stevel 	else
    266     0    stevel 		pp->dpp_stret[0] = 0;
    267     0    stevel 
    268     0    stevel 	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret2", &sym,
    269     0    stevel 	    NULL) == 0)
    270     0    stevel 		pp->dpp_stret[1] = sym.st_value;
    271     0    stevel 	else
    272     0    stevel 		pp->dpp_stret[1] = 0;
    273     0    stevel 
    274     0    stevel 	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret4", &sym,
    275     0    stevel 	    NULL) == 0)
    276     0    stevel 		pp->dpp_stret[2] = sym.st_value;
    277     0    stevel 	else
    278     0    stevel 		pp->dpp_stret[2] = 0;
    279     0    stevel 
    280     0    stevel 	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret8", &sym,
    281     0    stevel 	    NULL) == 0)
    282     0    stevel 		pp->dpp_stret[3] = sym.st_value;
    283     0    stevel 	else
    284     0    stevel 		pp->dpp_stret[3] = 0;
    285     0    stevel 
    286     0    stevel 	dt_dprintf("%s stret %llx %llx %llx %llx\n", obj,
    287     0    stevel 	    (u_longlong_t)pp->dpp_stret[0], (u_longlong_t)pp->dpp_stret[1],
    288     0    stevel 	    (u_longlong_t)pp->dpp_stret[2], (u_longlong_t)pp->dpp_stret[3]);
    289     0    stevel 
    290     0    stevel 	/*
    291     0    stevel 	 * If pp->dpp_func contains any globbing meta-characters, we need
    292     0    stevel 	 * to iterate over the symbol table and compare each function name
    293     0    stevel 	 * against the pattern.
    294     0    stevel 	 */
    295     0    stevel 	if (!strisglob(pp->dpp_func)) {
    296     0    stevel 		/*
    297     0    stevel 		 * If we fail to lookup the symbol, try interpreting the
    298     0    stevel 		 * function as the special "-" function that indicates that the
    299     0    stevel 		 * probe name should be interpreted as a absolute virtual
    300     0    stevel 		 * address. If that fails and we were matching a specific
    301     0    stevel 		 * function in a specific module, report the error, otherwise
    302     0    stevel 		 * just fail silently in the hopes that some other object will
    303     0    stevel 		 * contain the desired symbol.
    304     0    stevel 		 */
    305     0    stevel 		if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj,
    306     0    stevel 		    pp->dpp_func, &sym, NULL) != 0) {
    307     0    stevel 			if (strcmp("-", pp->dpp_func) == 0) {
    308     0    stevel 				sym.st_name = 0;
    309     0    stevel 				sym.st_info =
    310     0    stevel 				    GELF_ST_INFO(STB_LOCAL, STT_FUNC);
    311     0    stevel 				sym.st_other = 0;
    312     0    stevel 				sym.st_value = 0;
    313     0    stevel 				sym.st_size = Pstatus(pp->dpp_pr)->pr_dmodel ==
    314     0    stevel 				    PR_MODEL_ILP32 ? -1U : -1ULL;
    315     0    stevel 
    316     0    stevel 			} else if (!strisglob(pp->dpp_mod)) {
    317  1399       ahl 				return (dt_pid_error(dtp, pcb, dpr, NULL,
    318  1399       ahl 				    D_PROC_FUNC,
    319  1399       ahl 				    "failed to lookup '%s' in module '%s'",
    320  1399       ahl 				    pp->dpp_func, pp->dpp_mod));
    321     0    stevel 			} else {
    322  1399       ahl 				return (0);
    323     0    stevel 			}
    324     0    stevel 		}
    325     0    stevel 
    326     0    stevel 		/*
    327     0    stevel 		 * Only match defined functions of non-zero size.
    328     0    stevel 		 */
    329     0    stevel 		if (GELF_ST_TYPE(sym.st_info) != STT_FUNC ||
    330     0    stevel 		    sym.st_shndx == SHN_UNDEF || sym.st_size == 0)
    331  1399       ahl 			return (0);
    332     0    stevel 
    333     0    stevel 		/*
    334     0    stevel 		 * We don't instrument PLTs -- they're dynamically rewritten,
    335     0    stevel 		 * and, so, inherently dicey to instrument.
    336     0    stevel 		 */
    337     0    stevel 		if (Ppltdest(pp->dpp_pr, sym.st_value) != NULL)
    338  1399       ahl 			return (0);
    339     0    stevel 
    340     0    stevel 		(void) Plookup_by_addr(pp->dpp_pr, sym.st_value, pp->dpp_func,
    341     0    stevel 		    DTRACE_FUNCNAMELEN, &sym);
    342     0    stevel 
    343  1399       ahl 		return (dt_pid_per_sym(pp, &sym, pp->dpp_func));
    344     0    stevel 	} else {
    345     0    stevel 		uint_t nmatches = pp->dpp_nmatches;
    346     0    stevel 
    347  1399       ahl 		if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB,
    348  1399       ahl 		    BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)
    349  1399       ahl 			return (1);
    350     0    stevel 
    351     0    stevel 		if (nmatches == pp->dpp_nmatches) {
    352     0    stevel 			/*
    353     0    stevel 			 * If we didn't match anything in the PR_SYMTAB, try
    354     0    stevel 			 * the PR_DYNSYM.
    355     0    stevel 			 */
    356  1399       ahl 			if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_DYNSYM,
    357  1399       ahl 			    BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)
    358  1399       ahl 				return (1);
    359     0    stevel 		}
    360     0    stevel 	}
    361  1399       ahl 
    362  1399       ahl 	return (0);
    363     0    stevel }
    364     0    stevel 
    365     0    stevel static int
    366     0    stevel dt_pid_mod_filt(void *arg, const prmap_t *pmp, const char *obj)
    367     0    stevel {
    368  1399       ahl 	char name[DTRACE_MODNAMELEN];
    369     0    stevel 	dt_pid_probe_t *pp = arg;
    370     0    stevel 
    371  1399       ahl 	if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)
    372  1399       ahl 		pp->dpp_obj = obj;
    373  1399       ahl 	else
    374  1399       ahl 		pp->dpp_obj++;
    375     0    stevel 
    376  7991  Jonathan 	if (gmatch(pp->dpp_obj, pp->dpp_mod))
    377  7991  Jonathan 		return (dt_pid_per_mod(pp, pmp, obj));
    378  7991  Jonathan 
    379  7991  Jonathan 	(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
    380  7991  Jonathan 
    381  7991  Jonathan 	dt_pid_objname(name, sizeof (name), pp->dpp_lmid, pp->dpp_obj);
    382     0    stevel 
    383  1399       ahl 	if (gmatch(name, pp->dpp_mod))
    384  1399       ahl 		return (dt_pid_per_mod(pp, pmp, obj));
    385     0    stevel 
    386     0    stevel 	return (0);
    387     0    stevel }
    388     0    stevel 
    389     0    stevel static const prmap_t *
    390     0    stevel dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
    391     0    stevel {
    392     0    stevel 	char m[MAXPATHLEN];
    393     0    stevel 	Lmid_t lmid = PR_LMID_EVERY;
    394     0    stevel 	const char *obj;
    395     0    stevel 	const prmap_t *pmp;
    396     0    stevel 
    397     0    stevel 	/*
    398     0    stevel 	 * Pick apart the link map from the library name.
    399     0    stevel 	 */
    400     0    stevel 	if (strchr(pdp->dtpd_mod, '`') != NULL) {
    401     0    stevel 		char *end;
    402     0    stevel 
    403     0    stevel 		if (strncmp(pdp->dtpd_mod, "LM", 2) != 0 ||
    404     0    stevel 		    !isdigit(pdp->dtpd_mod[2]))
    405     0    stevel 			return (NULL);
    406     0    stevel 
    407     0    stevel 		lmid = strtoul(&pdp->dtpd_mod[2], &end, 16);
    408     0    stevel 
    409     0    stevel 		obj = end + 1;
    410     0    stevel 
    411     0    stevel 		if (*end != '`' || strchr(obj, '`') != NULL)
    412     0    stevel 			return (NULL);
    413     0    stevel 
    414     0    stevel 	} else {
    415     0    stevel 		obj = pdp->dtpd_mod;
    416     0    stevel 	}
    417     0    stevel 
    418     0    stevel 	if ((pmp = Plmid_to_map(P, lmid, obj)) == NULL)
    419     0    stevel 		return (NULL);
    420     0    stevel 
    421     0    stevel 	(void) Pobjname(P, pmp->pr_vaddr, m, sizeof (m));
    422     0    stevel 	if ((obj = strrchr(m, '/')) == NULL)
    423     0    stevel 		obj = &m[0];
    424     0    stevel 	else
    425     0    stevel 		obj++;
    426     0    stevel 
    427     0    stevel 	(void) Plmid(P, pmp->pr_vaddr, &lmid);
    428   630       ahl 	dt_pid_objname(pdp->dtpd_mod, sizeof (pdp->dtpd_mod), lmid, obj);
    429     0    stevel 
    430     0    stevel 	return (pmp);
    431     0    stevel }
    432     0    stevel 
    433     0    stevel 
    434  1399       ahl static int
    435  1399       ahl dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
    436  1399       ahl     dt_pcb_t *pcb, dt_proc_t *dpr)
    437     0    stevel {
    438     0    stevel 	dt_pid_probe_t pp;
    439  1399       ahl 	int ret = 0;
    440     0    stevel 
    441  1399       ahl 	pp.dpp_dtp = dtp;
    442  1399       ahl 	pp.dpp_dpr = dpr;
    443  1399       ahl 	pp.dpp_pr = dpr->dpr_proc;
    444  1399       ahl 	pp.dpp_pcb = pcb;
    445     0    stevel 
    446     0    stevel 	/*
    447     0    stevel 	 * We can only trace dynamically-linked executables (since we've
    448     0    stevel 	 * hidden some magic in ld.so.1 as well as libc.so.1).
    449     0    stevel 	 */
    450     0    stevel 	if (Pname_to_map(pp.dpp_pr, PR_OBJ_LDSO) == NULL) {
    451  1399       ahl 		return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_DYN,
    452  1399       ahl 		    "process %s is not a dynamically-linked executable",
    453  1399       ahl 		    &pdp->dtpd_provider[3]));
    454     0    stevel 	}
    455     0    stevel 
    456     0    stevel 	pp.dpp_mod = pdp->dtpd_mod[0] != '\0' ? pdp->dtpd_mod : "*";
    457     0    stevel 	pp.dpp_func = pdp->dtpd_func[0] != '\0' ? pdp->dtpd_func : "*";
    458     0    stevel 	pp.dpp_name = pdp->dtpd_name[0] != '\0' ? pdp->dtpd_name : "*";
    459  1399       ahl 	pp.dpp_last_taken = 0;
    460     0    stevel 
    461     0    stevel 	if (strcmp(pp.dpp_func, "-") == 0) {
    462     0    stevel 		const prmap_t *aout, *pmp;
    463     0    stevel 
    464     0    stevel 		if (pdp->dtpd_mod[0] == '\0') {
    465     0    stevel 			pp.dpp_mod = pdp->dtpd_mod;
    466     0    stevel 			(void) strcpy(pdp->dtpd_mod, "a.out");
    467     0    stevel 		} else if (strisglob(pp.dpp_mod) ||
    468     0    stevel 		    (aout = Pname_to_map(pp.dpp_pr, "a.out")) == NULL ||
    469     0    stevel 		    (pmp = Pname_to_map(pp.dpp_pr, pp.dpp_mod)) == NULL ||
    470     0    stevel 		    aout->pr_vaddr != pmp->pr_vaddr) {
    471  1399       ahl 			return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_LIB,
    472  1399       ahl 			    "only the a.out module is valid with the "
    473  1399       ahl 			    "'-' function"));
    474     0    stevel 		}
    475     0    stevel 
    476     0    stevel 		if (strisglob(pp.dpp_name)) {
    477  1399       ahl 			return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_NAME,
    478  1399       ahl 			    "only individual addresses may be specified "
    479  1399       ahl 			    "with the '-' function"));
    480     0    stevel 		}
    481     0    stevel 	}
    482     0    stevel 
    483     0    stevel 	/*
    484     0    stevel 	 * If pp.dpp_mod contains any globbing meta-characters, we need
    485     0    stevel 	 * to iterate over each module and compare its name against the
    486     0    stevel 	 * pattern. An empty module name is treated as '*'.
    487     0    stevel 	 */
    488     0    stevel 	if (strisglob(pp.dpp_mod)) {
    489  1399       ahl 		ret = Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp);
    490     0    stevel 	} else {
    491     0    stevel 		const prmap_t *pmp;
    492     0    stevel 		char *obj;
    493     0    stevel 
    494     0    stevel 		/*
    495  1399       ahl 		 * If we can't find a matching module, don't sweat it -- either
    496     0    stevel 		 * we'll fail the enabling because the probes don't exist or
    497     0    stevel 		 * we'll wait for that module to come along.
    498     0    stevel 		 */
    499     0    stevel 		if ((pmp = dt_pid_fix_mod(pdp, pp.dpp_pr)) != NULL) {
    500     0    stevel 			if ((obj = strchr(pdp->dtpd_mod, '`')) == NULL)
    501     0    stevel 				obj = pdp->dtpd_mod;
    502     0    stevel 			else
    503     0    stevel 				obj++;
    504     0    stevel 
    505  1399       ahl 			ret = dt_pid_per_mod(&pp, pmp, obj);
    506     0    stevel 		}
    507     0    stevel 	}
    508  1399       ahl 
    509  1399       ahl 	return (ret);
    510     0    stevel }
    511     0    stevel 
    512     0    stevel static int
    513     0    stevel dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
    514     0    stevel {
    515     0    stevel 	struct ps_prochandle *P = data;
    516     0    stevel 	GElf_Sym sym;
    517     0    stevel 	prsyminfo_t sip;
    518     0    stevel 	dof_helper_t dh;
    519     0    stevel 	GElf_Half e_type;
    520     0    stevel 	const char *mname;
    521     0    stevel 	const char *syms[] = { "___SUNW_dof", "__SUNW_dof" };
    522  1399       ahl 	int i, fd = -1;
    523     0    stevel 
    524     0    stevel 	/*
    525     0    stevel 	 * The symbol ___SUNW_dof is for lazy-loaded DOF sections, and
    526     0    stevel 	 * __SUNW_dof is for actively-loaded DOF sections. We try to force
    527     0    stevel 	 * in both types of DOF section since the process may not yet have
    528     0    stevel 	 * run the code to instantiate these providers.
    529     0    stevel 	 */
    530     0    stevel 	for (i = 0; i < 2; i++) {
    531     0    stevel 		if (Pxlookup_by_name(P, PR_LMID_EVERY, oname, syms[i], &sym,
    532     0    stevel 		    &sip) != 0) {
    533     0    stevel 			continue;
    534     0    stevel 		}
    535     0    stevel 
    536     0    stevel 		if ((mname = strrchr(oname, '/')) == NULL)
    537     0    stevel 			mname = oname;
    538     0    stevel 		else
    539     0    stevel 			mname++;
    540     0    stevel 
    541     0    stevel 		dt_dprintf("lookup of %s succeeded for %s\n", syms[i], mname);
    542     0    stevel 
    543     0    stevel 		if (Pread(P, &e_type, sizeof (e_type), pmp->pr_vaddr +
    544     0    stevel 		    offsetof(Elf64_Ehdr, e_type)) != sizeof (e_type)) {
    545     0    stevel 			dt_dprintf("read of ELF header failed");
    546     0    stevel 			continue;
    547     0    stevel 		}
    548     0    stevel 
    549     0    stevel 		dh.dofhp_dof = sym.st_value;
    550     0    stevel 		dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr;
    551     0    stevel 
    552   630       ahl 		dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod),
    553   630       ahl 		    sip.prs_lmid, mname);
    554     0    stevel 
    555  1399       ahl 		if (fd == -1 &&
    556  1399       ahl 		    (fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) {
    557     0    stevel 			dt_dprintf("pr_open of helper device failed: %s\n",
    558     0    stevel 			    strerror(errno));
    559  1399       ahl 			return (-1); /* errno is set for us */
    560     0    stevel 		}
    561     0    stevel 
    562  1399       ahl 		if (pr_ioctl(P, fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0)
    563  1399       ahl 			dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod);
    564  1399       ahl 	}
    565     0    stevel 
    566  1399       ahl 	if (fd != -1)
    567  1399       ahl 		(void) pr_close(P, fd);
    568     0    stevel 
    569     0    stevel 	return (0);
    570     0    stevel }
    571     0    stevel 
    572     0    stevel static int
    573  1399       ahl dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
    574  1399       ahl     dt_pcb_t *pcb, dt_proc_t *dpr)
    575     0    stevel {
    576     0    stevel 	struct ps_prochandle *P = dpr->dpr_proc;
    577  1399       ahl 	int ret = 0;
    578     0    stevel 
    579     0    stevel 	assert(DT_MUTEX_HELD(&dpr->dpr_lock));
    580     0    stevel 
    581     0    stevel 	(void) Pupdate_maps(P);
    582  1399       ahl 	if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) {
    583  1399       ahl 		ret = -1;
    584  1399       ahl 		(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT,
    585  1399       ahl 		    "failed to instantiate probes for pid %d: %s",
    586  1399       ahl 		    (int)Pstatus(P)->pr_pid, strerror(errno));
    587  1399       ahl 	}
    588     0    stevel 
    589     0    stevel 	/*
    590     0    stevel 	 * Put the module name in its canonical form.
    591     0    stevel 	 */
    592     0    stevel 	(void) dt_pid_fix_mod(pdp, P);
    593     0    stevel 
    594  1399       ahl 	return (ret);
    595     0    stevel }
    596     0    stevel 
    597     0    stevel static pid_t
    598  1399       ahl dt_pid_get_pid(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb,
    599  1399       ahl     dt_proc_t *dpr)
    600     0    stevel {
    601     0    stevel 	pid_t pid;
    602     0    stevel 	char *c, *last = NULL, *end;
    603     0    stevel 
    604     0    stevel 	for (c = &pdp->dtpd_provider[0]; *c != '\0'; c++) {
    605     0    stevel 		if (!isdigit(*c))
    606     0    stevel 			last = c;
    607     0    stevel 	}
    608     0    stevel 
    609     0    stevel 	if (last == NULL || (*(++last) == '\0')) {
    610  1399       ahl 		(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPROV,
    611  1399       ahl 		    "'%s' is not a valid provider", pdp->dtpd_provider);
    612  1399       ahl 		return (-1);
    613     0    stevel 	}
    614     0    stevel 
    615     0    stevel 	errno = 0;
    616     0    stevel 	pid = strtol(last, &end, 10);
    617     0    stevel 
    618     0    stevel 	if (errno != 0 || end == last || end[0] != '\0' || pid <= 0) {
    619  1399       ahl 		(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPID,
    620  1399       ahl 		    "'%s' does not contain a valid pid", pdp->dtpd_provider);
    621  1399       ahl 		return (-1);
    622     0    stevel 	}
    623     0    stevel 
    624     0    stevel 	return (pid);
    625     0    stevel }
    626     0    stevel 
    627  1399       ahl int
    628  1399       ahl dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
    629     0    stevel {
    630     0    stevel 	char provname[DTRACE_PROVNAMELEN];
    631     0    stevel 	struct ps_prochandle *P;
    632     0    stevel 	dt_proc_t *dpr;
    633  1399       ahl 	pid_t pid;
    634  1593       ahl 	int err = 0;
    635  1399       ahl 
    636  1399       ahl 	assert(pcb != NULL);
    637  1399       ahl 
    638  1399       ahl 	if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1)
    639  1399       ahl 		return (-1);
    640     0    stevel 
    641     0    stevel 	if (dtp->dt_ftfd == -1) {
    642     0    stevel 		if (dtp->dt_fterr == ENOENT) {
    643  1399       ahl 			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,
    644  1399       ahl 			    "pid provider is not installed on this system");
    645     0    stevel 		} else {
    646  1399       ahl 			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,
    647  1399       ahl 			    "pid provider is not available: %s",
    648  1399       ahl 			    strerror(dtp->dt_fterr));
    649     0    stevel 		}
    650  1399       ahl 
    651  1399       ahl 		return (-1);
    652     0    stevel 	}
    653     0    stevel 
    654     0    stevel 	(void) snprintf(provname, sizeof (provname), "pid%d", (int)pid);
    655     0    stevel 
    656  5984   jhaslam 	if (gmatch(provname, pdp->dtpd_provider) != 0) {
    657  1399       ahl 		if ((P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE,
    658  1399       ahl 		    0)) == NULL) {
    659  1399       ahl 			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,
    660  1399       ahl 			    "failed to grab process %d", (int)pid);
    661  1399       ahl 			return (-1);
    662  1399       ahl 		}
    663     0    stevel 
    664     0    stevel 		dpr = dt_proc_lookup(dtp, P, 0);
    665     0    stevel 		assert(dpr != NULL);
    666  1399       ahl 		(void) pthread_mutex_lock(&dpr->dpr_lock);
    667     0    stevel 
    668  6390       ahl 		if ((err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr)) == 0) {
    669  6390       ahl 			/*
    670  6390       ahl 			 * Alert other retained enablings which may match
    671  6390       ahl 			 * against the newly created probes.
    672  6390       ahl 			 */
    673  6390       ahl 			(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
    674  6390       ahl 		}
    675  1399       ahl 
    676  1399       ahl 		(void) pthread_mutex_unlock(&dpr->dpr_lock);
    677  1399       ahl 		dt_proc_release(dtp, P);
    678  5984   jhaslam 	}
    679  1399       ahl 
    680  5984   jhaslam 	/*
    681  5984   jhaslam 	 * If it's not strictly a pid provider, we might match a USDT provider.
    682  5984   jhaslam 	 */
    683  5984   jhaslam 	if (strcmp(provname, pdp->dtpd_provider) != 0) {
    684  1399       ahl 		if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL) {
    685  1399       ahl 			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,
    686  1399       ahl 			    "failed to grab process %d", (int)pid);
    687  1399       ahl 			return (-1);
    688  1399       ahl 		}
    689  1399       ahl 
    690  1399       ahl 		dpr = dt_proc_lookup(dtp, P, 0);
    691  1399       ahl 		assert(dpr != NULL);
    692     0    stevel 		(void) pthread_mutex_lock(&dpr->dpr_lock);
    693     0    stevel 
    694     0    stevel 		if (!dpr->dpr_usdt) {
    695  1399       ahl 			err = dt_pid_create_usdt_probes(pdp, dtp, pcb, dpr);
    696     0    stevel 			dpr->dpr_usdt = B_TRUE;
    697     0    stevel 		}
    698     0    stevel 
    699     0    stevel 		(void) pthread_mutex_unlock(&dpr->dpr_lock);
    700  1399       ahl 		dt_proc_release(dtp, P);
    701  1399       ahl 	}
    702     0    stevel 
    703  1399       ahl 	return (err ? -1 : 0);
    704     0    stevel }
    705     0    stevel 
    706  1399       ahl int
    707     0    stevel dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
    708     0    stevel {
    709     0    stevel 	dtrace_prog_t *pgp;
    710     0    stevel 	dt_stmt_t *stp;
    711     0    stevel 	dtrace_probedesc_t *pdp, pd;
    712     0    stevel 	pid_t pid;
    713  1399       ahl 	int ret = 0, found = B_FALSE;
    714  5984   jhaslam 	char provname[DTRACE_PROVNAMELEN];
    715  5984   jhaslam 
    716  5984   jhaslam 	(void) snprintf(provname, sizeof (provname), "pid%d",
    717  5984   jhaslam 	    (int)dpr->dpr_pid);
    718     0    stevel 
    719     0    stevel 	for (pgp = dt_list_next(&dtp->dt_programs); pgp != NULL;
    720     0    stevel 	    pgp = dt_list_next(pgp)) {
    721     0    stevel 
    722     0    stevel 		for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL;
    723     0    stevel 		    stp = dt_list_next(stp)) {
    724     0    stevel 
    725     0    stevel 			pdp = &stp->ds_desc->dtsd_ecbdesc->dted_probe;
    726  1399       ahl 			pid = dt_pid_get_pid(pdp, dtp, NULL, dpr);
    727  1399       ahl 			if (pid != dpr->dpr_pid)
    728     0    stevel 				continue;
    729     0    stevel 
    730     0    stevel 			found = B_TRUE;
    731     0    stevel 
    732     0    stevel 			pd = *pdp;
    733     0    stevel 
    734  5984   jhaslam 			if (gmatch(provname, pdp->dtpd_provider) != 0 &&
    735  5984   jhaslam 			    dt_pid_create_pid_probes(&pd, dtp, NULL, dpr) != 0)
    736  5984   jhaslam 				ret = 1;
    737  5984   jhaslam 
    738  5984   jhaslam 			/*
    739  5984   jhaslam 			 * If it's not strictly a pid provider, we might match
    740  5984   jhaslam 			 * a USDT provider.
    741  5984   jhaslam 			 */
    742  5984   jhaslam 			if (strcmp(provname, pdp->dtpd_provider) != 0 &&
    743  5984   jhaslam 			    dt_pid_create_usdt_probes(&pd, dtp, NULL, dpr) != 0)
    744  5984   jhaslam 				ret = 1;
    745     0    stevel 		}
    746     0    stevel 	}
    747     0    stevel 
    748     0    stevel 	if (found) {
    749     0    stevel 		/*
    750     0    stevel 		 * Give DTrace a shot to the ribs to get it to check
    751     0    stevel 		 * out the newly created probes.
    752     0    stevel 		 */
    753     0    stevel 		(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
    754     0    stevel 	}
    755  1399       ahl 
    756  1399       ahl 	return (ret);
    757     0    stevel }
    758