dt_provider.c revision 178529
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 2006 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 <sys/types.h>
30#include <sys/sysmacros.h>
31
32#include <assert.h>
33#include <limits.h>
34#include <strings.h>
35#include <stdlib.h>
36#include <alloca.h>
37#include <unistd.h>
38#include <errno.h>
39
40#include <dt_provider.h>
41#include <dt_module.h>
42#include <dt_string.h>
43#include <dt_list.h>
44
45static dt_provider_t *
46dt_provider_insert(dtrace_hdl_t *dtp, dt_provider_t *pvp, uint_t h)
47{
48	dt_list_append(&dtp->dt_provlist, pvp);
49
50	pvp->pv_next = dtp->dt_provs[h];
51	dtp->dt_provs[h] = pvp;
52	dtp->dt_nprovs++;
53
54	return (pvp);
55}
56
57dt_provider_t *
58dt_provider_lookup(dtrace_hdl_t *dtp, const char *name)
59{
60	uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_provbuckets;
61	dtrace_providerdesc_t desc;
62	dt_provider_t *pvp;
63
64	for (pvp = dtp->dt_provs[h]; pvp != NULL; pvp = pvp->pv_next) {
65		if (strcmp(pvp->pv_desc.dtvd_name, name) == 0)
66			return (pvp);
67	}
68
69	if (strisglob(name) || name[0] == '\0') {
70		(void) dt_set_errno(dtp, EDT_NOPROV);
71		return (NULL);
72	}
73
74	bzero(&desc, sizeof (desc));
75	(void) strlcpy(desc.dtvd_name, name, DTRACE_PROVNAMELEN);
76
77	if (dt_ioctl(dtp, DTRACEIOC_PROVIDER, &desc) == -1) {
78		(void) dt_set_errno(dtp, errno == ESRCH ? EDT_NOPROV : errno);
79		return (NULL);
80	}
81
82	if ((pvp = dt_provider_create(dtp, name)) == NULL)
83		return (NULL); /* dt_errno is set for us */
84
85	bcopy(&desc, &pvp->pv_desc, sizeof (desc));
86	pvp->pv_flags |= DT_PROVIDER_IMPL;
87	return (pvp);
88}
89
90dt_provider_t *
91dt_provider_create(dtrace_hdl_t *dtp, const char *name)
92{
93	dt_provider_t *pvp;
94
95	if ((pvp = dt_zalloc(dtp, sizeof (dt_provider_t))) == NULL)
96		return (NULL);
97
98	(void) strlcpy(pvp->pv_desc.dtvd_name, name, DTRACE_PROVNAMELEN);
99	pvp->pv_probes = dt_idhash_create(pvp->pv_desc.dtvd_name, NULL, 0, 0);
100	pvp->pv_gen = dtp->dt_gen;
101	pvp->pv_hdl = dtp;
102
103	if (pvp->pv_probes == NULL) {
104		dt_free(dtp, pvp);
105		(void) dt_set_errno(dtp, EDT_NOMEM);
106		return (NULL);
107	}
108
109	pvp->pv_desc.dtvd_attr.dtpa_provider = _dtrace_prvattr;
110	pvp->pv_desc.dtvd_attr.dtpa_mod = _dtrace_prvattr;
111	pvp->pv_desc.dtvd_attr.dtpa_func = _dtrace_prvattr;
112	pvp->pv_desc.dtvd_attr.dtpa_name = _dtrace_prvattr;
113	pvp->pv_desc.dtvd_attr.dtpa_args = _dtrace_prvattr;
114
115	return (dt_provider_insert(dtp, pvp,
116	    dt_strtab_hash(name, NULL) % dtp->dt_provbuckets));
117}
118
119void
120dt_provider_destroy(dtrace_hdl_t *dtp, dt_provider_t *pvp)
121{
122	dt_provider_t **pp;
123	uint_t h;
124
125	assert(pvp->pv_hdl == dtp);
126
127	h = dt_strtab_hash(pvp->pv_desc.dtvd_name, NULL) % dtp->dt_provbuckets;
128	pp = &dtp->dt_provs[h];
129
130	while (*pp != NULL && *pp != pvp)
131		pp = &(*pp)->pv_next;
132
133	assert(*pp != NULL && *pp == pvp);
134	*pp = pvp->pv_next;
135
136	dt_list_delete(&dtp->dt_provlist, pvp);
137	dtp->dt_nprovs--;
138
139	if (pvp->pv_probes != NULL)
140		dt_idhash_destroy(pvp->pv_probes);
141
142	dt_node_link_free(&pvp->pv_nodes);
143	dt_free(dtp, pvp->pv_xrefs);
144	dt_free(dtp, pvp);
145}
146
147int
148dt_provider_xref(dtrace_hdl_t *dtp, dt_provider_t *pvp, id_t id)
149{
150	size_t oldsize = BT_SIZEOFMAP(pvp->pv_xrmax);
151	size_t newsize = BT_SIZEOFMAP(dtp->dt_xlatorid);
152
153	assert(id >= 0 && id < dtp->dt_xlatorid);
154
155	if (newsize > oldsize) {
156		ulong_t *xrefs = dt_zalloc(dtp, newsize);
157
158		if (xrefs == NULL)
159			return (-1);
160
161		bcopy(pvp->pv_xrefs, xrefs, oldsize);
162		dt_free(dtp, pvp->pv_xrefs);
163
164		pvp->pv_xrefs = xrefs;
165		pvp->pv_xrmax = dtp->dt_xlatorid;
166	}
167
168	BT_SET(pvp->pv_xrefs, id);
169	return (0);
170}
171
172static uint8_t
173dt_probe_argmap(dt_node_t *xnp, dt_node_t *nnp)
174{
175	uint8_t i;
176
177	for (i = 0; nnp != NULL; i++) {
178		if (nnp->dn_string != NULL &&
179		    strcmp(nnp->dn_string, xnp->dn_string) == 0)
180			break;
181		else
182			nnp = nnp->dn_list;
183	}
184
185	return (i);
186}
187
188static dt_node_t *
189dt_probe_alloc_args(dt_provider_t *pvp, int argc)
190{
191	dt_node_t *args = NULL, *pnp = NULL, *dnp;
192	int i;
193
194	for (i = 0; i < argc; i++, pnp = dnp) {
195		if ((dnp = dt_node_xalloc(pvp->pv_hdl, DT_NODE_TYPE)) == NULL)
196			return (NULL);
197
198		dnp->dn_link = pvp->pv_nodes;
199		pvp->pv_nodes = dnp;
200
201		if (args == NULL)
202			args = dnp;
203		else
204			pnp->dn_list = dnp;
205	}
206
207	return (args);
208}
209
210static size_t
211dt_probe_keylen(const dtrace_probedesc_t *pdp)
212{
213	return (strlen(pdp->dtpd_mod) + 1 +
214	    strlen(pdp->dtpd_func) + 1 + strlen(pdp->dtpd_name) + 1);
215}
216
217static char *
218dt_probe_key(const dtrace_probedesc_t *pdp, char *s)
219{
220	(void) snprintf(s, INT_MAX, "%s:%s:%s",
221	    pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name);
222	return (s);
223}
224
225/*
226 * If a probe was discovered from the kernel, ask dtrace(7D) for a description
227 * of each of its arguments, including native and translated types.
228 */
229static dt_probe_t *
230dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
231{
232	dtrace_hdl_t *dtp = pvp->pv_hdl;
233	char *name = dt_probe_key(pdp, alloca(dt_probe_keylen(pdp)));
234
235	dt_node_t *xargs, *nargs;
236	dt_ident_t *idp;
237	dt_probe_t *prp;
238
239	dtrace_typeinfo_t dtt;
240	int i, nc, xc;
241
242	int adc = _dtrace_argmax;
243	dtrace_argdesc_t *adv = alloca(sizeof (dtrace_argdesc_t) * adc);
244	dtrace_argdesc_t *adp = adv;
245
246	assert(strcmp(pvp->pv_desc.dtvd_name, pdp->dtpd_provider) == 0);
247	assert(pdp->dtpd_id != DTRACE_IDNONE);
248
249	dt_dprintf("discovering probe %s:%s id=%d\n",
250	    pvp->pv_desc.dtvd_name, name, pdp->dtpd_id);
251
252	for (nc = -1, i = 0; i < adc; i++, adp++) {
253		bzero(adp, sizeof (dtrace_argdesc_t));
254		adp->dtargd_ndx = i;
255		adp->dtargd_id = pdp->dtpd_id;
256
257		if (dt_ioctl(dtp, DTRACEIOC_PROBEARG, adp) != 0) {
258			(void) dt_set_errno(dtp, errno);
259			return (NULL);
260		}
261
262		if (adp->dtargd_ndx == DTRACE_ARGNONE)
263			break; /* all argument descs have been retrieved */
264
265		nc = MAX(nc, adp->dtargd_mapping);
266	}
267
268	xc = i;
269	nc++;
270
271	/*
272	 * Now that we have discovered the number of native and translated
273	 * arguments from the argument descriptions, allocate a new probe ident
274	 * and corresponding dt_probe_t and hash it into the provider.
275	 */
276	xargs = dt_probe_alloc_args(pvp, xc);
277	nargs = dt_probe_alloc_args(pvp, nc);
278
279	if ((xc != 0 && xargs == NULL) || (nc != 0 && nargs == NULL))
280		return (NULL); /* dt_errno is set for us */
281
282	idp = dt_ident_create(name, DT_IDENT_PROBE,
283	    DT_IDFLG_ORPHAN, pdp->dtpd_id, _dtrace_defattr, 0,
284	    &dt_idops_probe, NULL, dtp->dt_gen);
285
286	if (idp == NULL) {
287		(void) dt_set_errno(dtp, EDT_NOMEM);
288		return (NULL);
289	}
290
291	if ((prp = dt_probe_create(dtp, idp, 2,
292	    nargs, nc, xargs, xc)) == NULL) {
293		dt_ident_destroy(idp);
294		return (NULL);
295	}
296
297	dt_probe_declare(pvp, prp);
298
299	/*
300	 * Once our new dt_probe_t is fully constructed, iterate over the
301	 * cached argument descriptions and assign types to prp->pr_nargv[]
302	 * and prp->pr_xargv[] and assign mappings to prp->pr_mapping[].
303	 */
304	for (adp = adv, i = 0; i < xc; i++, adp++) {
305		if (dtrace_type_strcompile(dtp,
306		    adp->dtargd_native, &dtt) != 0) {
307			dt_dprintf("failed to resolve input type %s "
308			    "for %s:%s arg #%d: %s\n", adp->dtargd_native,
309			    pvp->pv_desc.dtvd_name, name, i + 1,
310			    dtrace_errmsg(dtp, dtrace_errno(dtp)));
311
312			dtt.dtt_object = NULL;
313			dtt.dtt_ctfp = NULL;
314			dtt.dtt_type = CTF_ERR;
315		} else {
316			dt_node_type_assign(prp->pr_nargv[adp->dtargd_mapping],
317			    dtt.dtt_ctfp, dtt.dtt_type);
318		}
319
320		if (dtt.dtt_type != CTF_ERR && (adp->dtargd_xlate[0] == '\0' ||
321		    strcmp(adp->dtargd_native, adp->dtargd_xlate) == 0)) {
322			dt_node_type_propagate(prp->pr_nargv[
323			    adp->dtargd_mapping], prp->pr_xargv[i]);
324		} else if (dtrace_type_strcompile(dtp,
325		    adp->dtargd_xlate, &dtt) != 0) {
326			dt_dprintf("failed to resolve output type %s "
327			    "for %s:%s arg #%d: %s\n", adp->dtargd_xlate,
328			    pvp->pv_desc.dtvd_name, name, i + 1,
329			    dtrace_errmsg(dtp, dtrace_errno(dtp)));
330
331			dtt.dtt_object = NULL;
332			dtt.dtt_ctfp = NULL;
333			dtt.dtt_type = CTF_ERR;
334		} else {
335			dt_node_type_assign(prp->pr_xargv[i],
336			    dtt.dtt_ctfp, dtt.dtt_type);
337		}
338
339		prp->pr_mapping[i] = adp->dtargd_mapping;
340		prp->pr_argv[i] = dtt;
341	}
342
343	return (prp);
344}
345
346/*
347 * Lookup a probe declaration based on a known provider and full or partially
348 * specified module, function, and name.  If the probe is not known to us yet,
349 * ask dtrace(7D) to match the description and then cache any useful results.
350 */
351dt_probe_t *
352dt_probe_lookup(dt_provider_t *pvp, const char *s)
353{
354	dtrace_hdl_t *dtp = pvp->pv_hdl;
355	dtrace_probedesc_t pd;
356	dt_ident_t *idp;
357	size_t keylen;
358	char *key;
359
360	if (dtrace_str2desc(dtp, DTRACE_PROBESPEC_NAME, s, &pd) != 0)
361		return (NULL); /* dt_errno is set for us */
362
363	keylen = dt_probe_keylen(&pd);
364	key = dt_probe_key(&pd, alloca(keylen));
365
366	/*
367	 * If the probe is already declared, then return the dt_probe_t from
368	 * the existing identifier.  This could come from a static declaration
369	 * or it could have been cached from an earlier call to this function.
370	 */
371	if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL)
372		return (idp->di_data);
373
374	/*
375	 * If the probe isn't known, use the probe description computed above
376	 * to ask dtrace(7D) to find the first matching probe.
377	 */
378	if (dt_ioctl(dtp, DTRACEIOC_PROBEMATCH, &pd) == 0)
379		return (dt_probe_discover(pvp, &pd));
380
381	if (errno == ESRCH || errno == EBADF)
382		(void) dt_set_errno(dtp, EDT_NOPROBE);
383	else
384		(void) dt_set_errno(dtp, errno);
385
386	return (NULL);
387}
388
389dt_probe_t *
390dt_probe_create(dtrace_hdl_t *dtp, dt_ident_t *idp, int protoc,
391    dt_node_t *nargs, uint_t nargc, dt_node_t *xargs, uint_t xargc)
392{
393	dt_module_t *dmp;
394	dt_probe_t *prp;
395	const char *p;
396	uint_t i;
397
398	assert(idp->di_kind == DT_IDENT_PROBE);
399	assert(idp->di_data == NULL);
400
401	/*
402	 * If only a single prototype is given, set xargc/s to nargc/s to
403	 * simplify subsequent use.  Note that we can have one or both of nargs
404	 * and xargs be specified but set to NULL, indicating a void prototype.
405	 */
406	if (protoc < 2) {
407		assert(xargs == NULL);
408		assert(xargc == 0);
409		xargs = nargs;
410		xargc = nargc;
411	}
412
413	if ((prp = dt_alloc(dtp, sizeof (dt_probe_t))) == NULL)
414		return (NULL);
415
416	prp->pr_pvp = NULL;
417	prp->pr_ident = idp;
418
419	p = strrchr(idp->di_name, ':');
420	assert(p != NULL);
421	prp->pr_name = p + 1;
422
423	prp->pr_nargs = nargs;
424	prp->pr_nargv = dt_alloc(dtp, sizeof (dt_node_t *) * nargc);
425	prp->pr_nargc = nargc;
426	prp->pr_xargs = xargs;
427	prp->pr_xargv = dt_alloc(dtp, sizeof (dt_node_t *) * xargc);
428	prp->pr_xargc = xargc;
429	prp->pr_mapping = dt_alloc(dtp, sizeof (uint8_t) * xargc);
430	prp->pr_inst = NULL;
431	prp->pr_argv = dt_alloc(dtp, sizeof (dtrace_typeinfo_t) * xargc);
432	prp->pr_argc = xargc;
433
434	if ((prp->pr_nargc != 0 && prp->pr_nargv == NULL) ||
435	    (prp->pr_xargc != 0 && prp->pr_xargv == NULL) ||
436	    (prp->pr_xargc != 0 && prp->pr_mapping == NULL) ||
437	    (prp->pr_argc != 0 && prp->pr_argv == NULL)) {
438		dt_probe_destroy(prp);
439		return (NULL);
440	}
441
442	for (i = 0; i < xargc; i++, xargs = xargs->dn_list) {
443		if (xargs->dn_string != NULL)
444			prp->pr_mapping[i] = dt_probe_argmap(xargs, nargs);
445		else
446			prp->pr_mapping[i] = i;
447
448		prp->pr_xargv[i] = xargs;
449
450		if ((dmp = dt_module_lookup_by_ctf(dtp,
451		    xargs->dn_ctfp)) != NULL)
452			prp->pr_argv[i].dtt_object = dmp->dm_name;
453		else
454			prp->pr_argv[i].dtt_object = NULL;
455
456		prp->pr_argv[i].dtt_ctfp = xargs->dn_ctfp;
457		prp->pr_argv[i].dtt_type = xargs->dn_type;
458	}
459
460	for (i = 0; i < nargc; i++, nargs = nargs->dn_list)
461		prp->pr_nargv[i] = nargs;
462
463	idp->di_data = prp;
464	return (prp);
465}
466
467void
468dt_probe_declare(dt_provider_t *pvp, dt_probe_t *prp)
469{
470	assert(prp->pr_ident->di_kind == DT_IDENT_PROBE);
471	assert(prp->pr_ident->di_data == prp);
472	assert(prp->pr_pvp == NULL);
473
474	if (prp->pr_xargs != prp->pr_nargs)
475		pvp->pv_flags &= ~DT_PROVIDER_INTF;
476
477	prp->pr_pvp = pvp;
478	dt_idhash_xinsert(pvp->pv_probes, prp->pr_ident);
479}
480
481void
482dt_probe_destroy(dt_probe_t *prp)
483{
484	dt_probe_instance_t *pip, *pip_next;
485	dtrace_hdl_t *dtp;
486
487	if (prp->pr_pvp != NULL)
488		dtp = prp->pr_pvp->pv_hdl;
489	else
490		dtp = yypcb->pcb_hdl;
491
492	dt_node_list_free(&prp->pr_nargs);
493	dt_node_list_free(&prp->pr_xargs);
494
495	dt_free(dtp, prp->pr_nargv);
496	dt_free(dtp, prp->pr_xargv);
497
498	for (pip = prp->pr_inst; pip != NULL; pip = pip_next) {
499		pip_next = pip->pi_next;
500		dt_free(dtp, pip->pi_offs);
501		dt_free(dtp, pip->pi_enoffs);
502		dt_free(dtp, pip);
503	}
504
505	dt_free(dtp, prp->pr_mapping);
506	dt_free(dtp, prp->pr_argv);
507	dt_free(dtp, prp);
508}
509
510int
511dt_probe_define(dt_provider_t *pvp, dt_probe_t *prp,
512    const char *fname, const char *rname, uint32_t offset, int isenabled)
513{
514	dtrace_hdl_t *dtp = pvp->pv_hdl;
515	dt_probe_instance_t *pip;
516	uint32_t **offs;
517	uint_t *noffs, *maxoffs;
518
519	assert(fname != NULL);
520
521	for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) {
522		if (strcmp(pip->pi_fname, fname) == 0 &&
523		    ((rname == NULL && pip->pi_rname[0] == '\0') ||
524		    (rname != NULL && strcmp(pip->pi_rname, rname)) == 0))
525			break;
526	}
527
528	if (pip == NULL) {
529		if ((pip = dt_zalloc(dtp, sizeof (*pip))) == NULL)
530			return (-1);
531
532		if ((pip->pi_offs = dt_zalloc(dtp,
533		    sizeof (uint32_t))) == NULL) {
534			dt_free(dtp, pip);
535			return (-1);
536		}
537
538		if ((pip->pi_enoffs = dt_zalloc(dtp,
539		    sizeof (uint32_t))) == NULL) {
540			dt_free(dtp, pip->pi_offs);
541			dt_free(dtp, pip);
542			return (-1);
543		}
544
545		(void) strlcpy(pip->pi_fname, fname, sizeof (pip->pi_fname));
546		if (rname != NULL) {
547			if (strlen(rname) + 1 > sizeof (pip->pi_rname)) {
548				dt_free(dtp, pip->pi_offs);
549				dt_free(dtp, pip);
550				return (dt_set_errno(dtp, EDT_COMPILER));
551			}
552			(void) strcpy(pip->pi_rname, rname);
553		}
554
555		pip->pi_noffs = 0;
556		pip->pi_maxoffs = 1;
557		pip->pi_nenoffs = 0;
558		pip->pi_maxenoffs = 1;
559
560		pip->pi_next = prp->pr_inst;
561
562		prp->pr_inst = pip;
563	}
564
565	if (isenabled) {
566		offs = &pip->pi_enoffs;
567		noffs = &pip->pi_nenoffs;
568		maxoffs = &pip->pi_maxenoffs;
569	} else {
570		offs = &pip->pi_offs;
571		noffs = &pip->pi_noffs;
572		maxoffs = &pip->pi_maxoffs;
573	}
574
575	if (*noffs == *maxoffs) {
576		uint_t new_max = *maxoffs * 2;
577		uint32_t *new_offs = dt_alloc(dtp, sizeof (uint32_t) * new_max);
578
579		if (new_offs == NULL)
580			return (-1);
581
582		bcopy(*offs, new_offs, sizeof (uint32_t) * *maxoffs);
583
584		dt_free(dtp, *offs);
585		*maxoffs = new_max;
586		*offs = new_offs;
587	}
588
589	dt_dprintf("defined probe %s %s:%s %s() +0x%x (%s)\n",
590	    isenabled ? "(is-enabled)" : "",
591	    pvp->pv_desc.dtvd_name, prp->pr_ident->di_name, fname, offset,
592	    rname != NULL ? rname : fname);
593
594	assert(*noffs < *maxoffs);
595	(*offs)[(*noffs)++] = offset;
596
597	return (0);
598}
599
600/*
601 * Lookup the dynamic translator type tag for the specified probe argument and
602 * assign the type to the specified node.  If the type is not yet defined, add
603 * it to the "D" module's type container as a typedef for an unknown type.
604 */
605dt_node_t *
606dt_probe_tag(dt_probe_t *prp, uint_t argn, dt_node_t *dnp)
607{
608	dtrace_hdl_t *dtp = prp->pr_pvp->pv_hdl;
609	dtrace_typeinfo_t dtt;
610	size_t len;
611	char *tag;
612
613	len = snprintf(NULL, 0, "__dtrace_%s___%s_arg%u",
614	    prp->pr_pvp->pv_desc.dtvd_name, prp->pr_name, argn);
615
616	tag = alloca(len + 1);
617
618	(void) snprintf(tag, len + 1, "__dtrace_%s___%s_arg%u",
619	    prp->pr_pvp->pv_desc.dtvd_name, prp->pr_name, argn);
620
621	if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_DDEFS, tag, &dtt) != 0) {
622		dtt.dtt_object = DTRACE_OBJ_DDEFS;
623		dtt.dtt_ctfp = DT_DYN_CTFP(dtp);
624		dtt.dtt_type = ctf_add_typedef(DT_DYN_CTFP(dtp),
625		    CTF_ADD_ROOT, tag, DT_DYN_TYPE(dtp));
626
627		if (dtt.dtt_type == CTF_ERR ||
628		    ctf_update(dtt.dtt_ctfp) == CTF_ERR) {
629			xyerror(D_UNKNOWN, "cannot define type %s: %s\n",
630			    tag, ctf_errmsg(ctf_errno(dtt.dtt_ctfp)));
631		}
632	}
633
634	bzero(dnp, sizeof (dt_node_t));
635	dnp->dn_kind = DT_NODE_TYPE;
636
637	dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
638	dt_node_attr_assign(dnp, _dtrace_defattr);
639
640	return (dnp);
641}
642
643/*ARGSUSED*/
644static int
645dt_probe_desc(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, void *arg)
646{
647	if (((dtrace_probedesc_t *)arg)->dtpd_id == DTRACE_IDNONE) {
648		bcopy(pdp, arg, sizeof (dtrace_probedesc_t));
649		return (0);
650	}
651
652	return (1);
653}
654
655dt_probe_t *
656dt_probe_info(dtrace_hdl_t *dtp,
657    const dtrace_probedesc_t *pdp, dtrace_probeinfo_t *pip)
658{
659	int m_is_glob = pdp->dtpd_mod[0] == '\0' || strisglob(pdp->dtpd_mod);
660	int f_is_glob = pdp->dtpd_func[0] == '\0' || strisglob(pdp->dtpd_func);
661	int n_is_glob = pdp->dtpd_name[0] == '\0' || strisglob(pdp->dtpd_name);
662
663	dt_probe_t *prp = NULL;
664	const dtrace_pattr_t *pap;
665	dt_provider_t *pvp;
666	dt_ident_t *idp;
667
668	/*
669	 * Attempt to lookup the probe in our existing cache for this provider.
670	 * If none is found and an explicit probe ID was specified, discover
671	 * that specific probe and cache its description and arguments.
672	 */
673	if ((pvp = dt_provider_lookup(dtp, pdp->dtpd_provider)) != NULL) {
674		size_t keylen = dt_probe_keylen(pdp);
675		char *key = dt_probe_key(pdp, alloca(keylen));
676
677		if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL)
678			prp = idp->di_data;
679		else if (pdp->dtpd_id != DTRACE_IDNONE)
680			prp = dt_probe_discover(pvp, pdp);
681	}
682
683	/*
684	 * If no probe was found in our cache, convert the caller's partial
685	 * probe description into a fully-formed matching probe description by
686	 * iterating over up to at most two probes that match 'pdp'.  We then
687	 * call dt_probe_discover() on the resulting probe identifier.
688	 */
689	if (prp == NULL) {
690		dtrace_probedesc_t pd;
691		int m;
692
693		bzero(&pd, sizeof (pd));
694		pd.dtpd_id = DTRACE_IDNONE;
695
696		/*
697		 * Call dtrace_probe_iter() to find matching probes.  Our
698		 * dt_probe_desc() callback will produce the following results:
699		 *
700		 * m < 0 dtrace_probe_iter() found zero matches (or failed).
701		 * m > 0 dtrace_probe_iter() found more than one match.
702		 * m = 0 dtrace_probe_iter() found exactly one match.
703		 */
704		if ((m = dtrace_probe_iter(dtp, pdp, dt_probe_desc, &pd)) < 0)
705			return (NULL); /* dt_errno is set for us */
706
707		if ((pvp = dt_provider_lookup(dtp, pd.dtpd_provider)) == NULL)
708			return (NULL); /* dt_errno is set for us */
709
710		/*
711		 * If more than one probe was matched, then do not report probe
712		 * information if either of the following conditions is true:
713		 *
714		 * (a) The Arguments Data stability of the matched provider is
715		 *	less than Evolving.
716		 *
717		 * (b) Any description component that is at least Evolving is
718		 *	empty or is specified using a globbing expression.
719		 *
720		 * These conditions imply that providers that provide Evolving
721		 * or better Arguments Data stability must guarantee that all
722		 * probes with identical field names in a field of Evolving or
723		 * better Name stability have identical argument signatures.
724		 */
725		if (m > 0) {
726			if (pvp->pv_desc.dtvd_attr.dtpa_args.dtat_data <
727			    DTRACE_STABILITY_EVOLVING) {
728				(void) dt_set_errno(dtp, EDT_UNSTABLE);
729				return (NULL);
730			}
731
732
733			if (pvp->pv_desc.dtvd_attr.dtpa_mod.dtat_name >=
734			    DTRACE_STABILITY_EVOLVING && m_is_glob) {
735				(void) dt_set_errno(dtp, EDT_UNSTABLE);
736				return (NULL);
737			}
738
739			if (pvp->pv_desc.dtvd_attr.dtpa_func.dtat_name >=
740			    DTRACE_STABILITY_EVOLVING && f_is_glob) {
741				(void) dt_set_errno(dtp, EDT_UNSTABLE);
742				return (NULL);
743			}
744
745			if (pvp->pv_desc.dtvd_attr.dtpa_name.dtat_name >=
746			    DTRACE_STABILITY_EVOLVING && n_is_glob) {
747				(void) dt_set_errno(dtp, EDT_UNSTABLE);
748				return (NULL);
749			}
750		}
751
752		/*
753		 * If we matched a probe exported by dtrace(7D), then discover
754		 * the real attributes.  Otherwise grab the static declaration.
755		 */
756		if (pd.dtpd_id != DTRACE_IDNONE)
757			prp = dt_probe_discover(pvp, &pd);
758		else
759			prp = dt_probe_lookup(pvp, pd.dtpd_name);
760
761		if (prp == NULL)
762			return (NULL); /* dt_errno is set for us */
763	}
764
765	assert(pvp != NULL && prp != NULL);
766
767	/*
768	 * Compute the probe description attributes by taking the minimum of
769	 * the attributes of the specified fields.  If no provider is specified
770	 * or a glob pattern is used for the provider, use Unstable attributes.
771	 */
772	if (pdp->dtpd_provider[0] == '\0' || strisglob(pdp->dtpd_provider))
773		pap = &_dtrace_prvdesc;
774	else
775		pap = &pvp->pv_desc.dtvd_attr;
776
777	pip->dtp_attr = pap->dtpa_provider;
778
779	if (!m_is_glob)
780		pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_mod);
781	if (!f_is_glob)
782		pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_func);
783	if (!n_is_glob)
784		pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_name);
785
786	pip->dtp_arga = pap->dtpa_args;
787	pip->dtp_argv = prp->pr_argv;
788	pip->dtp_argc = prp->pr_argc;
789
790	return (prp);
791}
792
793int
794dtrace_probe_info(dtrace_hdl_t *dtp,
795    const dtrace_probedesc_t *pdp, dtrace_probeinfo_t *pip)
796{
797	return (dt_probe_info(dtp, pdp, pip) != NULL ? 0 : -1);
798}
799
800/*ARGSUSED*/
801static int
802dt_probe_iter(dt_idhash_t *ihp, dt_ident_t *idp, dt_probe_iter_t *pit)
803{
804	const dt_probe_t *prp = idp->di_data;
805
806	if (!dt_gmatch(prp->pr_name, pit->pit_pat))
807		return (0); /* continue on and examine next probe in hash */
808
809	(void) strlcpy(pit->pit_desc.dtpd_name, prp->pr_name, DTRACE_NAMELEN);
810	pit->pit_desc.dtpd_id = idp->di_id;
811	pit->pit_matches++;
812
813	return (pit->pit_func(pit->pit_hdl, &pit->pit_desc, pit->pit_arg));
814}
815
816int
817dtrace_probe_iter(dtrace_hdl_t *dtp,
818    const dtrace_probedesc_t *pdp, dtrace_probe_f *func, void *arg)
819{
820	const char *provider = pdp ? pdp->dtpd_provider : NULL;
821	dtrace_id_t id = DTRACE_IDNONE;
822
823	dtrace_probedesc_t pd;
824	dt_probe_iter_t pit;
825	int cmd, rv;
826
827	bzero(&pit, sizeof (pit));
828	pit.pit_hdl = dtp;
829	pit.pit_func = func;
830	pit.pit_arg = arg;
831	pit.pit_pat = pdp ? pdp->dtpd_name : NULL;
832
833	for (pit.pit_pvp = dt_list_next(&dtp->dt_provlist);
834	    pit.pit_pvp != NULL; pit.pit_pvp = dt_list_next(pit.pit_pvp)) {
835
836		if (pit.pit_pvp->pv_flags & DT_PROVIDER_IMPL)
837			continue; /* we'll get these later using dt_ioctl() */
838
839		if (!dt_gmatch(pit.pit_pvp->pv_desc.dtvd_name, provider))
840			continue;
841
842		(void) strlcpy(pit.pit_desc.dtpd_provider,
843		    pit.pit_pvp->pv_desc.dtvd_name, DTRACE_PROVNAMELEN);
844
845		if ((rv = dt_idhash_iter(pit.pit_pvp->pv_probes,
846		    (dt_idhash_f *)dt_probe_iter, &pit)) != 0)
847			return (rv);
848	}
849
850	if (pdp != NULL)
851		cmd = DTRACEIOC_PROBEMATCH;
852	else
853		cmd = DTRACEIOC_PROBES;
854
855	for (;;) {
856		if (pdp != NULL)
857			bcopy(pdp, &pd, sizeof (pd));
858
859		pd.dtpd_id = id;
860
861		if (dt_ioctl(dtp, cmd, &pd) != 0)
862			break;
863		else if ((rv = func(dtp, &pd, arg)) != 0)
864			return (rv);
865
866		pit.pit_matches++;
867		id = pd.dtpd_id + 1;
868	}
869
870	switch (errno) {
871	case ESRCH:
872	case EBADF:
873		return (pit.pit_matches ? 0 : dt_set_errno(dtp, EDT_NOPROBE));
874	case EINVAL:
875		return (dt_set_errno(dtp, EDT_BADPGLOB));
876	default:
877		return (dt_set_errno(dtp, errno));
878	}
879}
880