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