xref: /onnv-gate/usr/src/lib/libdtrace/common/dt_pid.c (revision 1399:f3a549d00510)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*1399Sahl 
230Sstevel@tonic-gate /*
24*1399Sahl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
250Sstevel@tonic-gate  * Use is subject to license terms.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <assert.h>
310Sstevel@tonic-gate #include <strings.h>
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <errno.h>
350Sstevel@tonic-gate #include <ctype.h>
360Sstevel@tonic-gate #include <alloca.h>
370Sstevel@tonic-gate #include <libgen.h>
380Sstevel@tonic-gate #include <stddef.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include <dt_impl.h>
41265Smws #include <dt_program.h>
420Sstevel@tonic-gate #include <dt_pid.h>
430Sstevel@tonic-gate #include <dt_string.h>
440Sstevel@tonic-gate 
450Sstevel@tonic-gate typedef struct dt_pid_probe {
46*1399Sahl 	dtrace_hdl_t *dpp_dtp;
47*1399Sahl 	dt_pcb_t *dpp_pcb;
48*1399Sahl 	dt_proc_t *dpp_dpr;
49*1399Sahl 	struct ps_prochandle *dpp_pr;
50*1399Sahl 	const char *dpp_mod;
51*1399Sahl 	char *dpp_func;
52*1399Sahl 	const char *dpp_name;
53*1399Sahl 	const char *dpp_obj;
54*1399Sahl 	uintptr_t dpp_pc;
55*1399Sahl 	size_t dpp_size;
56*1399Sahl 	Lmid_t dpp_lmid;
57*1399Sahl 	uint_t dpp_nmatches;
58*1399Sahl 	uint64_t dpp_stret[4];
59*1399Sahl 	GElf_Sym dpp_last;
60*1399Sahl 	uint_t dpp_last_taken;
610Sstevel@tonic-gate } dt_pid_probe_t;
620Sstevel@tonic-gate 
63630Sahl /*
64630Sahl  * Compose the lmid and object name into the canonical representation. We
65630Sahl  * omit the lmid for the default link map for convenience.
66630Sahl  */
67630Sahl static void
68630Sahl dt_pid_objname(char *buf, size_t len, Lmid_t lmid, const char *obj)
69630Sahl {
70630Sahl 	if (lmid == LM_ID_BASE)
71630Sahl 		(void) strncpy(buf, obj, len);
72630Sahl 	else
73630Sahl 		(void) snprintf(buf, len, "LM%lx`%s", lmid, obj);
74630Sahl }
75630Sahl 
76*1399Sahl static int
77*1399Sahl dt_pid_error(dtrace_hdl_t *dtp, dt_pcb_t *pcb, dt_proc_t *dpr,
78*1399Sahl     fasttrap_probe_spec_t *ftp, dt_errtag_t tag, const char *fmt, ...)
79630Sahl {
80630Sahl 	va_list ap;
81*1399Sahl 	int len;
82*1399Sahl 
83*1399Sahl 	if (ftp != NULL)
84*1399Sahl 		dt_free(dtp, ftp);
85630Sahl 
86630Sahl 	va_start(ap, fmt);
87*1399Sahl 	if (pcb == NULL) {
88*1399Sahl 		assert(dpr != NULL);
89*1399Sahl 		len = vsnprintf(dpr->dpr_errmsg, sizeof (dpr->dpr_errmsg),
90*1399Sahl 		    fmt, ap);
91*1399Sahl 		assert(len >= 2);
92*1399Sahl 		if (dpr->dpr_errmsg[len - 2] == '\n')
93*1399Sahl 			dpr->dpr_errmsg[len - 2] = '\0';
94*1399Sahl 	} else {
95*1399Sahl 		dt_set_errmsg(dtp, dt_errtag(tag), pcb->pcb_region,
96*1399Sahl 		    pcb->pcb_filetag, pcb->pcb_fileptr ? yylineno : 0, fmt, ap);
97*1399Sahl 	}
98630Sahl 	va_end(ap);
99*1399Sahl 
100*1399Sahl 	return (1);
101630Sahl }
102630Sahl 
103*1399Sahl static int
1040Sstevel@tonic-gate dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
1050Sstevel@tonic-gate {
106*1399Sahl 	dtrace_hdl_t *dtp = pp->dpp_dtp;
107*1399Sahl 	dt_pcb_t *pcb = pp->dpp_pcb;
108*1399Sahl 	dt_proc_t *dpr = pp->dpp_dpr;
1090Sstevel@tonic-gate 	fasttrap_probe_spec_t *ftp;
1100Sstevel@tonic-gate 	uint64_t off;
1110Sstevel@tonic-gate 	char *end;
1120Sstevel@tonic-gate 	uint_t nmatches = 0;
1130Sstevel@tonic-gate 	ulong_t sz;
1140Sstevel@tonic-gate 	int glob, err;
1150Sstevel@tonic-gate 	int isdash = strcmp("-", func) == 0;
1160Sstevel@tonic-gate 	pid_t pid;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	pid = Pstatus(pp->dpp_pr)->pr_pid;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	dt_dprintf("creating probe pid%d:%s:%s:%s\n", (int)pid, pp->dpp_obj,
1210Sstevel@tonic-gate 	    func, pp->dpp_name);
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	sz = sizeof (fasttrap_probe_spec_t) + (isdash ? 4 :
1240Sstevel@tonic-gate 	    (symp->st_size - 1) * sizeof (ftp->ftps_offs[0]));
1250Sstevel@tonic-gate 
126*1399Sahl 	if ((ftp = dt_alloc(dtp, sz)) == NULL) {
127*1399Sahl 		dt_dprintf("proc_per_sym: dt_alloc(%lu) failed\n", sz);
128*1399Sahl 		return (1); /* errno is set for us */
1290Sstevel@tonic-gate 	}
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	ftp->ftps_pid = pid;
1320Sstevel@tonic-gate 	(void) strncpy(ftp->ftps_func, func, sizeof (ftp->ftps_func));
1330Sstevel@tonic-gate 
134630Sahl 	dt_pid_objname(ftp->ftps_mod, sizeof (ftp->ftps_mod), pp->dpp_lmid,
135630Sahl 	    pp->dpp_obj);
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	if (!isdash && gmatch("return", pp->dpp_name)) {
138*1399Sahl 		if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp,
139*1399Sahl 		    pp->dpp_stret) < 0) {
140*1399Sahl 			return (dt_pid_error(dtp, pcb, dpr, ftp,
141*1399Sahl 			    D_PROC_CREATEFAIL, "failed to create return probe "
142*1399Sahl 			    "for '%s': %s", func,
143*1399Sahl 			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
144*1399Sahl 		}
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 		nmatches++;
1470Sstevel@tonic-gate 	}
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	if (!isdash && gmatch("entry", pp->dpp_name)) {
150*1399Sahl 		if (dt_pid_create_entry_probe(pp->dpp_pr, dtp, ftp, symp) < 0) {
151*1399Sahl 			return (dt_pid_error(dtp, pcb, dpr, ftp,
152*1399Sahl 			    D_PROC_CREATEFAIL, "failed to create entry probe "
153*1399Sahl 			    "for '%s': %s", func,
154*1399Sahl 			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
155*1399Sahl 		}
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 		nmatches++;
1580Sstevel@tonic-gate 	}
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	glob = strisglob(pp->dpp_name);
1610Sstevel@tonic-gate 	if (!glob && nmatches == 0) {
1620Sstevel@tonic-gate 		off = strtoull(pp->dpp_name, &end, 16);
1630Sstevel@tonic-gate 		if (*end != '\0') {
164*1399Sahl 			return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_NAME,
165*1399Sahl 			    "'%s' is an invalid probe name", pp->dpp_name));
1660Sstevel@tonic-gate 		}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 		if (off >= symp->st_size) {
169*1399Sahl 			return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_OFF,
170*1399Sahl 			    "offset 0x%llx outside of function '%s'",
171*1399Sahl 			    (u_longlong_t)off, func));
1720Sstevel@tonic-gate 		}
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 		err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp,
1750Sstevel@tonic-gate 		    symp, off);
1760Sstevel@tonic-gate 
177*1399Sahl 		if (err == DT_PROC_ERR) {
178*1399Sahl 			return (dt_pid_error(dtp, pcb, dpr, ftp,
179*1399Sahl 			    D_PROC_CREATEFAIL, "failed to create probe at "
180*1399Sahl 			    "'%s+0x%llx': %s", func, (u_longlong_t)off,
181*1399Sahl 			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
182*1399Sahl 		}
183*1399Sahl 
1840Sstevel@tonic-gate 		if (err == DT_PROC_ALIGN) {
185*1399Sahl 			return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_ALIGN,
186*1399Sahl 			    "offset 0x%llx is not aligned on an instruction",
187*1399Sahl 			    (u_longlong_t)off));
1880Sstevel@tonic-gate 		}
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 		nmatches++;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	} else if (glob && !isdash) {
1930Sstevel@tonic-gate 		if (dt_pid_create_glob_offset_probes(pp->dpp_pr,
194*1399Sahl 		    pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) {
195*1399Sahl 			return (dt_pid_error(dtp, pcb, dpr, ftp,
196*1399Sahl 			    D_PROC_CREATEFAIL,
197*1399Sahl 			    "failed to create offset probes in '%s': %s", func,
198*1399Sahl 			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
199*1399Sahl 		}
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 		nmatches++;
2020Sstevel@tonic-gate 	}
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	pp->dpp_nmatches += nmatches;
2050Sstevel@tonic-gate 
206*1399Sahl 	dt_free(dtp, ftp);
2070Sstevel@tonic-gate 
208*1399Sahl 	return (0);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate static int
2120Sstevel@tonic-gate dt_pid_sym_filt(void *arg, const GElf_Sym *symp, const char *func)
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate 	dt_pid_probe_t *pp = arg;
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	if (symp->st_shndx == SHN_UNDEF)
2170Sstevel@tonic-gate 		return (0);
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	if (symp->st_size == 0) {
2200Sstevel@tonic-gate 		dt_dprintf("st_size of %s is zero\n", func);
2210Sstevel@tonic-gate 		return (0);
2220Sstevel@tonic-gate 	}
2230Sstevel@tonic-gate 
224*1399Sahl 	if (pp->dpp_last_taken == 0 ||
225*1399Sahl 	    symp->st_value != pp->dpp_last.st_value ||
2260Sstevel@tonic-gate 	    symp->st_size != pp->dpp_last.st_size) {
2270Sstevel@tonic-gate 		/*
2280Sstevel@tonic-gate 		 * Due to 4524008, _init and _fini may have a bloated st_size.
2290Sstevel@tonic-gate 		 * While this bug has been fixed for a while, old binaries
2300Sstevel@tonic-gate 		 * may exist that still exhibit this problem. As a result, we
2310Sstevel@tonic-gate 		 * don't match _init and _fini though we allow users to
2320Sstevel@tonic-gate 		 * specify them explicitly.
2330Sstevel@tonic-gate 		 */
2340Sstevel@tonic-gate 		if (strcmp(func, "_init") == 0 || strcmp(func, "_fini") == 0)
2350Sstevel@tonic-gate 			return (0);
2360Sstevel@tonic-gate 
237*1399Sahl 		if ((pp->dpp_last_taken = gmatch(func, pp->dpp_func)) != 0) {
238*1399Sahl 			pp->dpp_last = *symp;
239*1399Sahl 			return (dt_pid_per_sym(pp, symp, func));
2400Sstevel@tonic-gate 		}
2410Sstevel@tonic-gate 	}
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	return (0);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate 
246*1399Sahl static int
2470Sstevel@tonic-gate dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
2480Sstevel@tonic-gate {
2490Sstevel@tonic-gate 	dt_pid_probe_t *pp = arg;
250*1399Sahl 	dtrace_hdl_t *dtp = pp->dpp_dtp;
251*1399Sahl 	dt_pcb_t *pcb = pp->dpp_pcb;
252*1399Sahl 	dt_proc_t *dpr = pp->dpp_dpr;
2530Sstevel@tonic-gate 	GElf_Sym sym;
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	if (obj == NULL)
256*1399Sahl 		return (0);
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)
2610Sstevel@tonic-gate 		pp->dpp_obj = obj;
2620Sstevel@tonic-gate 	else
2630Sstevel@tonic-gate 		pp->dpp_obj++;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret1", &sym,
2660Sstevel@tonic-gate 	    NULL) == 0)
2670Sstevel@tonic-gate 		pp->dpp_stret[0] = sym.st_value;
2680Sstevel@tonic-gate 	else
2690Sstevel@tonic-gate 		pp->dpp_stret[0] = 0;
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret2", &sym,
2720Sstevel@tonic-gate 	    NULL) == 0)
2730Sstevel@tonic-gate 		pp->dpp_stret[1] = sym.st_value;
2740Sstevel@tonic-gate 	else
2750Sstevel@tonic-gate 		pp->dpp_stret[1] = 0;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret4", &sym,
2780Sstevel@tonic-gate 	    NULL) == 0)
2790Sstevel@tonic-gate 		pp->dpp_stret[2] = sym.st_value;
2800Sstevel@tonic-gate 	else
2810Sstevel@tonic-gate 		pp->dpp_stret[2] = 0;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret8", &sym,
2840Sstevel@tonic-gate 	    NULL) == 0)
2850Sstevel@tonic-gate 		pp->dpp_stret[3] = sym.st_value;
2860Sstevel@tonic-gate 	else
2870Sstevel@tonic-gate 		pp->dpp_stret[3] = 0;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	dt_dprintf("%s stret %llx %llx %llx %llx\n", obj,
2900Sstevel@tonic-gate 	    (u_longlong_t)pp->dpp_stret[0], (u_longlong_t)pp->dpp_stret[1],
2910Sstevel@tonic-gate 	    (u_longlong_t)pp->dpp_stret[2], (u_longlong_t)pp->dpp_stret[3]);
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	/*
2940Sstevel@tonic-gate 	 * If pp->dpp_func contains any globbing meta-characters, we need
2950Sstevel@tonic-gate 	 * to iterate over the symbol table and compare each function name
2960Sstevel@tonic-gate 	 * against the pattern.
2970Sstevel@tonic-gate 	 */
2980Sstevel@tonic-gate 	if (!strisglob(pp->dpp_func)) {
2990Sstevel@tonic-gate 		/*
3000Sstevel@tonic-gate 		 * If we fail to lookup the symbol, try interpreting the
3010Sstevel@tonic-gate 		 * function as the special "-" function that indicates that the
3020Sstevel@tonic-gate 		 * probe name should be interpreted as a absolute virtual
3030Sstevel@tonic-gate 		 * address. If that fails and we were matching a specific
3040Sstevel@tonic-gate 		 * function in a specific module, report the error, otherwise
3050Sstevel@tonic-gate 		 * just fail silently in the hopes that some other object will
3060Sstevel@tonic-gate 		 * contain the desired symbol.
3070Sstevel@tonic-gate 		 */
3080Sstevel@tonic-gate 		if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj,
3090Sstevel@tonic-gate 		    pp->dpp_func, &sym, NULL) != 0) {
3100Sstevel@tonic-gate 			if (strcmp("-", pp->dpp_func) == 0) {
3110Sstevel@tonic-gate 				sym.st_name = 0;
3120Sstevel@tonic-gate 				sym.st_info =
3130Sstevel@tonic-gate 				    GELF_ST_INFO(STB_LOCAL, STT_FUNC);
3140Sstevel@tonic-gate 				sym.st_other = 0;
3150Sstevel@tonic-gate 				sym.st_value = 0;
3160Sstevel@tonic-gate 				sym.st_size = Pstatus(pp->dpp_pr)->pr_dmodel ==
3170Sstevel@tonic-gate 				    PR_MODEL_ILP32 ? -1U : -1ULL;
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 			} else if (!strisglob(pp->dpp_mod)) {
320*1399Sahl 				return (dt_pid_error(dtp, pcb, dpr, NULL,
321*1399Sahl 				    D_PROC_FUNC,
322*1399Sahl 				    "failed to lookup '%s' in module '%s'",
323*1399Sahl 				    pp->dpp_func, pp->dpp_mod));
3240Sstevel@tonic-gate 			} else {
325*1399Sahl 				return (0);
3260Sstevel@tonic-gate 			}
3270Sstevel@tonic-gate 		}
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 		/*
3300Sstevel@tonic-gate 		 * Only match defined functions of non-zero size.
3310Sstevel@tonic-gate 		 */
3320Sstevel@tonic-gate 		if (GELF_ST_TYPE(sym.st_info) != STT_FUNC ||
3330Sstevel@tonic-gate 		    sym.st_shndx == SHN_UNDEF || sym.st_size == 0)
334*1399Sahl 			return (0);
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 		/*
3370Sstevel@tonic-gate 		 * We don't instrument PLTs -- they're dynamically rewritten,
3380Sstevel@tonic-gate 		 * and, so, inherently dicey to instrument.
3390Sstevel@tonic-gate 		 */
3400Sstevel@tonic-gate 		if (Ppltdest(pp->dpp_pr, sym.st_value) != NULL)
341*1399Sahl 			return (0);
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 		(void) Plookup_by_addr(pp->dpp_pr, sym.st_value, pp->dpp_func,
3440Sstevel@tonic-gate 		    DTRACE_FUNCNAMELEN, &sym);
3450Sstevel@tonic-gate 
346*1399Sahl 		return (dt_pid_per_sym(pp, &sym, pp->dpp_func));
3470Sstevel@tonic-gate 	} else {
3480Sstevel@tonic-gate 		uint_t nmatches = pp->dpp_nmatches;
3490Sstevel@tonic-gate 
350*1399Sahl 		if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB,
351*1399Sahl 		    BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)
352*1399Sahl 			return (1);
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 		if (nmatches == pp->dpp_nmatches) {
3550Sstevel@tonic-gate 			/*
3560Sstevel@tonic-gate 			 * If we didn't match anything in the PR_SYMTAB, try
3570Sstevel@tonic-gate 			 * the PR_DYNSYM.
3580Sstevel@tonic-gate 			 */
359*1399Sahl 			if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_DYNSYM,
360*1399Sahl 			    BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)
361*1399Sahl 				return (1);
3620Sstevel@tonic-gate 		}
3630Sstevel@tonic-gate 	}
364*1399Sahl 
365*1399Sahl 	return (0);
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate static int
3690Sstevel@tonic-gate dt_pid_mod_filt(void *arg, const prmap_t *pmp, const char *obj)
3700Sstevel@tonic-gate {
371*1399Sahl 	char name[DTRACE_MODNAMELEN];
3720Sstevel@tonic-gate 	dt_pid_probe_t *pp = arg;
3730Sstevel@tonic-gate 
374*1399Sahl 	if (gmatch(obj, pp->dpp_mod))
375*1399Sahl 		return (dt_pid_per_mod(pp, pmp, obj));
3760Sstevel@tonic-gate 
377*1399Sahl 	(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
3780Sstevel@tonic-gate 
379*1399Sahl 	if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)
380*1399Sahl 		pp->dpp_obj = obj;
381*1399Sahl 	else
382*1399Sahl 		pp->dpp_obj++;
3830Sstevel@tonic-gate 
384*1399Sahl 	dt_pid_objname(name, sizeof (name), pp->dpp_lmid, obj);
3850Sstevel@tonic-gate 
386*1399Sahl 	if (gmatch(name, pp->dpp_mod))
387*1399Sahl 		return (dt_pid_per_mod(pp, pmp, obj));
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	return (0);
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate static const prmap_t *
3930Sstevel@tonic-gate dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
3940Sstevel@tonic-gate {
3950Sstevel@tonic-gate 	char m[MAXPATHLEN];
3960Sstevel@tonic-gate 	Lmid_t lmid = PR_LMID_EVERY;
3970Sstevel@tonic-gate 	const char *obj;
3980Sstevel@tonic-gate 	const prmap_t *pmp;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	/*
4010Sstevel@tonic-gate 	 * Pick apart the link map from the library name.
4020Sstevel@tonic-gate 	 */
4030Sstevel@tonic-gate 	if (strchr(pdp->dtpd_mod, '`') != NULL) {
4040Sstevel@tonic-gate 		char *end;
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 		if (strncmp(pdp->dtpd_mod, "LM", 2) != 0 ||
4070Sstevel@tonic-gate 		    !isdigit(pdp->dtpd_mod[2]))
4080Sstevel@tonic-gate 			return (NULL);
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 		lmid = strtoul(&pdp->dtpd_mod[2], &end, 16);
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 		obj = end + 1;
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 		if (*end != '`' || strchr(obj, '`') != NULL)
4150Sstevel@tonic-gate 			return (NULL);
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	} else {
4180Sstevel@tonic-gate 		obj = pdp->dtpd_mod;
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	if ((pmp = Plmid_to_map(P, lmid, obj)) == NULL)
4220Sstevel@tonic-gate 		return (NULL);
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	(void) Pobjname(P, pmp->pr_vaddr, m, sizeof (m));
4250Sstevel@tonic-gate 	if ((obj = strrchr(m, '/')) == NULL)
4260Sstevel@tonic-gate 		obj = &m[0];
4270Sstevel@tonic-gate 	else
4280Sstevel@tonic-gate 		obj++;
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 	(void) Plmid(P, pmp->pr_vaddr, &lmid);
431630Sahl 	dt_pid_objname(pdp->dtpd_mod, sizeof (pdp->dtpd_mod), lmid, obj);
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	return (pmp);
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 
437*1399Sahl static int
438*1399Sahl dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
439*1399Sahl     dt_pcb_t *pcb, dt_proc_t *dpr)
4400Sstevel@tonic-gate {
4410Sstevel@tonic-gate 	dt_pid_probe_t pp;
442*1399Sahl 	int ret = 0;
4430Sstevel@tonic-gate 
444*1399Sahl 	/*
445*1399Sahl 	 * Disable breakpoints so they don't interfere with our disassembly.
446*1399Sahl 	 */
447*1399Sahl 	dt_proc_bpdisable(dpr);
448*1399Sahl 
449*1399Sahl 	pp.dpp_dtp = dtp;
450*1399Sahl 	pp.dpp_dpr = dpr;
451*1399Sahl 	pp.dpp_pr = dpr->dpr_proc;
452*1399Sahl 	pp.dpp_pcb = pcb;
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	/*
4550Sstevel@tonic-gate 	 * We can only trace dynamically-linked executables (since we've
4560Sstevel@tonic-gate 	 * hidden some magic in ld.so.1 as well as libc.so.1).
4570Sstevel@tonic-gate 	 */
4580Sstevel@tonic-gate 	if (Pname_to_map(pp.dpp_pr, PR_OBJ_LDSO) == NULL) {
459*1399Sahl 		dt_proc_bpenable(dpr);
460*1399Sahl 		return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_DYN,
461*1399Sahl 		    "process %s is not a dynamically-linked executable",
462*1399Sahl 		    &pdp->dtpd_provider[3]));
4630Sstevel@tonic-gate 	}
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	pp.dpp_mod = pdp->dtpd_mod[0] != '\0' ? pdp->dtpd_mod : "*";
4660Sstevel@tonic-gate 	pp.dpp_func = pdp->dtpd_func[0] != '\0' ? pdp->dtpd_func : "*";
4670Sstevel@tonic-gate 	pp.dpp_name = pdp->dtpd_name[0] != '\0' ? pdp->dtpd_name : "*";
468*1399Sahl 	pp.dpp_last_taken = 0;
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	if (strcmp(pp.dpp_func, "-") == 0) {
4710Sstevel@tonic-gate 		const prmap_t *aout, *pmp;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 		if (pdp->dtpd_mod[0] == '\0') {
4740Sstevel@tonic-gate 			pp.dpp_mod = pdp->dtpd_mod;
4750Sstevel@tonic-gate 			(void) strcpy(pdp->dtpd_mod, "a.out");
4760Sstevel@tonic-gate 		} else if (strisglob(pp.dpp_mod) ||
4770Sstevel@tonic-gate 		    (aout = Pname_to_map(pp.dpp_pr, "a.out")) == NULL ||
4780Sstevel@tonic-gate 		    (pmp = Pname_to_map(pp.dpp_pr, pp.dpp_mod)) == NULL ||
4790Sstevel@tonic-gate 		    aout->pr_vaddr != pmp->pr_vaddr) {
480*1399Sahl 			dt_proc_bpenable(dpr);
481*1399Sahl 			return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_LIB,
482*1399Sahl 			    "only the a.out module is valid with the "
483*1399Sahl 			    "'-' function"));
4840Sstevel@tonic-gate 		}
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 		if (strisglob(pp.dpp_name)) {
487*1399Sahl 			dt_proc_bpenable(dpr);
488*1399Sahl 			return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_NAME,
489*1399Sahl 			    "only individual addresses may be specified "
490*1399Sahl 			    "with the '-' function"));
4910Sstevel@tonic-gate 		}
4920Sstevel@tonic-gate 	}
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	/*
4950Sstevel@tonic-gate 	 * If pp.dpp_mod contains any globbing meta-characters, we need
4960Sstevel@tonic-gate 	 * to iterate over each module and compare its name against the
4970Sstevel@tonic-gate 	 * pattern. An empty module name is treated as '*'.
4980Sstevel@tonic-gate 	 */
4990Sstevel@tonic-gate 	if (strisglob(pp.dpp_mod)) {
500*1399Sahl 		ret = Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp);
5010Sstevel@tonic-gate 	} else {
5020Sstevel@tonic-gate 		const prmap_t *pmp;
5030Sstevel@tonic-gate 		char *obj;
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 		/*
506*1399Sahl 		 * If we can't find a matching module, don't sweat it -- either
5070Sstevel@tonic-gate 		 * we'll fail the enabling because the probes don't exist or
5080Sstevel@tonic-gate 		 * we'll wait for that module to come along.
5090Sstevel@tonic-gate 		 */
5100Sstevel@tonic-gate 		if ((pmp = dt_pid_fix_mod(pdp, pp.dpp_pr)) != NULL) {
5110Sstevel@tonic-gate 			if ((obj = strchr(pdp->dtpd_mod, '`')) == NULL)
5120Sstevel@tonic-gate 				obj = pdp->dtpd_mod;
5130Sstevel@tonic-gate 			else
5140Sstevel@tonic-gate 				obj++;
5150Sstevel@tonic-gate 
516*1399Sahl 			ret = dt_pid_per_mod(&pp, pmp, obj);
5170Sstevel@tonic-gate 		}
5180Sstevel@tonic-gate 	}
5190Sstevel@tonic-gate 
520*1399Sahl 	dt_proc_bpenable(dpr);
521*1399Sahl 
522*1399Sahl 	return (ret);
5230Sstevel@tonic-gate }
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate static int
5260Sstevel@tonic-gate dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
5270Sstevel@tonic-gate {
5280Sstevel@tonic-gate 	struct ps_prochandle *P = data;
5290Sstevel@tonic-gate 	GElf_Sym sym;
5300Sstevel@tonic-gate 	prsyminfo_t sip;
5310Sstevel@tonic-gate 	dof_helper_t dh;
5320Sstevel@tonic-gate 	GElf_Half e_type;
5330Sstevel@tonic-gate 	const char *mname;
5340Sstevel@tonic-gate 	const char *syms[] = { "___SUNW_dof", "__SUNW_dof" };
535*1399Sahl 	int i, fd = -1;
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	/*
5380Sstevel@tonic-gate 	 * The symbol ___SUNW_dof is for lazy-loaded DOF sections, and
5390Sstevel@tonic-gate 	 * __SUNW_dof is for actively-loaded DOF sections. We try to force
5400Sstevel@tonic-gate 	 * in both types of DOF section since the process may not yet have
5410Sstevel@tonic-gate 	 * run the code to instantiate these providers.
5420Sstevel@tonic-gate 	 */
5430Sstevel@tonic-gate 	for (i = 0; i < 2; i++) {
5440Sstevel@tonic-gate 		if (Pxlookup_by_name(P, PR_LMID_EVERY, oname, syms[i], &sym,
5450Sstevel@tonic-gate 		    &sip) != 0) {
5460Sstevel@tonic-gate 			continue;
5470Sstevel@tonic-gate 		}
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 		if ((mname = strrchr(oname, '/')) == NULL)
5500Sstevel@tonic-gate 			mname = oname;
5510Sstevel@tonic-gate 		else
5520Sstevel@tonic-gate 			mname++;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 		dt_dprintf("lookup of %s succeeded for %s\n", syms[i], mname);
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 		if (Pread(P, &e_type, sizeof (e_type), pmp->pr_vaddr +
5570Sstevel@tonic-gate 		    offsetof(Elf64_Ehdr, e_type)) != sizeof (e_type)) {
5580Sstevel@tonic-gate 			dt_dprintf("read of ELF header failed");
5590Sstevel@tonic-gate 			continue;
5600Sstevel@tonic-gate 		}
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 		dh.dofhp_dof = sym.st_value;
5630Sstevel@tonic-gate 		dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr;
5640Sstevel@tonic-gate 
565630Sahl 		dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod),
566630Sahl 		    sip.prs_lmid, mname);
5670Sstevel@tonic-gate 
568*1399Sahl 		if (fd == -1 &&
569*1399Sahl 		    (fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) {
5700Sstevel@tonic-gate 			dt_dprintf("pr_open of helper device failed: %s\n",
5710Sstevel@tonic-gate 			    strerror(errno));
572*1399Sahl 			return (-1); /* errno is set for us */
5730Sstevel@tonic-gate 		}
5740Sstevel@tonic-gate 
575*1399Sahl 		if (pr_ioctl(P, fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0)
576*1399Sahl 			dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod);
577*1399Sahl 	}
5780Sstevel@tonic-gate 
579*1399Sahl 	if (fd != -1)
580*1399Sahl 		(void) pr_close(P, fd);
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	return (0);
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate static int
586*1399Sahl dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
587*1399Sahl     dt_pcb_t *pcb, dt_proc_t *dpr)
5880Sstevel@tonic-gate {
5890Sstevel@tonic-gate 	struct ps_prochandle *P = dpr->dpr_proc;
590*1399Sahl 	int ret = 0;
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 	assert(DT_MUTEX_HELD(&dpr->dpr_lock));
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	(void) Pupdate_maps(P);
595*1399Sahl 	if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) {
596*1399Sahl 		ret = -1;
597*1399Sahl 		(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT,
598*1399Sahl 		    "failed to instantiate probes for pid %d: %s",
599*1399Sahl 		    (int)Pstatus(P)->pr_pid, strerror(errno));
600*1399Sahl 	}
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	/*
6030Sstevel@tonic-gate 	 * Put the module name in its canonical form.
6040Sstevel@tonic-gate 	 */
6050Sstevel@tonic-gate 	(void) dt_pid_fix_mod(pdp, P);
6060Sstevel@tonic-gate 
607*1399Sahl 	return (ret);
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate static pid_t
611*1399Sahl dt_pid_get_pid(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb,
612*1399Sahl     dt_proc_t *dpr)
6130Sstevel@tonic-gate {
6140Sstevel@tonic-gate 	pid_t pid;
6150Sstevel@tonic-gate 	char *c, *last = NULL, *end;
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 	for (c = &pdp->dtpd_provider[0]; *c != '\0'; c++) {
6180Sstevel@tonic-gate 		if (!isdigit(*c))
6190Sstevel@tonic-gate 			last = c;
6200Sstevel@tonic-gate 	}
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	if (last == NULL || (*(++last) == '\0')) {
623*1399Sahl 		(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPROV,
624*1399Sahl 		    "'%s' is not a valid provider", pdp->dtpd_provider);
625*1399Sahl 		return (-1);
6260Sstevel@tonic-gate 	}
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	errno = 0;
6290Sstevel@tonic-gate 	pid = strtol(last, &end, 10);
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	if (errno != 0 || end == last || end[0] != '\0' || pid <= 0) {
632*1399Sahl 		(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPID,
633*1399Sahl 		    "'%s' does not contain a valid pid", pdp->dtpd_provider);
634*1399Sahl 		return (-1);
6350Sstevel@tonic-gate 	}
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	return (pid);
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate 
640*1399Sahl int
641*1399Sahl dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
6420Sstevel@tonic-gate {
6430Sstevel@tonic-gate 	char provname[DTRACE_PROVNAMELEN];
6440Sstevel@tonic-gate 	struct ps_prochandle *P;
6450Sstevel@tonic-gate 	dt_proc_t *dpr;
646*1399Sahl 	pid_t pid;
647*1399Sahl 	int err;
648*1399Sahl 
649*1399Sahl 	assert(pcb != NULL);
650*1399Sahl 
651*1399Sahl 	if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1)
652*1399Sahl 		return (-1);
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate 	if (dtp->dt_ftfd == -1) {
6550Sstevel@tonic-gate 		if (dtp->dt_fterr == ENOENT) {
656*1399Sahl 			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,
657*1399Sahl 			    "pid provider is not installed on this system");
6580Sstevel@tonic-gate 		} else {
659*1399Sahl 			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,
660*1399Sahl 			    "pid provider is not available: %s",
661*1399Sahl 			    strerror(dtp->dt_fterr));
6620Sstevel@tonic-gate 		}
663*1399Sahl 
664*1399Sahl 		return (-1);
6650Sstevel@tonic-gate 	}
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 	(void) snprintf(provname, sizeof (provname), "pid%d", (int)pid);
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate 	if (strcmp(provname, pdp->dtpd_provider) == 0) {
670*1399Sahl 		if ((P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE,
671*1399Sahl 		    0)) == NULL) {
672*1399Sahl 			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,
673*1399Sahl 			    "failed to grab process %d", (int)pid);
674*1399Sahl 			return (-1);
675*1399Sahl 		}
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 		dpr = dt_proc_lookup(dtp, P, 0);
6780Sstevel@tonic-gate 		assert(dpr != NULL);
679*1399Sahl 		(void) pthread_mutex_lock(&dpr->dpr_lock);
6800Sstevel@tonic-gate 
681*1399Sahl 		err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr);
682*1399Sahl 
683*1399Sahl 		(void) pthread_mutex_unlock(&dpr->dpr_lock);
684*1399Sahl 		dt_proc_release(dtp, P);
685*1399Sahl 
686*1399Sahl 	} else {
687*1399Sahl 		if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL) {
688*1399Sahl 			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,
689*1399Sahl 			    "failed to grab process %d", (int)pid);
690*1399Sahl 			return (-1);
691*1399Sahl 		}
692*1399Sahl 
693*1399Sahl 		dpr = dt_proc_lookup(dtp, P, 0);
694*1399Sahl 		assert(dpr != NULL);
6950Sstevel@tonic-gate 		(void) pthread_mutex_lock(&dpr->dpr_lock);
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate 		if (!dpr->dpr_usdt) {
698*1399Sahl 			err = dt_pid_create_usdt_probes(pdp, dtp, pcb, dpr);
6990Sstevel@tonic-gate 			dpr->dpr_usdt = B_TRUE;
7000Sstevel@tonic-gate 		}
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&dpr->dpr_lock);
7030Sstevel@tonic-gate 		dt_proc_release(dtp, P);
704*1399Sahl 	}
7050Sstevel@tonic-gate 
706*1399Sahl 	return (err ? -1 : 0);
7070Sstevel@tonic-gate }
7080Sstevel@tonic-gate 
709*1399Sahl int
7100Sstevel@tonic-gate dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
7110Sstevel@tonic-gate {
7120Sstevel@tonic-gate 	dtrace_prog_t *pgp;
7130Sstevel@tonic-gate 	dt_stmt_t *stp;
7140Sstevel@tonic-gate 	dtrace_probedesc_t *pdp, pd;
7150Sstevel@tonic-gate 	pid_t pid;
716*1399Sahl 	int ret = 0, found = B_FALSE;
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 	for (pgp = dt_list_next(&dtp->dt_programs); pgp != NULL;
7190Sstevel@tonic-gate 	    pgp = dt_list_next(pgp)) {
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 		for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL;
7220Sstevel@tonic-gate 		    stp = dt_list_next(stp)) {
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 			pdp = &stp->ds_desc->dtsd_ecbdesc->dted_probe;
725*1399Sahl 			pid = dt_pid_get_pid(pdp, dtp, NULL, dpr);
726*1399Sahl 			if (pid != dpr->dpr_pid)
7270Sstevel@tonic-gate 				continue;
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 			found = B_TRUE;
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 			pd = *pdp;
7320Sstevel@tonic-gate 
733*1399Sahl 			if (strncmp(pdp->dtpd_provider, "pid", 3) == 0) {
734*1399Sahl 				if (dt_pid_create_pid_probes(&pd, dtp, NULL,
735*1399Sahl 				    dpr) != 0)
736*1399Sahl 					ret = 1;
737*1399Sahl 			} else {
738*1399Sahl 				if (dt_pid_create_usdt_probes(&pd, dtp, NULL,
739*1399Sahl 				    dpr) != 0)
740*1399Sahl 					ret = 1;
741*1399Sahl 			}
7420Sstevel@tonic-gate 		}
7430Sstevel@tonic-gate 	}
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 	if (found) {
7460Sstevel@tonic-gate 		/*
7470Sstevel@tonic-gate 		 * Give DTrace a shot to the ribs to get it to check
7480Sstevel@tonic-gate 		 * out the newly created probes.
7490Sstevel@tonic-gate 		 */
7500Sstevel@tonic-gate 		(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
7510Sstevel@tonic-gate 	}
752*1399Sahl 
753*1399Sahl 	return (ret);
7540Sstevel@tonic-gate }
755