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