xref: /titanic_44/usr/src/lib/libdtrace/common/dt_ident.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 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/sysmacros.h>
30 #include <strings.h>
31 #include <stdlib.h>
32 #include <alloca.h>
33 #include <assert.h>
34 #include <errno.h>
35 #include <ctype.h>
36 #include <sys/procfs_isa.h>
37 #include <limits.h>
38 
39 #include <dt_ident.h>
40 #include <dt_parser.h>
41 #include <dt_provider.h>
42 #include <dt_strtab.h>
43 #include <dt_impl.h>
44 
45 /*
46  * Common code for cooking an identifier that uses a typed signature list (we
47  * use this for associative arrays and functions).  If the argument list is
48  * of the same length and types, then return the return type.  Otherwise
49  * print an appropriate compiler error message and abort the compile.
50  */
51 static void
52 dt_idcook_sign(dt_node_t *dnp, dt_ident_t *idp,
53     int argc, dt_node_t *args, const char *prefix, const char *suffix)
54 {
55 	dt_idsig_t *isp = idp->di_data;
56 	int i, compat, mismatch, arglimit;
57 
58 	char n1[DT_TYPE_NAMELEN];
59 	char n2[DT_TYPE_NAMELEN];
60 
61 	if (isp->dis_varargs >= 0) {
62 		mismatch = argc < isp->dis_varargs;
63 		arglimit = isp->dis_varargs;
64 	} else if (isp->dis_optargs >= 0) {
65 		mismatch = (argc < isp->dis_optargs || argc > isp->dis_argc);
66 		arglimit = argc;
67 	} else {
68 		mismatch = argc != isp->dis_argc;
69 		arglimit = isp->dis_argc;
70 	}
71 
72 	if (mismatch) {
73 		xyerror(D_PROTO_LEN, "%s%s%s prototype mismatch: %d arg%s"
74 		    "passed, %s%d expected\n", prefix, idp->di_name, suffix,
75 		    argc, argc == 1 ? " " : "s ",
76 		    isp->dis_optargs >= 0 ? "at least " : "",
77 		    isp->dis_optargs >= 0 ? isp->dis_optargs : arglimit);
78 	}
79 
80 	for (i = 0; i < arglimit; i++, args = args->dn_list) {
81 		if (isp->dis_args[i].dn_ctfp != NULL)
82 			compat = dt_node_is_argcompat(&isp->dis_args[i], args);
83 		else
84 			compat = 1; /* "@" matches any type */
85 
86 		if (!compat) {
87 			xyerror(D_PROTO_ARG,
88 			    "%s%s%s argument #%d is incompatible with "
89 			    "prototype:\n\tprototype: %s\n\t argument: %s\n",
90 			    prefix, idp->di_name, suffix, i + 1,
91 			    dt_node_type_name(&isp->dis_args[i], n1,
92 			    sizeof (n1)),
93 			    dt_node_type_name(args, n2, sizeof (n2)));
94 		}
95 	}
96 
97 	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
98 }
99 
100 /*
101  * Cook an associative array identifier.  If this is the first time we are
102  * cooking this array, create its signature based on the argument list.
103  * Otherwise validate the argument list against the existing signature.
104  */
105 static void
106 dt_idcook_assc(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
107 {
108 	if (idp->di_data == NULL) {
109 		dt_idsig_t *isp = idp->di_data = malloc(sizeof (dt_idsig_t));
110 		char n[DT_TYPE_NAMELEN];
111 		int i;
112 
113 		if (isp == NULL)
114 			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
115 
116 		isp->dis_varargs = -1;
117 		isp->dis_optargs = -1;
118 		isp->dis_argc = argc;
119 		isp->dis_args = NULL;
120 
121 		if (argc != 0 && (isp->dis_args = calloc(argc,
122 		    sizeof (dt_node_t))) == NULL) {
123 			idp->di_data = NULL;
124 			free(isp);
125 			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
126 		}
127 
128 		/*
129 		 * If this identifier has not been explicitly declared earlier,
130 		 * set the identifier's base type to be our special type <DYN>.
131 		 * If this ident is an aggregation, it will remain as is.  If
132 		 * this ident is an associative array, it will be reassigned
133 		 * based on the result type of the first assignment statement.
134 		 */
135 		if (!(idp->di_flags & DT_IDFLG_DECL)) {
136 			idp->di_ctfp = DT_DYN_CTFP(yypcb->pcb_hdl);
137 			idp->di_type = DT_DYN_TYPE(yypcb->pcb_hdl);
138 		}
139 
140 		for (i = 0; i < argc; i++, args = args->dn_list) {
141 			if (dt_node_is_dynamic(args) || dt_node_is_void(args)) {
142 				xyerror(D_KEY_TYPE, "%s expression may not be "
143 				    "used as %s index: key #%d\n",
144 				    dt_node_type_name(args, n, sizeof (n)),
145 				    dt_idkind_name(idp->di_kind), i + 1);
146 			}
147 
148 			dt_node_type_propagate(args, &isp->dis_args[i]);
149 			isp->dis_args[i].dn_list = &isp->dis_args[i + 1];
150 		}
151 
152 		if (argc != 0)
153 			isp->dis_args[argc - 1].dn_list = NULL;
154 
155 		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
156 
157 	} else {
158 		dt_idcook_sign(dnp, idp, argc, args,
159 		    idp->di_kind == DT_IDENT_AGG ? "@" : "", "[ ]");
160 	}
161 }
162 
163 /*
164  * Cook a function call.  If this is the first time we are cooking this
165  * identifier, create its type signature based on predefined prototype stored
166  * in di_iarg.  We then validate the argument list against this signature.
167  */
168 static void
169 dt_idcook_func(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
170 {
171 	if (idp->di_data == NULL) {
172 		dtrace_hdl_t *dtp = yypcb->pcb_hdl;
173 		dtrace_typeinfo_t dtt;
174 		dt_idsig_t *isp;
175 		char *s, *p1, *p2;
176 		int i = 0;
177 
178 		assert(idp->di_iarg != NULL);
179 		s = alloca(strlen(idp->di_iarg) + 1);
180 		(void) strcpy(s, idp->di_iarg);
181 
182 		if ((p2 = strrchr(s, ')')) != NULL)
183 			*p2 = '\0'; /* mark end of parameter list string */
184 
185 		if ((p1 = strchr(s, '(')) != NULL)
186 			*p1++ = '\0'; /* mark end of return type string */
187 
188 		if (p1 == NULL || p2 == NULL) {
189 			xyerror(D_UNKNOWN, "internal error: malformed entry "
190 			    "for built-in function %s\n", idp->di_name);
191 		}
192 
193 		for (p2 = p1; *p2 != '\0'; p2++) {
194 			if (!isspace(*p2)) {
195 				i++;
196 				break;
197 			}
198 		}
199 
200 		for (p2 = strchr(p2, ','); p2++ != NULL; i++)
201 			p2 = strchr(p2, ',');
202 
203 		/*
204 		 * We first allocate a new ident signature structure with the
205 		 * appropriate number of argument entries, and then look up
206 		 * the return type and store its CTF data in di_ctfp/type.
207 		 */
208 		if ((isp = idp->di_data = malloc(sizeof (dt_idsig_t))) == NULL)
209 			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
210 
211 		isp->dis_varargs = -1;
212 		isp->dis_optargs = -1;
213 		isp->dis_argc = i;
214 		isp->dis_args = NULL;
215 
216 		if (i != 0 && (isp->dis_args = calloc(i,
217 		    sizeof (dt_node_t))) == NULL) {
218 			idp->di_data = NULL;
219 			free(isp);
220 			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
221 		}
222 
223 		if (dt_type_lookup(s, &dtt) == -1) {
224 			xyerror(D_UNKNOWN, "failed to resolve type of %s (%s):"
225 			    " %s\n", idp->di_name, s,
226 			    dtrace_errmsg(dtp, dtrace_errno(dtp)));
227 		}
228 
229 		if (idp->di_kind == DT_IDENT_AGGFUNC) {
230 			idp->di_ctfp = DT_DYN_CTFP(dtp);
231 			idp->di_type = DT_DYN_TYPE(dtp);
232 		} else {
233 			idp->di_ctfp = dtt.dtt_ctfp;
234 			idp->di_type = dtt.dtt_type;
235 		}
236 
237 		/*
238 		 * For each comma-delimited parameter in the prototype string,
239 		 * we look up the corresponding type and store its CTF data in
240 		 * the corresponding location in dis_args[].  We also recognize
241 		 * the special type string "@" to indicate that the specified
242 		 * parameter may be a D expression of *any* type (represented
243 		 * as a dis_args[] element with ctfp = NULL, type == CTF_ERR).
244 		 * If a varargs "..." is present, we record the argument index
245 		 * in dis_varargs for the benefit of dt_idcook_sign(), above.
246 		 * If the type of an argument is enclosed in square brackets
247 		 * (e.g. "[int]"), the argument is considered optional:  the
248 		 * argument may be absent, but if it is present, it must be of
249 		 * the specified type.  Note that varargs may not optional,
250 		 * optional arguments may not follow varargs, and non-optional
251 		 * arguments may not follow optional arguments.
252 		 */
253 		for (i = 0; i < isp->dis_argc; i++, p1 = p2) {
254 			while (isspace(*p1))
255 				p1++; /* skip leading whitespace */
256 
257 			if ((p2 = strchr(p1, ',')) == NULL)
258 				p2 = p1 + strlen(p1);
259 			else
260 				*p2++ = '\0';
261 
262 			if (strcmp(p1, "@") == 0 || strcmp(p1, "...") == 0) {
263 				isp->dis_args[i].dn_ctfp = NULL;
264 				isp->dis_args[i].dn_type = CTF_ERR;
265 				if (*p1 == '.')
266 					isp->dis_varargs = i;
267 				continue;
268 			}
269 
270 			if (*p1 == '[' && p1[strlen(p1) - 1] == ']') {
271 				if (isp->dis_varargs != -1) {
272 					xyerror(D_UNKNOWN, "optional arg#%d "
273 					    "may not follow variable arg#%d\n",
274 					    i + 1, isp->dis_varargs + 1);
275 				}
276 
277 				if (isp->dis_optargs == -1)
278 					isp->dis_optargs = i;
279 
280 				p1[strlen(p1) - 1] = '\0';
281 				p1++;
282 			} else if (isp->dis_optargs != -1) {
283 				xyerror(D_UNKNOWN, "required arg#%d may not "
284 				    "follow optional arg#%d\n", i + 1,
285 				    isp->dis_optargs + 1);
286 			}
287 
288 			if (dt_type_lookup(p1, &dtt) == -1) {
289 				xyerror(D_UNKNOWN, "failed to resolve type of "
290 				    "%s arg#%d (%s): %s\n", idp->di_name, i + 1,
291 				    p1, dtrace_errmsg(dtp, dtrace_errno(dtp)));
292 			}
293 
294 			dt_node_type_assign(&isp->dis_args[i],
295 			    dtt.dtt_ctfp, dtt.dtt_type);
296 		}
297 	}
298 
299 	dt_idcook_sign(dnp, idp, argc, args, "", "( )");
300 }
301 
302 /*
303  * Cook a reference to the dynamically typed args[] array.  We verify that the
304  * reference is using a single integer constant, and then construct a new ident
305  * representing the appropriate type or translation specifically for this node.
306  */
307 static void
308 dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
309 {
310 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
311 	dt_probe_t *prp = yypcb->pcb_probe;
312 
313 	dt_node_t *nnp, *xnp;
314 	dt_xlator_t *dxp;
315 	dt_ident_t *xidp;
316 
317 	char n1[DT_TYPE_NAMELEN];
318 	char n2[DT_TYPE_NAMELEN];
319 
320 	if (argc != 1) {
321 		xyerror(D_PROTO_LEN, "%s[ ] prototype mismatch: %d arg%s"
322 		    "passed, 1 expected\n", idp->di_name, argc,
323 		    argc == 1 ? " " : "s ");
324 	}
325 
326 	if (ap->dn_kind != DT_NODE_INT) {
327 		xyerror(D_PROTO_ARG, "%s[ ] argument #1 is incompatible with "
328 		    "prototype:\n\tprototype: %s\n\t argument: %s\n",
329 		    idp->di_name, "integer constant",
330 		    dt_type_name(ap->dn_ctfp, ap->dn_type, n1, sizeof (n1)));
331 	}
332 
333 	if (yypcb->pcb_pdesc == NULL) {
334 		xyerror(D_ARGS_NONE, "%s[ ] may not be referenced outside "
335 		    "of a probe clause\n", idp->di_name);
336 	}
337 
338 	if (prp == NULL) {
339 		xyerror(D_ARGS_MULTI,
340 		    "%s[ ] may not be referenced because probe description %s "
341 		    "matches an unstable set of probes\n", idp->di_name,
342 		    dtrace_desc2str(yypcb->pcb_pdesc, n1, sizeof (n1)));
343 	}
344 
345 	if (ap->dn_value >= prp->pr_argc) {
346 		xyerror(D_ARGS_IDX, "index %lld is out of range for %s %s[ ]\n",
347 		    (longlong_t)ap->dn_value, dtrace_desc2str(yypcb->pcb_pdesc,
348 		    n1, sizeof (n1)), idp->di_name);
349 	}
350 
351 	/*
352 	 * In order to support statically-defined KSDT translators, look up the
353 	 * native and translated argument types for the representative probe.
354 	 * If no translation is needed, these will be the same underlying node.
355 	 * If translation is needed, look up the appropriate translator.  Once
356 	 * we have the appropriate node, create a new dt_ident_t for this node,
357 	 * assign it the appropriate attributes, and set the type of 'dnp'.
358 	 */
359 	xnp = prp->pr_xargv[ap->dn_value];
360 	nnp = prp->pr_nargv[prp->pr_mapping[ap->dn_value]];
361 
362 	if (xnp->dn_type == CTF_ERR) {
363 		xyerror(D_ARGS_TYPE, "failed to resolve translated type for "
364 		    "%s[%lld]\n", idp->di_name, (longlong_t)ap->dn_value);
365 	}
366 
367 	if (nnp->dn_type == CTF_ERR) {
368 		xyerror(D_ARGS_TYPE, "failed to resolve native type for "
369 		    "%s[%lld]\n", idp->di_name, (longlong_t)ap->dn_value);
370 	}
371 
372 	if (nnp == xnp || dt_node_is_argcompat(nnp, xnp)) {
373 		dnp->dn_ident = dt_ident_create(idp->di_name, idp->di_kind,
374 		    idp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr,
375 		    idp->di_vers, idp->di_ops, idp->di_iarg, dtp->dt_gen);
376 
377 		if (dnp->dn_ident == NULL)
378 			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
379 
380 		dt_node_type_assign(dnp,
381 		    prp->pr_argv[ap->dn_value].dtt_ctfp,
382 		    prp->pr_argv[ap->dn_value].dtt_type);
383 
384 	} else if ((dxp = dt_xlator_lookup(dtp,
385 	    nnp, xnp, DT_XLATE_FUZZY)) != NULL) {
386 
387 		xidp = dt_xlator_ident(dxp, xnp->dn_ctfp, xnp->dn_type);
388 
389 		dnp->dn_ident = dt_ident_create(idp->di_name, xidp->di_kind,
390 		    xidp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr,
391 		    idp->di_vers, idp->di_ops, idp->di_iarg, dtp->dt_gen);
392 
393 		if (dnp->dn_ident == NULL)
394 			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
395 
396 		/*
397 		 * Propagate relevant members from the translator's internal
398 		 * dt_ident_t.  This code must be kept in sync with the state
399 		 * that is initialized for idents in dt_xlator_create().
400 		 */
401 		dnp->dn_ident->di_data = xidp->di_data;
402 		dnp->dn_ident->di_ctfp = xidp->di_ctfp;
403 		dnp->dn_ident->di_type = xidp->di_type;
404 
405 		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
406 
407 	} else {
408 		xyerror(D_ARGS_XLATOR, "translator for %s[%lld] from %s to %s "
409 		    "is not defined\n", idp->di_name, (longlong_t)ap->dn_value,
410 		    dt_node_type_name(nnp, n1, sizeof (n1)),
411 		    dt_node_type_name(xnp, n2, sizeof (n2)));
412 	}
413 
414 	assert(dnp->dn_ident->di_flags & DT_IDFLG_ORPHAN);
415 	assert(dnp->dn_ident->di_id == idp->di_id);
416 }
417 
418 static void
419 dt_idcook_regs(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
420 {
421 	dtrace_typeinfo_t dtt;
422 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
423 	char n[DT_TYPE_NAMELEN];
424 
425 	if (argc != 1) {
426 		xyerror(D_PROTO_LEN, "%s[ ] prototype mismatch: %d arg%s"
427 		    "passed, 1 expected\n", idp->di_name,
428 		    argc, argc == 1 ? " " : "s ");
429 	}
430 
431 	if (ap->dn_kind != DT_NODE_INT) {
432 		xyerror(D_PROTO_ARG, "%s[ ] argument #1 is incompatible with "
433 		    "prototype:\n\tprototype: %s\n\t argument: %s\n",
434 		    idp->di_name, "integer constant",
435 		    dt_type_name(ap->dn_ctfp, ap->dn_type, n, sizeof (n)));
436 	}
437 
438 	if ((ap->dn_flags & DT_NF_SIGNED) && (int64_t)ap->dn_value < 0) {
439 		xyerror(D_REGS_IDX, "index %lld is out of range for array %s\n",
440 		    (longlong_t)ap->dn_value, idp->di_name);
441 	}
442 
443 	if (dt_type_lookup("uint64_t", &dtt) == -1) {
444 		xyerror(D_UNKNOWN, "failed to resolve type of %s: %s\n",
445 		    idp->di_name, dtrace_errmsg(dtp, dtrace_errno(dtp)));
446 	}
447 
448 	idp->di_ctfp = dtt.dtt_ctfp;
449 	idp->di_type = dtt.dtt_type;
450 
451 	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
452 }
453 
454 /*ARGSUSED*/
455 static void
456 dt_idcook_type(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
457 {
458 	if (idp->di_type == CTF_ERR) {
459 		dtrace_hdl_t *dtp = yypcb->pcb_hdl;
460 		dtrace_typeinfo_t dtt;
461 
462 		if (dt_type_lookup(idp->di_iarg, &dtt) == -1) {
463 			xyerror(D_UNKNOWN,
464 			    "failed to resolve type %s for identifier %s: %s\n",
465 			    (const char *)idp->di_iarg, idp->di_name,
466 			    dtrace_errmsg(dtp, dtrace_errno(dtp)));
467 		}
468 
469 		idp->di_ctfp = dtt.dtt_ctfp;
470 		idp->di_type = dtt.dtt_type;
471 	}
472 
473 	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
474 }
475 
476 /*ARGSUSED*/
477 static void
478 dt_idcook_thaw(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
479 {
480 	if (idp->di_ctfp != NULL && idp->di_type != CTF_ERR)
481 		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
482 }
483 
484 static void
485 dt_idcook_inline(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
486 {
487 	if (idp->di_kind == DT_IDENT_ARRAY)
488 		dt_idcook_assc(dnp, idp, argc, args);
489 	else
490 		dt_idcook_thaw(dnp, idp, argc, args);
491 }
492 
493 static void
494 dt_iddtor_sign(dt_ident_t *idp)
495 {
496 	if (idp->di_data != NULL)
497 		free(((dt_idsig_t *)idp->di_data)->dis_args);
498 	free(idp->di_data);
499 }
500 
501 static void
502 dt_iddtor_free(dt_ident_t *idp)
503 {
504 	free(idp->di_data);
505 }
506 
507 static void
508 dt_iddtor_inline(dt_ident_t *idp)
509 {
510 	dt_idnode_t *inp = idp->di_iarg;
511 
512 	if (inp != NULL) {
513 		dt_node_link_free(&inp->din_list);
514 
515 		if (inp->din_hash != NULL)
516 			dt_idhash_destroy(inp->din_hash);
517 
518 		free(inp->din_argv);
519 		free(inp);
520 	}
521 
522 	if (idp->di_kind == DT_IDENT_ARRAY)
523 		dt_iddtor_sign(idp);
524 	else
525 		dt_iddtor_free(idp);
526 }
527 
528 /*ARGSUSED*/
529 static void
530 dt_iddtor_none(dt_ident_t *idp)
531 {
532 	/* do nothing */
533 }
534 
535 static void
536 dt_iddtor_probe(dt_ident_t *idp)
537 {
538 	if (idp->di_data != NULL)
539 		dt_probe_destroy(idp->di_data);
540 }
541 
542 static size_t
543 dt_idsize_type(dt_ident_t *idp)
544 {
545 	return (ctf_type_size(idp->di_ctfp, idp->di_type));
546 }
547 
548 /*ARGSUSED*/
549 static size_t
550 dt_idsize_none(dt_ident_t *idp)
551 {
552 	return (0);
553 }
554 
555 const dt_idops_t dt_idops_assc = {
556 	dt_idcook_assc,
557 	dt_iddtor_sign,
558 	dt_idsize_none,
559 };
560 
561 const dt_idops_t dt_idops_func = {
562 	dt_idcook_func,
563 	dt_iddtor_sign,
564 	dt_idsize_none,
565 };
566 
567 const dt_idops_t dt_idops_args = {
568 	dt_idcook_args,
569 	dt_iddtor_none,
570 	dt_idsize_none,
571 };
572 
573 const dt_idops_t dt_idops_regs = {
574 	dt_idcook_regs,
575 	dt_iddtor_free,
576 	dt_idsize_none,
577 };
578 
579 const dt_idops_t dt_idops_type = {
580 	dt_idcook_type,
581 	dt_iddtor_free,
582 	dt_idsize_type,
583 };
584 
585 const dt_idops_t dt_idops_thaw = {
586 	dt_idcook_thaw,
587 	dt_iddtor_free,
588 	dt_idsize_type,
589 };
590 
591 const dt_idops_t dt_idops_inline = {
592 	dt_idcook_inline,
593 	dt_iddtor_inline,
594 	dt_idsize_type,
595 };
596 
597 const dt_idops_t dt_idops_probe = {
598 	dt_idcook_thaw,
599 	dt_iddtor_probe,
600 	dt_idsize_none,
601 };
602 
603 static void
604 dt_idhash_populate(dt_idhash_t *dhp)
605 {
606 	const dt_ident_t *idp = dhp->dh_tmpl;
607 
608 	dhp->dh_tmpl = NULL; /* clear dh_tmpl first to avoid recursion */
609 	dt_dprintf("populating %s idhash from %p\n", dhp->dh_name, (void *)idp);
610 
611 	for (; idp->di_name != NULL; idp++) {
612 		if (dt_idhash_insert(dhp, idp->di_name,
613 		    idp->di_kind, idp->di_flags, idp->di_id, idp->di_attr,
614 		    idp->di_vers, idp->di_ops ? idp->di_ops : &dt_idops_thaw,
615 		    idp->di_iarg, 0) == NULL)
616 			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
617 	}
618 }
619 
620 dt_idhash_t *
621 dt_idhash_create(const char *name, const dt_ident_t *tmpl,
622     uint_t min, uint_t max)
623 {
624 	dt_idhash_t *dhp;
625 	size_t size;
626 
627 	assert(min <= max);
628 
629 	size = sizeof (dt_idhash_t) +
630 	    sizeof (dt_ident_t *) * (_dtrace_strbuckets - 1);
631 
632 	if ((dhp = malloc(size)) == NULL)
633 		return (NULL);
634 
635 	bzero(dhp, size);
636 	dhp->dh_name = name;
637 	dhp->dh_tmpl = tmpl;
638 	dhp->dh_nextid = min;
639 	dhp->dh_minid = min;
640 	dhp->dh_maxid = max;
641 	dhp->dh_hashsz = _dtrace_strbuckets;
642 
643 	return (dhp);
644 }
645 
646 /*
647  * Destroy an entire identifier hash.  This must be done using two passes with
648  * an inlined version of dt_ident_destroy() to avoid referencing freed memory.
649  * In the first pass di_dtor() is called for all identifiers; then the second
650  * pass frees the actual dt_ident_t's.  These must be done separately because
651  * a di_dtor() may operate on data structures which contain references to other
652  * identifiers inside of this hash itself (e.g. a global inline definition
653  * which contains a parse tree that refers to another global variable).
654  */
655 void
656 dt_idhash_destroy(dt_idhash_t *dhp)
657 {
658 	dt_ident_t *idp, *next;
659 	ulong_t i;
660 
661 	for (i = 0; i < dhp->dh_hashsz; i++) {
662 		for (idp = dhp->dh_hash[i]; idp != NULL; idp = next) {
663 			next = idp->di_next;
664 			idp->di_ops->di_dtor(idp);
665 		}
666 	}
667 
668 	for (i = 0; i < dhp->dh_hashsz; i++) {
669 		for (idp = dhp->dh_hash[i]; idp != NULL; idp = next) {
670 			next = idp->di_next;
671 			free(idp->di_name);
672 			free(idp);
673 		}
674 	}
675 
676 	free(dhp);
677 }
678 
679 void
680 dt_idhash_update(dt_idhash_t *dhp)
681 {
682 	uint_t nextid = dhp->dh_minid;
683 	dt_ident_t *idp;
684 	ulong_t i;
685 
686 	for (i = 0; i < dhp->dh_hashsz; i++) {
687 		for (idp = dhp->dh_hash[i]; idp != NULL; idp = idp->di_next) {
688 			if (idp->di_kind == DT_IDENT_ARRAY ||
689 			    idp->di_kind == DT_IDENT_SCALAR)
690 				nextid = MAX(nextid, idp->di_id + 1);
691 		}
692 	}
693 
694 	dhp->dh_nextid = nextid;
695 }
696 
697 dt_ident_t *
698 dt_idhash_lookup(dt_idhash_t *dhp, const char *name)
699 {
700 	size_t len;
701 	ulong_t h = dt_strtab_hash(name, &len) % dhp->dh_hashsz;
702 	dt_ident_t *idp;
703 
704 	if (dhp->dh_tmpl != NULL)
705 		dt_idhash_populate(dhp); /* fill hash w/ initial population */
706 
707 	for (idp = dhp->dh_hash[h]; idp != NULL; idp = idp->di_next) {
708 		if (strcmp(idp->di_name, name) == 0)
709 			return (idp);
710 	}
711 
712 	return (NULL);
713 }
714 
715 int
716 dt_idhash_nextid(dt_idhash_t *dhp, uint_t *p)
717 {
718 	if (dhp->dh_nextid >= dhp->dh_maxid)
719 		return (-1); /* no more id's are free to allocate */
720 
721 	*p = dhp->dh_nextid++;
722 	return (0);
723 }
724 
725 ulong_t
726 dt_idhash_size(const dt_idhash_t *dhp)
727 {
728 	return (dhp->dh_nelems);
729 }
730 
731 const char *
732 dt_idhash_name(const dt_idhash_t *dhp)
733 {
734 	return (dhp->dh_name);
735 }
736 
737 dt_ident_t *
738 dt_idhash_insert(dt_idhash_t *dhp, const char *name, ushort_t kind,
739     ushort_t flags, uint_t id, dtrace_attribute_t attr, uint_t vers,
740     const dt_idops_t *ops, void *iarg, ulong_t gen)
741 {
742 	dt_ident_t *idp;
743 	ulong_t h;
744 
745 	if (dhp->dh_tmpl != NULL)
746 		dt_idhash_populate(dhp); /* fill hash w/ initial population */
747 
748 	idp = dt_ident_create(name, kind, flags, id,
749 	    attr, vers, ops, iarg, gen);
750 
751 	if (idp == NULL)
752 		return (NULL);
753 
754 	h = dt_strtab_hash(name, NULL) % dhp->dh_hashsz;
755 	idp->di_next = dhp->dh_hash[h];
756 
757 	dhp->dh_hash[h] = idp;
758 	dhp->dh_nelems++;
759 
760 	if (dhp->dh_defer != NULL)
761 		dhp->dh_defer(dhp, idp);
762 
763 	return (idp);
764 }
765 
766 void
767 dt_idhash_xinsert(dt_idhash_t *dhp, dt_ident_t *idp)
768 {
769 	ulong_t h;
770 
771 	if (dhp->dh_tmpl != NULL)
772 		dt_idhash_populate(dhp); /* fill hash w/ initial population */
773 
774 	h = dt_strtab_hash(idp->di_name, NULL) % dhp->dh_hashsz;
775 	idp->di_next = dhp->dh_hash[h];
776 	idp->di_flags &= ~DT_IDFLG_ORPHAN;
777 
778 	dhp->dh_hash[h] = idp;
779 	dhp->dh_nelems++;
780 
781 	if (dhp->dh_defer != NULL)
782 		dhp->dh_defer(dhp, idp);
783 }
784 
785 void
786 dt_idhash_delete(dt_idhash_t *dhp, dt_ident_t *key)
787 {
788 	size_t len;
789 	ulong_t h = dt_strtab_hash(key->di_name, &len) % dhp->dh_hashsz;
790 	dt_ident_t **pp = &dhp->dh_hash[h];
791 	dt_ident_t *idp;
792 
793 	for (idp = dhp->dh_hash[h]; idp != NULL; idp = idp->di_next) {
794 		if (idp == key)
795 			break;
796 		else
797 			pp = &idp->di_next;
798 	}
799 
800 	assert(idp == key);
801 	*pp = idp->di_next;
802 
803 	assert(dhp->dh_nelems != 0);
804 	dhp->dh_nelems--;
805 
806 	dt_ident_destroy(idp);
807 }
808 
809 static int
810 dt_idhash_comp(const void *lp, const void *rp)
811 {
812 	const dt_ident_t *lhs = *((const dt_ident_t **)lp);
813 	const dt_ident_t *rhs = *((const dt_ident_t **)rp);
814 
815 	if (lhs->di_id != rhs->di_id)
816 		return ((int)(lhs->di_id - rhs->di_id));
817 	else
818 		return (strcmp(lhs->di_name, rhs->di_name));
819 }
820 
821 int
822 dt_idhash_iter(dt_idhash_t *dhp, dt_idhash_f *func, void *data)
823 {
824 	dt_ident_t **ids;
825 	dt_ident_t *idp;
826 	ulong_t i, j;
827 	int rv;
828 
829 	if (dhp->dh_tmpl != NULL)
830 		dt_idhash_populate(dhp); /* fill hash w/ initial population */
831 
832 	ids = alloca(sizeof (dt_ident_t *) * dhp->dh_nelems);
833 
834 	for (i = 0, j = 0; i < dhp->dh_hashsz; i++) {
835 		for (idp = dhp->dh_hash[i]; idp != NULL; idp = idp->di_next)
836 			ids[j++] = idp;
837 	}
838 
839 	qsort(ids, dhp->dh_nelems, sizeof (dt_ident_t *), dt_idhash_comp);
840 
841 	for (i = 0; i < dhp->dh_nelems; i++) {
842 		if ((rv = func(dhp, ids[i], data)) != 0)
843 			return (rv);
844 	}
845 
846 	return (0);
847 }
848 
849 dt_ident_t *
850 dt_idstack_lookup(dt_idstack_t *sp, const char *name)
851 {
852 	dt_idhash_t *dhp;
853 	dt_ident_t *idp;
854 
855 	for (dhp = dt_list_prev(&sp->dids_list);
856 	    dhp != NULL; dhp = dt_list_prev(dhp)) {
857 		if ((idp = dt_idhash_lookup(dhp, name)) != NULL)
858 			return (idp);
859 	}
860 
861 	return (NULL);
862 }
863 
864 void
865 dt_idstack_push(dt_idstack_t *sp, dt_idhash_t *dhp)
866 {
867 	dt_list_append(&sp->dids_list, dhp);
868 }
869 
870 void
871 dt_idstack_pop(dt_idstack_t *sp, dt_idhash_t *dhp)
872 {
873 	assert(dt_list_prev(&sp->dids_list) == dhp);
874 	dt_list_delete(&sp->dids_list, dhp);
875 }
876 
877 dt_ident_t *
878 dt_ident_create(const char *name, ushort_t kind, ushort_t flags, uint_t id,
879     dtrace_attribute_t attr, uint_t vers,
880     const dt_idops_t *ops, void *iarg, ulong_t gen)
881 {
882 	dt_ident_t *idp;
883 	char *s = NULL;
884 
885 	if ((name != NULL && (s = strdup(name)) == NULL) ||
886 	    (idp = malloc(sizeof (dt_ident_t))) == NULL) {
887 		free(s);
888 		return (NULL);
889 	}
890 
891 	idp->di_name = s;
892 	idp->di_kind = kind;
893 	idp->di_flags = flags;
894 	idp->di_id = id;
895 	idp->di_attr = attr;
896 	idp->di_vers = vers;
897 	idp->di_ops = ops;
898 	idp->di_iarg = iarg;
899 	idp->di_data = NULL;
900 	idp->di_ctfp = NULL;
901 	idp->di_type = CTF_ERR;
902 	idp->di_next = NULL;
903 	idp->di_gen = gen;
904 	idp->di_lineno = yylineno;
905 
906 	return (idp);
907 }
908 
909 /*
910  * Destroy an individual identifier.  This code must be kept in sync with the
911  * dt_idhash_destroy() function below, which separates out the call to di_dtor.
912  */
913 void
914 dt_ident_destroy(dt_ident_t *idp)
915 {
916 	idp->di_ops->di_dtor(idp);
917 	free(idp->di_name);
918 	free(idp);
919 }
920 
921 void
922 dt_ident_morph(dt_ident_t *idp, ushort_t kind,
923     const dt_idops_t *ops, void *iarg)
924 {
925 	idp->di_ops->di_dtor(idp);
926 	idp->di_kind = kind;
927 	idp->di_ops = ops;
928 	idp->di_iarg = iarg;
929 	idp->di_data = NULL;
930 }
931 
932 dtrace_attribute_t
933 dt_ident_cook(dt_node_t *dnp, dt_ident_t *idp, dt_node_t **pargp)
934 {
935 	dtrace_attribute_t attr;
936 	dt_node_t *args, *argp;
937 	int argc = 0;
938 
939 	attr = dt_node_list_cook(pargp, DT_IDFLG_REF);
940 	args = pargp ? *pargp : NULL;
941 
942 	for (argp = args; argp != NULL; argp = argp->dn_list)
943 		argc++;
944 
945 	idp->di_ops->di_cook(dnp, idp, argc, args);
946 
947 	if (idp->di_flags & DT_IDFLG_USER)
948 		dnp->dn_flags |= DT_NF_USERLAND;
949 
950 	return (dt_attr_min(attr, idp->di_attr));
951 }
952 
953 void
954 dt_ident_type_assign(dt_ident_t *idp, ctf_file_t *fp, ctf_id_t type)
955 {
956 	idp->di_ctfp = fp;
957 	idp->di_type = type;
958 }
959 
960 dt_ident_t *
961 dt_ident_resolve(dt_ident_t *idp)
962 {
963 	while (idp->di_flags & DT_IDFLG_INLINE) {
964 		const dt_node_t *dnp = ((dt_idnode_t *)idp->di_iarg)->din_root;
965 
966 		switch (dnp->dn_kind) {
967 		case DT_NODE_VAR:
968 		case DT_NODE_SYM:
969 		case DT_NODE_FUNC:
970 		case DT_NODE_AGG:
971 		case DT_NODE_INLINE:
972 		case DT_NODE_PROBE:
973 			idp = dnp->dn_ident;
974 			continue;
975 		}
976 
977 		if (dt_node_is_dynamic(dnp))
978 			idp = dnp->dn_ident;
979 		else
980 			break;
981 	}
982 
983 	return (idp);
984 }
985 
986 size_t
987 dt_ident_size(dt_ident_t *idp)
988 {
989 	idp = dt_ident_resolve(idp);
990 	return (idp->di_ops->di_size(idp));
991 }
992 
993 int
994 dt_ident_unref(const dt_ident_t *idp)
995 {
996 	return (idp->di_gen == yypcb->pcb_hdl->dt_gen &&
997 	    (idp->di_flags & (DT_IDFLG_REF|DT_IDFLG_MOD|DT_IDFLG_DECL)) == 0);
998 }
999 
1000 const char *
1001 dt_idkind_name(uint_t kind)
1002 {
1003 	switch (kind) {
1004 	case DT_IDENT_ARRAY:	return ("associative array");
1005 	case DT_IDENT_SCALAR:	return ("scalar");
1006 	case DT_IDENT_PTR:	return ("pointer");
1007 	case DT_IDENT_FUNC:	return ("function");
1008 	case DT_IDENT_AGG:	return ("aggregation");
1009 	case DT_IDENT_AGGFUNC:	return ("aggregating function");
1010 	case DT_IDENT_ACTFUNC:	return ("tracing function");
1011 	case DT_IDENT_XLSOU:	return ("translated data");
1012 	case DT_IDENT_XLPTR:	return ("pointer to translated data");
1013 	case DT_IDENT_SYMBOL:	return ("external symbol reference");
1014 	case DT_IDENT_ENUM:	return ("enumerator");
1015 	case DT_IDENT_PRAGAT:	return ("#pragma attributes");
1016 	case DT_IDENT_PRAGBN:	return ("#pragma binding");
1017 	case DT_IDENT_PROBE:	return ("probe definition");
1018 	default:		return ("<?>");
1019 	}
1020 }
1021