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