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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
25  * Copyright (c) 2013, Joyent Inc. All rights reserved.
26  * Copyright 2015 Gary Mills
27  */
28 
29 /*
30  * DTrace D Language Compiler
31  *
32  * The code in this source file implements the main engine for the D language
33  * compiler.  The driver routine for the compiler is dt_compile(), below.  The
34  * compiler operates on either stdio FILEs or in-memory strings as its input
35  * and can produce either dtrace_prog_t structures from a D program or a single
36  * dtrace_difo_t structure from a D expression.  Multiple entry points are
37  * provided as wrappers around dt_compile() for the various input/output pairs.
38  * The compiler itself is implemented across the following source files:
39  *
40  * dt_lex.l - lex scanner
41  * dt_grammar.y - yacc grammar
42  * dt_parser.c - parse tree creation and semantic checking
43  * dt_decl.c - declaration stack processing
44  * dt_xlator.c - D translator lookup and creation
45  * dt_ident.c - identifier and symbol table routines
46  * dt_pragma.c - #pragma processing and D pragmas
47  * dt_printf.c - D printf() and printa() argument checking and processing
48  * dt_cc.c - compiler driver and dtrace_prog_t construction
49  * dt_cg.c - DIF code generator
50  * dt_as.c - DIF assembler
51  * dt_dof.c - dtrace_prog_t -> DOF conversion
52  *
53  * Several other source files provide collections of utility routines used by
54  * these major files.  The compiler itself is implemented in multiple passes:
55  *
56  * (1) The input program is scanned and parsed by dt_lex.l and dt_grammar.y
57  *     and parse tree nodes are constructed using the routines in dt_parser.c.
58  *     This node construction pass is described further in dt_parser.c.
59  *
60  * (2) The parse tree is "cooked" by assigning each clause a context (see the
61  *     routine dt_setcontext(), below) based on its probe description and then
62  *     recursively descending the tree performing semantic checking.  The cook
63  *     routines are also implemented in dt_parser.c and described there.
64  *
65  * (3) For actions that are DIF expression statements, the DIF code generator
66  *     and assembler are invoked to create a finished DIFO for the statement.
67  *
68  * (4) The dtrace_prog_t data structures for the program clauses and actions
69  *     are built, containing pointers to any DIFOs created in step (3).
70  *
71  * (5) The caller invokes a routine in dt_dof.c to convert the finished program
72  *     into DOF format for use in anonymous tracing or enabling in the kernel.
73  *
74  * In the implementation, steps 2-4 are intertwined in that they are performed
75  * in order for each clause as part of a loop that executes over the clauses.
76  *
77  * The D compiler currently implements nearly no optimization.  The compiler
78  * implements integer constant folding as part of pass (1), and a set of very
79  * simple peephole optimizations as part of pass (3).  As with any C compiler,
80  * a large number of optimizations are possible on both the intermediate data
81  * structures and the generated DIF code.  These possibilities should be
82  * investigated in the context of whether they will have any substantive effect
83  * on the overall DTrace probe effect before they are undertaken.
84  */
85 
86 #include <sys/types.h>
87 #include <sys/wait.h>
88 #include <sys/sysmacros.h>
89 
90 #include <assert.h>
91 #include <string.h>
92 #include <strings.h>
93 #include <signal.h>
94 #include <unistd.h>
95 #include <stdlib.h>
96 #include <stdio.h>
97 #include <errno.h>
98 #include <ucontext.h>
99 #include <limits.h>
100 #include <ctype.h>
101 #include <dirent.h>
102 #include <dt_module.h>
103 #include <dt_program.h>
104 #include <dt_provider.h>
105 #include <dt_printf.h>
106 #include <dt_pid.h>
107 #include <dt_grammar.h>
108 #include <dt_ident.h>
109 #include <dt_string.h>
110 #include <dt_impl.h>
111 
112 static const dtrace_diftype_t dt_void_rtype = {
113           DIF_TYPE_CTF, CTF_K_INTEGER, 0, 0, 0
114 };
115 
116 static const dtrace_diftype_t dt_int_rtype = {
117           DIF_TYPE_CTF, CTF_K_INTEGER, 0, 0, sizeof (uint64_t)
118 };
119 
120 static void *dt_compile(dtrace_hdl_t *, int, dtrace_probespec_t, void *,
121     uint_t, int, char *const[], FILE *, const char *);
122 
123 /*ARGSUSED*/
124 static int
dt_idreset(dt_idhash_t * dhp,dt_ident_t * idp,void * ignored)125 dt_idreset(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored)
126 {
127           idp->di_flags &= ~(DT_IDFLG_REF | DT_IDFLG_MOD |
128               DT_IDFLG_DIFR | DT_IDFLG_DIFW);
129           return (0);
130 }
131 
132 /*ARGSUSED*/
133 static int
dt_idpragma(dt_idhash_t * dhp,dt_ident_t * idp,void * ignored)134 dt_idpragma(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored)
135 {
136           yylineno = idp->di_lineno;
137           xyerror(D_PRAGMA_UNUSED, "unused #pragma %s\n", (char *)idp->di_iarg);
138           return (0);
139 }
140 
141 static dtrace_stmtdesc_t *
dt_stmt_create(dtrace_hdl_t * dtp,dtrace_ecbdesc_t * edp,dtrace_attribute_t descattr,dtrace_attribute_t stmtattr)142 dt_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp,
143     dtrace_attribute_t descattr, dtrace_attribute_t stmtattr)
144 {
145           dtrace_stmtdesc_t *sdp = dtrace_stmt_create(dtp, edp);
146 
147           if (sdp == NULL)
148                     longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
149 
150           assert(yypcb->pcb_stmt == NULL);
151           yypcb->pcb_stmt = sdp;
152 
153           sdp->dtsd_descattr = descattr;
154           sdp->dtsd_stmtattr = stmtattr;
155 
156           return (sdp);
157 }
158 
159 static dtrace_actdesc_t *
dt_stmt_action(dtrace_hdl_t * dtp,dtrace_stmtdesc_t * sdp)160 dt_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
161 {
162           dtrace_actdesc_t *new;
163 
164           if ((new = dtrace_stmt_action(dtp, sdp)) == NULL)
165                     longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
166 
167           return (new);
168 }
169 
170 /*
171  * Utility function to determine if a given action description is destructive.
172  * The dtdo_destructive bit is set for us by the DIF assembler (see dt_as.c).
173  */
174 static int
dt_action_destructive(const dtrace_actdesc_t * ap)175 dt_action_destructive(const dtrace_actdesc_t *ap)
176 {
177           return (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind) || (ap->dtad_kind ==
178               DTRACEACT_DIFEXPR && ap->dtad_difo->dtdo_destructive));
179 }
180 
181 static void
dt_stmt_append(dtrace_stmtdesc_t * sdp,const dt_node_t * dnp)182 dt_stmt_append(dtrace_stmtdesc_t *sdp, const dt_node_t *dnp)
183 {
184           dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc;
185           dtrace_actdesc_t *ap, *tap;
186           int commit = 0;
187           int speculate = 0;
188           int datarec = 0;
189 
190           /*
191            * Make sure that the new statement jibes with the rest of the ECB.
192            */
193           for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) {
194                     if (ap->dtad_kind == DTRACEACT_COMMIT) {
195                               if (commit) {
196                                         dnerror(dnp, D_COMM_COMM, "commit( ) may "
197                                             "not follow commit( )\n");
198                               }
199 
200                               if (datarec) {
201                                         dnerror(dnp, D_COMM_DREC, "commit( ) may "
202                                             "not follow data-recording action(s)\n");
203                               }
204 
205                               for (tap = ap; tap != NULL; tap = tap->dtad_next) {
206                                         if (!DTRACEACT_ISAGG(tap->dtad_kind))
207                                                   continue;
208 
209                                         dnerror(dnp, D_AGG_COMM, "aggregating actions "
210                                             "may not follow commit( )\n");
211                               }
212 
213                               commit = 1;
214                               continue;
215                     }
216 
217                     if (ap->dtad_kind == DTRACEACT_SPECULATE) {
218                               if (speculate) {
219                                         dnerror(dnp, D_SPEC_SPEC, "speculate( ) may "
220                                             "not follow speculate( )\n");
221                               }
222 
223                               if (commit) {
224                                         dnerror(dnp, D_SPEC_COMM, "speculate( ) may "
225                                             "not follow commit( )\n");
226                               }
227 
228                               if (datarec) {
229                                         dnerror(dnp, D_SPEC_DREC, "speculate( ) may "
230                                             "not follow data-recording action(s)\n");
231                               }
232 
233                               speculate = 1;
234                               continue;
235                     }
236 
237                     if (DTRACEACT_ISAGG(ap->dtad_kind)) {
238                               if (speculate) {
239                                         dnerror(dnp, D_AGG_SPEC, "aggregating actions "
240                                             "may not follow speculate( )\n");
241                               }
242 
243                               datarec = 1;
244                               continue;
245                     }
246 
247                     if (speculate) {
248                               if (dt_action_destructive(ap)) {
249                                         dnerror(dnp, D_ACT_SPEC, "destructive actions "
250                                             "may not follow speculate( )\n");
251                               }
252 
253                               if (ap->dtad_kind == DTRACEACT_EXIT) {
254                                         dnerror(dnp, D_EXIT_SPEC, "exit( ) may not "
255                                             "follow speculate( )\n");
256                               }
257                     }
258 
259                     /*
260                      * Exclude all non data-recording actions.
261                      */
262                     if (dt_action_destructive(ap) ||
263                         ap->dtad_kind == DTRACEACT_DISCARD)
264                               continue;
265 
266                     if (ap->dtad_kind == DTRACEACT_DIFEXPR &&
267                         ap->dtad_difo->dtdo_rtype.dtdt_kind == DIF_TYPE_CTF &&
268                         ap->dtad_difo->dtdo_rtype.dtdt_size == 0)
269                               continue;
270 
271                     if (commit) {
272                               dnerror(dnp, D_DREC_COMM, "data-recording actions "
273                                   "may not follow commit( )\n");
274                     }
275 
276                     if (!speculate)
277                               datarec = 1;
278           }
279 
280           if (dtrace_stmt_add(yypcb->pcb_hdl, yypcb->pcb_prog, sdp) != 0)
281                     longjmp(yypcb->pcb_jmpbuf, dtrace_errno(yypcb->pcb_hdl));
282 
283           if (yypcb->pcb_stmt == sdp)
284                     yypcb->pcb_stmt = NULL;
285 }
286 
287 /*
288  * For the first element of an aggregation tuple or for printa(), we create a
289  * simple DIF program that simply returns the immediate value that is the ID
290  * of the aggregation itself.  This could be optimized in the future by
291  * creating a new in-kernel dtad_kind that just returns an integer.
292  */
293 static void
dt_action_difconst(dtrace_actdesc_t * ap,uint_t id,dtrace_actkind_t kind)294 dt_action_difconst(dtrace_actdesc_t *ap, uint_t id, dtrace_actkind_t kind)
295 {
296           dtrace_hdl_t *dtp = yypcb->pcb_hdl;
297           dtrace_difo_t *dp = dt_zalloc(dtp, sizeof (dtrace_difo_t));
298 
299           if (dp == NULL)
300                     longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
301 
302           dp->dtdo_buf = dt_alloc(dtp, sizeof (dif_instr_t) * 2);
303           dp->dtdo_inttab = dt_alloc(dtp, sizeof (uint64_t));
304 
305           if (dp->dtdo_buf == NULL || dp->dtdo_inttab == NULL) {
306                     dt_difo_free(dtp, dp);
307                     longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
308           }
309 
310           dp->dtdo_buf[0] = DIF_INSTR_SETX(0, 1); /* setx   DIF_INTEGER[0], %r1 */
311           dp->dtdo_buf[1] = DIF_INSTR_RET(1);     /* ret    %r1 */
312           dp->dtdo_len = 2;
313           dp->dtdo_inttab[0] = id;
314           dp->dtdo_intlen = 1;
315           dp->dtdo_rtype = dt_int_rtype;
316 
317           ap->dtad_difo = dp;
318           ap->dtad_kind = kind;
319 }
320 
321 static void
dt_action_clear(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)322 dt_action_clear(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
323 {
324           dt_ident_t *aid;
325           dtrace_actdesc_t *ap;
326           dt_node_t *anp;
327 
328           char n[DT_TYPE_NAMELEN];
329           int argc = 0;
330 
331           for (anp = dnp->dn_args; anp != NULL; anp = anp->dn_list)
332                     argc++; /* count up arguments for error messages below */
333 
334           if (argc != 1) {
335                     dnerror(dnp, D_CLEAR_PROTO,
336                         "%s( ) prototype mismatch: %d args passed, 1 expected\n",
337                         dnp->dn_ident->di_name, argc);
338           }
339 
340           anp = dnp->dn_args;
341           assert(anp != NULL);
342 
343           if (anp->dn_kind != DT_NODE_AGG) {
344                     dnerror(dnp, D_CLEAR_AGGARG,
345                         "%s( ) argument #1 is incompatible with prototype:\n"
346                         "\tprototype: aggregation\n\t argument: %s\n",
347                         dnp->dn_ident->di_name,
348                         dt_node_type_name(anp, n, sizeof (n)));
349           }
350 
351           aid = anp->dn_ident;
352 
353           if (aid->di_gen == dtp->dt_gen && !(aid->di_flags & DT_IDFLG_MOD)) {
354                     dnerror(dnp, D_CLEAR_AGGBAD,
355                         "undefined aggregation: @%s\n", aid->di_name);
356           }
357 
358           ap = dt_stmt_action(dtp, sdp);
359           dt_action_difconst(ap, anp->dn_ident->di_id, DTRACEACT_LIBACT);
360           ap->dtad_arg = DT_ACT_CLEAR;
361 }
362 
363 static void
dt_action_normalize(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)364 dt_action_normalize(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
365 {
366           dt_ident_t *aid;
367           dtrace_actdesc_t *ap;
368           dt_node_t *anp, *normal;
369           int denormal = (strcmp(dnp->dn_ident->di_name, "denormalize") == 0);
370 
371           char n[DT_TYPE_NAMELEN];
372           int argc = 0;
373 
374           for (anp = dnp->dn_args; anp != NULL; anp = anp->dn_list)
375                     argc++; /* count up arguments for error messages below */
376 
377           if ((denormal && argc != 1) || (!denormal && argc != 2)) {
378                     dnerror(dnp, D_NORMALIZE_PROTO,
379                         "%s( ) prototype mismatch: %d args passed, %d expected\n",
380                         dnp->dn_ident->di_name, argc, denormal ? 1 : 2);
381           }
382 
383           anp = dnp->dn_args;
384           assert(anp != NULL);
385 
386           if (anp->dn_kind != DT_NODE_AGG) {
387                     dnerror(dnp, D_NORMALIZE_AGGARG,
388                         "%s( ) argument #1 is incompatible with prototype:\n"
389                         "\tprototype: aggregation\n\t argument: %s\n",
390                         dnp->dn_ident->di_name,
391                         dt_node_type_name(anp, n, sizeof (n)));
392           }
393 
394           if ((normal = anp->dn_list) != NULL && !dt_node_is_scalar(normal)) {
395                     dnerror(dnp, D_NORMALIZE_SCALAR,
396                         "%s( ) argument #2 must be of scalar type\n",
397                         dnp->dn_ident->di_name);
398           }
399 
400           aid = anp->dn_ident;
401 
402           if (aid->di_gen == dtp->dt_gen && !(aid->di_flags & DT_IDFLG_MOD)) {
403                     dnerror(dnp, D_NORMALIZE_AGGBAD,
404                         "undefined aggregation: @%s\n", aid->di_name);
405           }
406 
407           ap = dt_stmt_action(dtp, sdp);
408           dt_action_difconst(ap, anp->dn_ident->di_id, DTRACEACT_LIBACT);
409 
410           if (denormal) {
411                     ap->dtad_arg = DT_ACT_DENORMALIZE;
412                     return;
413           }
414 
415           ap->dtad_arg = DT_ACT_NORMALIZE;
416 
417           assert(normal != NULL);
418           ap = dt_stmt_action(dtp, sdp);
419           dt_cg(yypcb, normal);
420 
421           ap->dtad_difo = dt_as(yypcb);
422           ap->dtad_kind = DTRACEACT_LIBACT;
423           ap->dtad_arg = DT_ACT_NORMALIZE;
424 }
425 
426 static void
dt_action_trunc(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)427 dt_action_trunc(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
428 {
429           dt_ident_t *aid;
430           dtrace_actdesc_t *ap;
431           dt_node_t *anp, *trunc;
432 
433           char n[DT_TYPE_NAMELEN];
434           int argc = 0;
435 
436           for (anp = dnp->dn_args; anp != NULL; anp = anp->dn_list)
437                     argc++; /* count up arguments for error messages below */
438 
439           if (argc > 2 || argc < 1) {
440                     dnerror(dnp, D_TRUNC_PROTO,
441                         "%s( ) prototype mismatch: %d args passed, %s expected\n",
442                         dnp->dn_ident->di_name, argc,
443                         argc < 1 ? "at least 1" : "no more than 2");
444           }
445 
446           anp = dnp->dn_args;
447           assert(anp != NULL);
448           trunc = anp->dn_list;
449 
450           if (anp->dn_kind != DT_NODE_AGG) {
451                     dnerror(dnp, D_TRUNC_AGGARG,
452                         "%s( ) argument #1 is incompatible with prototype:\n"
453                         "\tprototype: aggregation\n\t argument: %s\n",
454                         dnp->dn_ident->di_name,
455                         dt_node_type_name(anp, n, sizeof (n)));
456           }
457 
458           if (argc == 2) {
459                     assert(trunc != NULL);
460                     if (!dt_node_is_scalar(trunc)) {
461                               dnerror(dnp, D_TRUNC_SCALAR,
462                                   "%s( ) argument #2 must be of scalar type\n",
463                                   dnp->dn_ident->di_name);
464                     }
465           }
466 
467           aid = anp->dn_ident;
468 
469           if (aid->di_gen == dtp->dt_gen && !(aid->di_flags & DT_IDFLG_MOD)) {
470                     dnerror(dnp, D_TRUNC_AGGBAD,
471                         "undefined aggregation: @%s\n", aid->di_name);
472           }
473 
474           ap = dt_stmt_action(dtp, sdp);
475           dt_action_difconst(ap, anp->dn_ident->di_id, DTRACEACT_LIBACT);
476           ap->dtad_arg = DT_ACT_TRUNC;
477 
478           ap = dt_stmt_action(dtp, sdp);
479 
480           if (argc == 1) {
481                     dt_action_difconst(ap, 0, DTRACEACT_LIBACT);
482           } else {
483                     assert(trunc != NULL);
484                     dt_cg(yypcb, trunc);
485                     ap->dtad_difo = dt_as(yypcb);
486                     ap->dtad_kind = DTRACEACT_LIBACT;
487           }
488 
489           ap->dtad_arg = DT_ACT_TRUNC;
490 }
491 
492 static void
dt_action_printa(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)493 dt_action_printa(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
494 {
495           dt_ident_t *aid, *fid;
496           dtrace_actdesc_t *ap;
497           const char *format;
498           dt_node_t *anp, *proto = NULL;
499 
500           char n[DT_TYPE_NAMELEN];
501           int argc = 0, argr = 0;
502 
503           for (anp = dnp->dn_args; anp != NULL; anp = anp->dn_list)
504                     argc++; /* count up arguments for error messages below */
505 
506           switch (dnp->dn_args->dn_kind) {
507           case DT_NODE_STRING:
508                     format = dnp->dn_args->dn_string;
509                     anp = dnp->dn_args->dn_list;
510                     argr = 2;
511                     break;
512           case DT_NODE_AGG:
513                     format = NULL;
514                     anp = dnp->dn_args;
515                     argr = 1;
516                     break;
517           default:
518                     format = NULL;
519                     anp = dnp->dn_args;
520                     argr = 1;
521           }
522 
523           if (argc < argr) {
524                     dnerror(dnp, D_PRINTA_PROTO,
525                         "%s( ) prototype mismatch: %d args passed, %d expected\n",
526                         dnp->dn_ident->di_name, argc, argr);
527           }
528 
529           assert(anp != NULL);
530 
531           while (anp != NULL) {
532                     if (anp->dn_kind != DT_NODE_AGG) {
533                               dnerror(dnp, D_PRINTA_AGGARG,
534                                   "%s( ) argument #%d is incompatible with "
535                                   "prototype:\n\tprototype: aggregation\n"
536                                   "\t argument: %s\n", dnp->dn_ident->di_name, argr,
537                                   dt_node_type_name(anp, n, sizeof (n)));
538                     }
539 
540                     aid = anp->dn_ident;
541                     fid = aid->di_iarg;
542 
543                     if (aid->di_gen == dtp->dt_gen &&
544                         !(aid->di_flags & DT_IDFLG_MOD)) {
545                               dnerror(dnp, D_PRINTA_AGGBAD,
546                                   "undefined aggregation: @%s\n", aid->di_name);
547                     }
548 
549                     /*
550                      * If we have multiple aggregations, we must be sure that
551                      * their key signatures match.
552                      */
553                     if (proto != NULL) {
554                               dt_printa_validate(proto, anp);
555                     } else {
556                               proto = anp;
557                     }
558 
559                     if (format != NULL) {
560                               yylineno = dnp->dn_line;
561 
562                               sdp->dtsd_fmtdata =
563                                   dt_printf_create(yypcb->pcb_hdl, format);
564                               dt_printf_validate(sdp->dtsd_fmtdata,
565                                   DT_PRINTF_AGGREGATION, dnp->dn_ident, 1,
566                                   fid->di_id, ((dt_idsig_t *)aid->di_data)->dis_args);
567                               format = NULL;
568                     }
569 
570                     ap = dt_stmt_action(dtp, sdp);
571                     dt_action_difconst(ap, anp->dn_ident->di_id, DTRACEACT_PRINTA);
572 
573                     anp = anp->dn_list;
574                     argr++;
575           }
576 }
577 
578 static void
dt_action_printflike(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp,dtrace_actkind_t kind)579 dt_action_printflike(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp,
580     dtrace_actkind_t kind)
581 {
582           dt_node_t *anp, *arg1;
583           dtrace_actdesc_t *ap = NULL;
584           char n[DT_TYPE_NAMELEN], *str;
585 
586           assert(DTRACEACT_ISPRINTFLIKE(kind));
587 
588           if (dnp->dn_args->dn_kind != DT_NODE_STRING) {
589                     dnerror(dnp, D_PRINTF_ARG_FMT,
590                         "%s( ) argument #1 is incompatible with prototype:\n"
591                         "\tprototype: string constant\n\t argument: %s\n",
592                         dnp->dn_ident->di_name,
593                         dt_node_type_name(dnp->dn_args, n, sizeof (n)));
594           }
595 
596           arg1 = dnp->dn_args->dn_list;
597           yylineno = dnp->dn_line;
598           str = dnp->dn_args->dn_string;
599 
600 
601           /*
602            * If this is an freopen(), we use an empty string to denote that
603            * stdout should be restored.  For other printf()-like actions, an
604            * empty format string is illegal:  an empty format string would
605            * result in malformed DOF, and the compiler thus flags an empty
606            * format string as a compile-time error.  To avoid propagating the
607            * freopen() special case throughout the system, we simply transpose
608            * an empty string into a sentinel string (DT_FREOPEN_RESTORE) that
609            * denotes that stdout should be restored.
610            */
611           if (kind == DTRACEACT_FREOPEN) {
612                     if (strcmp(str, DT_FREOPEN_RESTORE) == 0) {
613                               /*
614                                * Our sentinel is always an invalid argument to
615                                * freopen(), but if it's been manually specified, we
616                                * must fail now instead of when the freopen() is
617                                * actually evaluated.
618                                */
619                               dnerror(dnp, D_FREOPEN_INVALID,
620                                   "%s( ) argument #1 cannot be \"%s\"\n",
621                                   dnp->dn_ident->di_name, DT_FREOPEN_RESTORE);
622                     }
623 
624                     if (str[0] == '\0')
625                               str = __UNCONST(DT_FREOPEN_RESTORE);
626           }
627 
628           sdp->dtsd_fmtdata = dt_printf_create(dtp, str);
629 
630           dt_printf_validate(sdp->dtsd_fmtdata, DT_PRINTF_EXACTLEN,
631               dnp->dn_ident, 1, DTRACEACT_AGGREGATION, arg1);
632 
633           if (arg1 == NULL) {
634                     dif_instr_t *dbuf;
635                     dtrace_difo_t *dp;
636 
637                     if ((dbuf = dt_alloc(dtp, sizeof (dif_instr_t))) == NULL ||
638                         (dp = dt_zalloc(dtp, sizeof (dtrace_difo_t))) == NULL) {
639                               dt_free(dtp, dbuf);
640                               longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
641                     }
642 
643                     dbuf[0] = DIF_INSTR_RET(DIF_REG_R0); /* ret %r0 */
644 
645                     dp->dtdo_buf = dbuf;
646                     dp->dtdo_len = 1;
647                     dp->dtdo_rtype = dt_int_rtype;
648 
649                     ap = dt_stmt_action(dtp, sdp);
650                     ap->dtad_difo = dp;
651                     ap->dtad_kind = kind;
652                     return;
653           }
654 
655           for (anp = arg1; anp != NULL; anp = anp->dn_list) {
656                     ap = dt_stmt_action(dtp, sdp);
657                     dt_cg(yypcb, anp);
658                     ap->dtad_difo = dt_as(yypcb);
659                     ap->dtad_kind = kind;
660           }
661 }
662 
663 static void
dt_action_trace(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)664 dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
665 {
666           int ctflib = 0;     // XXX: gcc
667 
668           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
669           boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
670           const char *act = istrace ?  "trace" : "print";
671 
672           if (dt_node_is_void(dnp->dn_args)) {
673                     dnerror(dnp->dn_args, istrace ? D_TRACE_VOID : D_PRINT_VOID,
674                         "%s( ) may not be applied to a void expression\n", act);
675           }
676 
677           if (dt_node_resolve(dnp->dn_args, DT_IDENT_XLPTR) != NULL) {
678                     dnerror(dnp->dn_args, istrace ? D_TRACE_DYN : D_PRINT_DYN,
679                         "%s( ) may not be applied to a translated pointer\n", act);
680           }
681 
682           if (dnp->dn_args->dn_kind == DT_NODE_AGG) {
683                     dnerror(dnp->dn_args, istrace ? D_TRACE_AGG : D_PRINT_AGG,
684                         "%s( ) may not be applied to an aggregation%s\n", act,
685                         istrace ? "" : " -- did you mean printa()?");
686           }
687 
688           dt_cg(yypcb, dnp->dn_args);
689 
690           /*
691            * The print() action behaves identically to trace(), except that it
692            * stores the CTF type of the argument (if present) within the DOF for
693            * the DIFEXPR action.  To do this, we set the 'dtsd_strdata' to point
694            * to the fully-qualified CTF type ID for the result of the DIF
695            * action.  We use the ID instead of the name to handles complex types
696            * like arrays and function pointers that can't be resolved by
697            * ctf_type_lookup().  This is later processed by dtrace_dof_create()
698            * and turned into a reference into the string table so that we can
699            * get the type information when we process the data after the fact.  In
700            * the case where we are referring to userland CTF data, we also need to
701            * to identify which ctf container in question we care about and encode
702            * that within the name.
703            */
704           if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
705                     dt_node_t *dret;
706                     size_t n;
707                     dt_module_t *dmp;
708 
709                     dret = yypcb->pcb_dret;
710                     dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
711 
712                     n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name, dret->dn_type) + 1;
713                     if (dmp->dm_pid != 0) {
714                               ctflib = dt_module_getlibid(dtp, dmp, dret->dn_ctfp);
715                               assert(ctflib >= 0);
716                               n = snprintf(NULL, 0, "%s`%d`%ld", dmp->dm_name,
717                                   ctflib, dret->dn_type) + 1;
718                     } else {
719                               n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name,
720                                   dret->dn_type) + 1;
721                     }
722                     sdp->dtsd_strdata = dt_alloc(dtp, n);
723                     if (sdp->dtsd_strdata == NULL)
724                               longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
725                     (void) snprintf(sdp->dtsd_strdata, n, "%s`%ld", dmp->dm_name,
726                         dret->dn_type);
727                     if (dmp->dm_pid != 0) {
728                               (void) snprintf(sdp->dtsd_strdata, n, "%s`%d`%ld",
729                                   dmp->dm_name, ctflib, dret->dn_type);
730                     } else {
731                               (void) snprintf(sdp->dtsd_strdata, n, "%s`%ld",
732                                   dmp->dm_name, dret->dn_type);
733                     }
734           }
735 
736           ap->dtad_difo = dt_as(yypcb);
737           ap->dtad_kind = DTRACEACT_DIFEXPR;
738 }
739 
740 static void
dt_action_tracemem(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)741 dt_action_tracemem(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
742 {
743           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
744 
745           dt_node_t *addr = dnp->dn_args;
746           dt_node_t *max = dnp->dn_args->dn_list;
747           dt_node_t *size;
748 
749           char n[DT_TYPE_NAMELEN];
750 
751           if (dt_node_is_integer(addr) == 0 && dt_node_is_pointer(addr) == 0) {
752                     dnerror(addr, D_TRACEMEM_ADDR,
753                         "tracemem( ) argument #1 is incompatible with "
754                         "prototype:\n\tprototype: pointer or integer\n"
755                         "\t argument: %s\n",
756                         dt_node_type_name(addr, n, sizeof (n)));
757           }
758 
759           if (dt_node_is_posconst(max) == 0) {
760                     dnerror(max, D_TRACEMEM_SIZE, "tracemem( ) argument #2 must "
761                         "be a non-zero positive integral constant expression\n");
762           }
763 
764           if ((size = max->dn_list) != NULL) {
765                     if (size->dn_list != NULL) {
766                               dnerror(size, D_TRACEMEM_ARGS, "tracemem ( ) prototype "
767                                   "mismatch: expected at most 3 args\n");
768                     }
769 
770                     if (!dt_node_is_scalar(size)) {
771                               dnerror(size, D_TRACEMEM_DYNSIZE, "tracemem ( ) "
772                                   "dynamic size (argument #3) must be of "
773                                   "scalar type\n");
774                     }
775 
776                     dt_cg(yypcb, size);
777                     ap->dtad_difo = dt_as(yypcb);
778                     ap->dtad_difo->dtdo_rtype = dt_int_rtype;
779                     ap->dtad_kind = DTRACEACT_TRACEMEM_DYNSIZE;
780 
781                     ap = dt_stmt_action(dtp, sdp);
782           }
783 
784           dt_cg(yypcb, addr);
785           ap->dtad_difo = dt_as(yypcb);
786           ap->dtad_kind = DTRACEACT_TRACEMEM;
787 
788           ap->dtad_difo->dtdo_rtype.dtdt_flags |= DIF_TF_BYREF;
789           ap->dtad_difo->dtdo_rtype.dtdt_size = max->dn_value;
790 }
791 
792 static void
dt_action_stack_args(dtrace_hdl_t * dtp,dtrace_actdesc_t * ap,dt_node_t * arg0)793 dt_action_stack_args(dtrace_hdl_t *dtp, dtrace_actdesc_t *ap, dt_node_t *arg0)
794 {
795           ap->dtad_kind = DTRACEACT_STACK;
796 
797           if (dtp->dt_options[DTRACEOPT_STACKFRAMES] != DTRACEOPT_UNSET) {
798                     ap->dtad_arg = dtp->dt_options[DTRACEOPT_STACKFRAMES];
799           } else {
800                     ap->dtad_arg = 0;
801           }
802 
803           if (arg0 != NULL) {
804                     if (arg0->dn_list != NULL) {
805                               dnerror(arg0, D_STACK_PROTO, "stack( ) prototype "
806                                   "mismatch: too many arguments\n");
807                     }
808 
809                     if (dt_node_is_posconst(arg0) == 0) {
810                               dnerror(arg0, D_STACK_SIZE, "stack( ) size must be a "
811                                   "non-zero positive integral constant expression\n");
812                     }
813 
814                     ap->dtad_arg = arg0->dn_value;
815           }
816 }
817 
818 static void
dt_action_stack(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)819 dt_action_stack(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
820 {
821           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
822           dt_action_stack_args(dtp, ap, dnp->dn_args);
823 }
824 
825 static void
dt_action_ustack_args(dtrace_hdl_t * dtp,dtrace_actdesc_t * ap,dt_node_t * dnp)826 dt_action_ustack_args(dtrace_hdl_t *dtp, dtrace_actdesc_t *ap, dt_node_t *dnp)
827 {
828           uint32_t nframes = 0;
829           uint32_t strsize = 0;         /* default string table size */
830           dt_node_t *arg0 = dnp->dn_args;
831           dt_node_t *arg1 = arg0 != NULL ? arg0->dn_list : NULL;
832 
833           assert(dnp->dn_ident->di_id == DT_ACT_JSTACK ||
834               dnp->dn_ident->di_id == DT_ACT_USTACK);
835 
836           if (dnp->dn_ident->di_id == DT_ACT_JSTACK) {
837                     if (dtp->dt_options[DTRACEOPT_JSTACKFRAMES] != DTRACEOPT_UNSET)
838                               nframes = dtp->dt_options[DTRACEOPT_JSTACKFRAMES];
839 
840                     if (dtp->dt_options[DTRACEOPT_JSTACKSTRSIZE] != DTRACEOPT_UNSET)
841                               strsize = dtp->dt_options[DTRACEOPT_JSTACKSTRSIZE];
842 
843                     ap->dtad_kind = DTRACEACT_JSTACK;
844           } else {
845                     assert(dnp->dn_ident->di_id == DT_ACT_USTACK);
846 
847                     if (dtp->dt_options[DTRACEOPT_USTACKFRAMES] != DTRACEOPT_UNSET)
848                               nframes = dtp->dt_options[DTRACEOPT_USTACKFRAMES];
849 
850                     ap->dtad_kind = DTRACEACT_USTACK;
851           }
852 
853           if (arg0 != NULL) {
854                     if (!dt_node_is_posconst(arg0)) {
855                               dnerror(arg0, D_USTACK_FRAMES, "ustack( ) argument #1 "
856                                   "must be a non-zero positive integer constant\n");
857                     }
858                     nframes = (uint32_t)arg0->dn_value;
859           }
860 
861           if (arg1 != NULL) {
862                     if (arg1->dn_kind != DT_NODE_INT ||
863                         ((arg1->dn_flags & DT_NF_SIGNED) &&
864                         (int64_t)arg1->dn_value < 0)) {
865                               dnerror(arg1, D_USTACK_STRSIZE, "ustack( ) argument #2 "
866                                   "must be a positive integer constant\n");
867                     }
868 
869                     if (arg1->dn_list != NULL) {
870                               dnerror(arg1, D_USTACK_PROTO, "ustack( ) prototype "
871                                   "mismatch: too many arguments\n");
872                     }
873 
874                     strsize = (uint32_t)arg1->dn_value;
875           }
876 
877           ap->dtad_arg = DTRACE_USTACK_ARG(nframes, strsize);
878 }
879 
880 static void
dt_action_ustack(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)881 dt_action_ustack(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
882 {
883           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
884           dt_action_ustack_args(dtp, ap, dnp);
885 }
886 
887 static void
dt_action_setopt(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)888 dt_action_setopt(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
889 {
890           dtrace_actdesc_t *ap;
891           dt_node_t *arg0, *arg1;
892 
893           /*
894            * The prototype guarantees that we are called with either one or
895            * two arguments, and that any arguments that are present are strings.
896            */
897           arg0 = dnp->dn_args;
898           arg1 = arg0->dn_list;
899 
900           ap = dt_stmt_action(dtp, sdp);
901           dt_cg(yypcb, arg0);
902           ap->dtad_difo = dt_as(yypcb);
903           ap->dtad_kind = DTRACEACT_LIBACT;
904           ap->dtad_arg = DT_ACT_SETOPT;
905 
906           ap = dt_stmt_action(dtp, sdp);
907 
908           if (arg1 == NULL) {
909                     dt_action_difconst(ap, 0, DTRACEACT_LIBACT);
910           } else {
911                     dt_cg(yypcb, arg1);
912                     ap->dtad_difo = dt_as(yypcb);
913                     ap->dtad_kind = DTRACEACT_LIBACT;
914           }
915 
916           ap->dtad_arg = DT_ACT_SETOPT;
917 }
918 
919 /*ARGSUSED*/
920 static void
dt_action_symmod_args(dtrace_hdl_t * dtp,dtrace_actdesc_t * ap,dt_node_t * dnp,dtrace_actkind_t kind)921 dt_action_symmod_args(dtrace_hdl_t *dtp, dtrace_actdesc_t *ap,
922     dt_node_t *dnp, dtrace_actkind_t kind)
923 {
924           assert(kind == DTRACEACT_SYM || kind == DTRACEACT_MOD ||
925               kind == DTRACEACT_USYM || kind == DTRACEACT_UMOD ||
926               kind == DTRACEACT_UADDR);
927 
928           dt_cg(yypcb, dnp);
929           ap->dtad_difo = dt_as(yypcb);
930           ap->dtad_kind = kind;
931           ap->dtad_difo->dtdo_rtype.dtdt_size = sizeof (uint64_t);
932 }
933 
934 static void
dt_action_symmod(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp,dtrace_actkind_t kind)935 dt_action_symmod(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp,
936     dtrace_actkind_t kind)
937 {
938           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
939           dt_action_symmod_args(dtp, ap, dnp->dn_args, kind);
940 }
941 
942 /*ARGSUSED*/
943 static void
dt_action_ftruncate(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)944 dt_action_ftruncate(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
945 {
946           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
947 
948           /*
949            * Library actions need a DIFO that serves as an argument.  As
950            * ftruncate() doesn't take an argument, we generate the constant 0
951            * in a DIFO; this constant will be ignored when the ftruncate() is
952            * processed.
953            */
954           dt_action_difconst(ap, 0, DTRACEACT_LIBACT);
955           ap->dtad_arg = DT_ACT_FTRUNCATE;
956 }
957 
958 /*ARGSUSED*/
959 static void
dt_action_stop(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)960 dt_action_stop(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
961 {
962           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
963 
964           ap->dtad_kind = DTRACEACT_STOP;
965           ap->dtad_arg = 0;
966 }
967 
968 /*ARGSUSED*/
969 static void
dt_action_breakpoint(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)970 dt_action_breakpoint(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
971 {
972           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
973 
974           ap->dtad_kind = DTRACEACT_BREAKPOINT;
975           ap->dtad_arg = 0;
976 }
977 
978 /*ARGSUSED*/
979 static void
dt_action_panic(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)980 dt_action_panic(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
981 {
982           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
983 
984           ap->dtad_kind = DTRACEACT_PANIC;
985           ap->dtad_arg = 0;
986 }
987 
988 static void
dt_action_chill(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)989 dt_action_chill(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
990 {
991           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
992 
993           dt_cg(yypcb, dnp->dn_args);
994           ap->dtad_difo = dt_as(yypcb);
995           ap->dtad_kind = DTRACEACT_CHILL;
996 }
997 
998 static void
dt_action_raise(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)999 dt_action_raise(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1000 {
1001           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1002 
1003           dt_cg(yypcb, dnp->dn_args);
1004           ap->dtad_difo = dt_as(yypcb);
1005           ap->dtad_kind = DTRACEACT_RAISE;
1006 }
1007 
1008 static void
dt_action_exit(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)1009 dt_action_exit(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1010 {
1011           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1012 
1013           dt_cg(yypcb, dnp->dn_args);
1014           ap->dtad_difo = dt_as(yypcb);
1015           ap->dtad_kind = DTRACEACT_EXIT;
1016           ap->dtad_difo->dtdo_rtype.dtdt_size = sizeof (int);
1017 }
1018 
1019 static void
dt_action_speculate(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)1020 dt_action_speculate(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1021 {
1022           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1023 
1024           dt_cg(yypcb, dnp->dn_args);
1025           ap->dtad_difo = dt_as(yypcb);
1026           ap->dtad_kind = DTRACEACT_SPECULATE;
1027 }
1028 
1029 static void
dt_action_printm(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)1030 dt_action_printm(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1031 {
1032           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1033 
1034           dt_node_t *size = dnp->dn_args;
1035           dt_node_t *addr = dnp->dn_args->dn_list;
1036 
1037           char n[DT_TYPE_NAMELEN];
1038 
1039           if (dt_node_is_posconst(size) == 0) {
1040                     dnerror(size, D_PRINTM_SIZE, "printm( ) argument #1 must "
1041                         "be a non-zero positive integral constant expression\n");
1042           }
1043 
1044           if (dt_node_is_pointer(addr) == 0) {
1045                     dnerror(addr, D_PRINTM_ADDR,
1046                         "printm( ) argument #2 is incompatible with "
1047                         "prototype:\n\tprototype: pointer\n"
1048                         "\t argument: %s\n",
1049                         dt_node_type_name(addr, n, sizeof (n)));
1050           }
1051 
1052           dt_cg(yypcb, addr);
1053           ap->dtad_difo = dt_as(yypcb);
1054           ap->dtad_kind = DTRACEACT_PRINTM;
1055 
1056           ap->dtad_difo->dtdo_rtype.dtdt_flags |= DIF_TF_BYREF;
1057           ap->dtad_difo->dtdo_rtype.dtdt_size = size->dn_value + sizeof(uintptr_t);
1058 }
1059 
1060 static void
dt_action_commit(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)1061 dt_action_commit(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1062 {
1063           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1064 
1065           dt_cg(yypcb, dnp->dn_args);
1066           ap->dtad_difo = dt_as(yypcb);
1067           ap->dtad_kind = DTRACEACT_COMMIT;
1068 }
1069 
1070 static void
dt_action_discard(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)1071 dt_action_discard(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1072 {
1073           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1074 
1075           dt_cg(yypcb, dnp->dn_args);
1076           ap->dtad_difo = dt_as(yypcb);
1077           ap->dtad_kind = DTRACEACT_DISCARD;
1078 }
1079 
1080 static void
dt_compile_fun(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)1081 dt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1082 {
1083           switch (dnp->dn_expr->dn_ident->di_id) {
1084           case DT_ACT_BREAKPOINT:
1085                     dt_action_breakpoint(dtp, dnp->dn_expr, sdp);
1086                     break;
1087           case DT_ACT_CHILL:
1088                     dt_action_chill(dtp, dnp->dn_expr, sdp);
1089                     break;
1090           case DT_ACT_CLEAR:
1091                     dt_action_clear(dtp, dnp->dn_expr, sdp);
1092                     break;
1093           case DT_ACT_COMMIT:
1094                     dt_action_commit(dtp, dnp->dn_expr, sdp);
1095                     break;
1096           case DT_ACT_DENORMALIZE:
1097                     dt_action_normalize(dtp, dnp->dn_expr, sdp);
1098                     break;
1099           case DT_ACT_DISCARD:
1100                     dt_action_discard(dtp, dnp->dn_expr, sdp);
1101                     break;
1102           case DT_ACT_EXIT:
1103                     dt_action_exit(dtp, dnp->dn_expr, sdp);
1104                     break;
1105           case DT_ACT_FREOPEN:
1106                     dt_action_printflike(dtp, dnp->dn_expr, sdp, DTRACEACT_FREOPEN);
1107                     break;
1108           case DT_ACT_FTRUNCATE:
1109                     dt_action_ftruncate(dtp, dnp->dn_expr, sdp);
1110                     break;
1111           case DT_ACT_MOD:
1112                     dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_MOD);
1113                     break;
1114           case DT_ACT_NORMALIZE:
1115                     dt_action_normalize(dtp, dnp->dn_expr, sdp);
1116                     break;
1117           case DT_ACT_PANIC:
1118                     dt_action_panic(dtp, dnp->dn_expr, sdp);
1119                     break;
1120           case DT_ACT_PRINT:
1121                     dt_action_trace(dtp, dnp->dn_expr, sdp);
1122                     break;
1123           case DT_ACT_PRINTA:
1124                     dt_action_printa(dtp, dnp->dn_expr, sdp);
1125                     break;
1126           case DT_ACT_PRINTF:
1127                     dt_action_printflike(dtp, dnp->dn_expr, sdp, DTRACEACT_PRINTF);
1128                     break;
1129           case DT_ACT_PRINTM:
1130                     dt_action_printm(dtp, dnp->dn_expr, sdp);
1131                     break;
1132           case DT_ACT_RAISE:
1133                     dt_action_raise(dtp, dnp->dn_expr, sdp);
1134                     break;
1135           case DT_ACT_SETOPT:
1136                     dt_action_setopt(dtp, dnp->dn_expr, sdp);
1137                     break;
1138           case DT_ACT_SPECULATE:
1139                     dt_action_speculate(dtp, dnp->dn_expr, sdp);
1140                     break;
1141           case DT_ACT_STACK:
1142                     dt_action_stack(dtp, dnp->dn_expr, sdp);
1143                     break;
1144           case DT_ACT_STOP:
1145                     dt_action_stop(dtp, dnp->dn_expr, sdp);
1146                     break;
1147           case DT_ACT_SYM:
1148                     dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_SYM);
1149                     break;
1150           case DT_ACT_SYSTEM:
1151                     dt_action_printflike(dtp, dnp->dn_expr, sdp, DTRACEACT_SYSTEM);
1152                     break;
1153           case DT_ACT_TRACE:
1154                     dt_action_trace(dtp, dnp->dn_expr, sdp);
1155                     break;
1156           case DT_ACT_TRACEMEM:
1157                     dt_action_tracemem(dtp, dnp->dn_expr, sdp);
1158                     break;
1159           case DT_ACT_TRUNC:
1160                     dt_action_trunc(dtp, dnp->dn_expr, sdp);
1161                     break;
1162           case DT_ACT_UADDR:
1163                     dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_UADDR);
1164                     break;
1165           case DT_ACT_UMOD:
1166                     dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_UMOD);
1167                     break;
1168           case DT_ACT_USYM:
1169                     dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_USYM);
1170                     break;
1171           case DT_ACT_USTACK:
1172           case DT_ACT_JSTACK:
1173                     dt_action_ustack(dtp, dnp->dn_expr, sdp);
1174                     break;
1175           default:
1176                     dnerror(dnp->dn_expr, D_UNKNOWN, "tracing function %s( ) is "
1177                         "not yet supported\n", dnp->dn_expr->dn_ident->di_name);
1178           }
1179 }
1180 
1181 static void
dt_compile_exp(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)1182 dt_compile_exp(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1183 {
1184           dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1185 
1186           dt_cg(yypcb, dnp->dn_expr);
1187           ap->dtad_difo = dt_as(yypcb);
1188           ap->dtad_difo->dtdo_rtype = dt_void_rtype;
1189           ap->dtad_kind = DTRACEACT_DIFEXPR;
1190 }
1191 
1192 static void
dt_compile_agg(dtrace_hdl_t * dtp,dt_node_t * dnp,dtrace_stmtdesc_t * sdp)1193 dt_compile_agg(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1194 {
1195           dt_ident_t *aid, *fid;
1196           dt_node_t *anp, *incr = NULL;
1197           dtrace_actdesc_t *ap;
1198           uint_t n = 1, argmax;
1199           uint64_t arg = 0;
1200 
1201           /*
1202            * If the aggregation has no aggregating function applied to it, then
1203            * this statement has no effect.  Flag this as a programming error.
1204            */
1205           if (dnp->dn_aggfun == NULL) {
1206                     dnerror(dnp, D_AGG_NULL, "expression has null effect: @%s\n",
1207                         dnp->dn_ident->di_name);
1208           }
1209 
1210           aid = dnp->dn_ident;
1211           fid = dnp->dn_aggfun->dn_ident;
1212 
1213           if (dnp->dn_aggfun->dn_args != NULL &&
1214               dt_node_is_scalar(dnp->dn_aggfun->dn_args) == 0) {
1215                     dnerror(dnp->dn_aggfun, D_AGG_SCALAR, "%s( ) argument #1 must "
1216                         "be of scalar type\n", fid->di_name);
1217           }
1218 
1219           /*
1220            * The ID of the aggregation itself is implicitly recorded as the first
1221            * member of each aggregation tuple so we can distinguish them later.
1222            */
1223           ap = dt_stmt_action(dtp, sdp);
1224           dt_action_difconst(ap, aid->di_id, DTRACEACT_DIFEXPR);
1225 
1226           for (anp = dnp->dn_aggtup; anp != NULL; anp = anp->dn_list) {
1227                     ap = dt_stmt_action(dtp, sdp);
1228                     n++;
1229 
1230                     if (anp->dn_kind == DT_NODE_FUNC) {
1231                               if (anp->dn_ident->di_id == DT_ACT_STACK) {
1232                                         dt_action_stack_args(dtp, ap, anp->dn_args);
1233                                         continue;
1234                               }
1235 
1236                               if (anp->dn_ident->di_id == DT_ACT_USTACK ||
1237                                   anp->dn_ident->di_id == DT_ACT_JSTACK) {
1238                                         dt_action_ustack_args(dtp, ap, anp);
1239                                         continue;
1240                               }
1241 
1242                               switch (anp->dn_ident->di_id) {
1243                               case DT_ACT_UADDR:
1244                                         dt_action_symmod_args(dtp, ap,
1245                                             anp->dn_args, DTRACEACT_UADDR);
1246                                         continue;
1247 
1248                               case DT_ACT_USYM:
1249                                         dt_action_symmod_args(dtp, ap,
1250                                             anp->dn_args, DTRACEACT_USYM);
1251                                         continue;
1252 
1253                               case DT_ACT_UMOD:
1254                                         dt_action_symmod_args(dtp, ap,
1255                                             anp->dn_args, DTRACEACT_UMOD);
1256                                         continue;
1257 
1258                               case DT_ACT_SYM:
1259                                         dt_action_symmod_args(dtp, ap,
1260                                             anp->dn_args, DTRACEACT_SYM);
1261                                         continue;
1262 
1263                               case DT_ACT_MOD:
1264                                         dt_action_symmod_args(dtp, ap,
1265                                             anp->dn_args, DTRACEACT_MOD);
1266                                         continue;
1267 
1268                               default:
1269                                         break;
1270                               }
1271                     }
1272 
1273                     dt_cg(yypcb, anp);
1274                     ap->dtad_difo = dt_as(yypcb);
1275                     ap->dtad_kind = DTRACEACT_DIFEXPR;
1276           }
1277 
1278           if (fid->di_id == DTRACEAGG_LQUANTIZE) {
1279                     /*
1280                      * For linear quantization, we have between two and four
1281                      * arguments in addition to the expression:
1282                      *
1283                      *    arg1 => Base value
1284                      *    arg2 => Limit value
1285                      *    arg3 => Quantization level step size (defaults to 1)
1286                      *    arg4 => Quantization increment value (defaults to 1)
1287                      */
1288                     dt_node_t *arg1 = dnp->dn_aggfun->dn_args->dn_list;
1289                     dt_node_t *arg2 = arg1->dn_list;
1290                     dt_node_t *arg3 = arg2->dn_list;
1291                     dt_idsig_t *isp;
1292                     uint64_t nlevels, step = 1, oarg;
1293                     int64_t baseval, limitval;
1294 
1295                     if (arg1->dn_kind != DT_NODE_INT) {
1296                               dnerror(arg1, D_LQUANT_BASETYPE, "lquantize( ) "
1297                                   "argument #1 must be an integer constant\n");
1298                     }
1299 
1300                     baseval = (int64_t)arg1->dn_value;
1301 
1302                     if (baseval < INT32_MIN || baseval > INT32_MAX) {
1303                               dnerror(arg1, D_LQUANT_BASEVAL, "lquantize( ) "
1304                                   "argument #1 must be a 32-bit quantity\n");
1305                     }
1306 
1307                     if (arg2->dn_kind != DT_NODE_INT) {
1308                               dnerror(arg2, D_LQUANT_LIMTYPE, "lquantize( ) "
1309                                   "argument #2 must be an integer constant\n");
1310                     }
1311 
1312                     limitval = (int64_t)arg2->dn_value;
1313 
1314                     if (limitval < INT32_MIN || limitval > INT32_MAX) {
1315                               dnerror(arg2, D_LQUANT_LIMVAL, "lquantize( ) "
1316                                   "argument #2 must be a 32-bit quantity\n");
1317                     }
1318 
1319                     if (limitval < baseval) {
1320                               dnerror(dnp, D_LQUANT_MISMATCH,
1321                                   "lquantize( ) base (argument #1) must be less "
1322                                   "than limit (argument #2)\n");
1323                     }
1324 
1325                     if (arg3 != NULL) {
1326                               if (!dt_node_is_posconst(arg3)) {
1327                                         dnerror(arg3, D_LQUANT_STEPTYPE, "lquantize( ) "
1328                                             "argument #3 must be a non-zero positive "
1329                                             "integer constant\n");
1330                               }
1331 
1332                               if ((step = arg3->dn_value) > UINT16_MAX) {
1333                                         dnerror(arg3, D_LQUANT_STEPVAL, "lquantize( ) "
1334                                             "argument #3 must be a 16-bit quantity\n");
1335                               }
1336                     }
1337 
1338                     nlevels = (limitval - baseval) / step;
1339 
1340                     if (nlevels == 0) {
1341                               dnerror(dnp, D_LQUANT_STEPLARGE,
1342                                   "lquantize( ) step (argument #3) too large: must "
1343                                   "have at least one quantization level\n");
1344                     }
1345 
1346                     if (nlevels > UINT16_MAX) {
1347                               dnerror(dnp, D_LQUANT_STEPSMALL, "lquantize( ) step "
1348                                   "(argument #3) too small: number of quantization "
1349                                   "levels must be a 16-bit quantity\n");
1350                     }
1351 
1352                     arg = (step << DTRACE_LQUANTIZE_STEPSHIFT) |
1353                         (nlevels << DTRACE_LQUANTIZE_LEVELSHIFT) |
1354                         ((baseval << DTRACE_LQUANTIZE_BASESHIFT) &
1355                         DTRACE_LQUANTIZE_BASEMASK);
1356 
1357                     assert(arg != 0);
1358 
1359                     isp = (dt_idsig_t *)aid->di_data;
1360 
1361                     if (isp->dis_auxinfo == 0) {
1362                               /*
1363                                * This is the first time we've seen an lquantize()
1364                                * for this aggregation; we'll store our argument
1365                                * as the auxiliary signature information.
1366                                */
1367                               isp->dis_auxinfo = arg;
1368                     } else if ((oarg = isp->dis_auxinfo) != arg) {
1369                               /*
1370                                * If we have seen this lquantize() before and the
1371                                * argument doesn't match the original argument, pick
1372                                * the original argument apart to concisely report the
1373                                * mismatch.
1374                                */
1375                               int obaseval = DTRACE_LQUANTIZE_BASE(oarg);
1376                               int onlevels = DTRACE_LQUANTIZE_LEVELS(oarg);
1377                               int ostep = DTRACE_LQUANTIZE_STEP(oarg);
1378 
1379                               if (obaseval != baseval) {
1380                                         dnerror(dnp, D_LQUANT_MATCHBASE, "lquantize( ) "
1381                                             "base (argument #1) doesn't match previous "
1382                                             "declaration: expected %d, found %d\n",
1383                                             obaseval, (int)baseval);
1384                               }
1385 
1386                               if (onlevels * ostep != nlevels * step) {
1387                                         dnerror(dnp, D_LQUANT_MATCHLIM, "lquantize( ) "
1388                                             "limit (argument #2) doesn't match previous"
1389                                             " declaration: expected %d, found %d\n",
1390                                             obaseval + onlevels * ostep,
1391                                             (int)baseval + (int)nlevels * (int)step);
1392                               }
1393 
1394                               if (ostep != step) {
1395                                         dnerror(dnp, D_LQUANT_MATCHSTEP, "lquantize( ) "
1396                                             "step (argument #3) doesn't match previous "
1397                                             "declaration: expected %d, found %d\n",
1398                                             ostep, (int)step);
1399                               }
1400 
1401                               /*
1402                                * We shouldn't be able to get here -- one of the
1403                                * parameters must be mismatched if the arguments
1404                                * didn't match.
1405                                */
1406                               assert(0);
1407                     }
1408 
1409                     incr = arg3 != NULL ? arg3->dn_list : NULL;
1410                     argmax = 5;
1411           }
1412 
1413           if (fid->di_id == DTRACEAGG_LLQUANTIZE) {
1414                     /*
1415                      * For log/linear quantizations, we have between one and five
1416                      * arguments in addition to the expression:
1417                      *
1418                      *    arg1 => Factor
1419                      *    arg2 => Low magnitude
1420                      *    arg3 => High magnitude
1421                      *    arg4 => Number of steps per magnitude
1422                      *    arg5 => Quantization increment value (defaults to 1)
1423                      */
1424                     dt_node_t *llarg = dnp->dn_aggfun->dn_args->dn_list;
1425                     uint64_t oarg, order, v;
1426                     dt_idsig_t *isp;
1427                     int i;
1428 
1429                     struct {
1430                               char *str;                    /* string identifier */
1431                               int badtype;                  /* error on bad type */
1432                               int badval;                   /* error on bad value */
1433                               int mismatch;                 /* error on bad match */
1434                               int shift;                    /* shift value */
1435                               uint16_t value;               /* value itself */
1436                     } args[] = {
1437                               { "factor", D_LLQUANT_FACTORTYPE,
1438                                   D_LLQUANT_FACTORVAL, D_LLQUANT_FACTORMATCH,
1439                                   DTRACE_LLQUANTIZE_FACTORSHIFT },
1440                               { "low magnitude", D_LLQUANT_LOWTYPE,
1441                                   D_LLQUANT_LOWVAL, D_LLQUANT_LOWMATCH,
1442                                   DTRACE_LLQUANTIZE_LOWSHIFT },
1443                               { "high magnitude", D_LLQUANT_HIGHTYPE,
1444                                   D_LLQUANT_HIGHVAL, D_LLQUANT_HIGHMATCH,
1445                                   DTRACE_LLQUANTIZE_HIGHSHIFT },
1446                               { "linear steps per magnitude", D_LLQUANT_NSTEPTYPE,
1447                                   D_LLQUANT_NSTEPVAL, D_LLQUANT_NSTEPMATCH,
1448                                   DTRACE_LLQUANTIZE_NSTEPSHIFT },
1449                               { NULL }
1450                     };
1451 
1452                     assert(arg == 0);
1453 
1454                     for (i = 0; args[i].str != NULL; i++) {
1455                               if (llarg->dn_kind != DT_NODE_INT) {
1456                                         dnerror(llarg, args[i].badtype, "llquantize( ) "
1457                                             "argument #%d (%s) must be an "
1458                                             "integer constant\n", i + 1, args[i].str);
1459                               }
1460 
1461                               if ((uint64_t)llarg->dn_value > UINT16_MAX) {
1462                                         dnerror(llarg, args[i].badval, "llquantize( ) "
1463                                             "argument #%d (%s) must be an unsigned "
1464                                             "16-bit quantity\n", i + 1, args[i].str);
1465                               }
1466 
1467                               args[i].value = (uint16_t)llarg->dn_value;
1468 
1469                               assert(!(arg & ((uint64_t)UINT16_MAX <<
1470                                   args[i].shift)));
1471                               arg |= ((uint64_t)args[i].value << args[i].shift);
1472                               llarg = llarg->dn_list;
1473                     }
1474 
1475                     assert(arg != 0);
1476 
1477                     if (args[0].value < 2) {
1478                               dnerror(dnp, D_LLQUANT_FACTORSMALL, "llquantize( ) "
1479                                   "factor (argument #1) must be two or more\n");
1480                     }
1481 
1482                     if (args[1].value >= args[2].value) {
1483                               dnerror(dnp, D_LLQUANT_MAGRANGE, "llquantize( ) "
1484                                   "high magnitude (argument #3) must be greater "
1485                                   "than low magnitude (argument #2)\n");
1486                     }
1487 
1488                     if (args[3].value < args[0].value) {
1489                               dnerror(dnp, D_LLQUANT_FACTORNSTEPS, "llquantize( ) "
1490                                   "factor (argument #1) must be less than or "
1491                                   "equal to the number of linear steps per "
1492                                   "magnitude (argument #4)\n");
1493                     }
1494 
1495                     for (v = args[0].value; v < args[3].value; v *= args[0].value)
1496                               continue;
1497 
1498                     if ((args[3].value % args[0].value) || (v % args[3].value)) {
1499                               dnerror(dnp, D_LLQUANT_FACTOREVEN, "llquantize( ) "
1500                                   "factor (argument #1) must evenly divide the "
1501                                   "number of steps per magnitude (argument #4), "
1502                                   "and the number of steps per magnitude must evenly "
1503                                   "divide a power of the factor\n");
1504                     }
1505 
1506                     for (i = 0, order = 1; i < args[2].value; i++) {
1507                               if (order * args[0].value > order) {
1508                                         order *= args[0].value;
1509                                         continue;
1510                               }
1511 
1512                               dnerror(dnp, D_LLQUANT_MAGTOOBIG, "llquantize( ) "
1513                                   "factor (%d) raised to power of high magnitude "
1514                                   "(%d) overflows 64-bits\n", args[0].value,
1515                                   args[2].value);
1516                     }
1517 
1518                     isp = (dt_idsig_t *)aid->di_data;
1519 
1520                     if (isp->dis_auxinfo == 0) {
1521                               /*
1522                                * This is the first time we've seen an llquantize()
1523                                * for this aggregation; we'll store our argument
1524                                * as the auxiliary signature information.
1525                                */
1526                               isp->dis_auxinfo = arg;
1527                     } else if ((oarg = isp->dis_auxinfo) != arg) {
1528                               /*
1529                                * If we have seen this llquantize() before and the
1530                                * argument doesn't match the original argument, pick
1531                                * the original argument apart to concisely report the
1532                                * mismatch.
1533                                */
1534                               int expected = 0, found = 0;
1535 
1536                               for (i = 0; expected == found; i++) {
1537                                         assert(args[i].str != NULL);
1538 
1539                                         expected = (oarg >> args[i].shift) & UINT16_MAX;
1540                                         found = (arg >> args[i].shift) & UINT16_MAX;
1541                               }
1542 
1543                               dnerror(dnp, args[i - 1].mismatch, "llquantize( ) "
1544                                   "%s (argument #%d) doesn't match previous "
1545                                   "declaration: expected %d, found %d\n",
1546                                   args[i - 1].str, i, expected, found);
1547                     }
1548 
1549                     incr = llarg;
1550                     argmax = 6;
1551           }
1552 
1553           if (fid->di_id == DTRACEAGG_QUANTIZE) {
1554                     incr = dnp->dn_aggfun->dn_args->dn_list;
1555                     argmax = 2;
1556           }
1557 
1558           if (incr != NULL) {
1559                     if (!dt_node_is_scalar(incr)) {
1560                               dnerror(dnp, D_PROTO_ARG, "%s( ) increment value "
1561                                   "(argument #%d) must be of scalar type\n",
1562                                   fid->di_name, argmax);
1563                     }
1564 
1565                     if ((anp = incr->dn_list) != NULL) {
1566                               int argc = argmax;
1567 
1568                               for (; anp != NULL; anp = anp->dn_list)
1569                                         argc++;
1570 
1571                               dnerror(incr, D_PROTO_LEN, "%s( ) prototype "
1572                                   "mismatch: %d args passed, at most %d expected",
1573                                   fid->di_name, argc, argmax);
1574                     }
1575 
1576                     ap = dt_stmt_action(dtp, sdp);
1577                     n++;
1578 
1579                     dt_cg(yypcb, incr);
1580                     ap->dtad_difo = dt_as(yypcb);
1581                     ap->dtad_difo->dtdo_rtype = dt_void_rtype;
1582                     ap->dtad_kind = DTRACEACT_DIFEXPR;
1583           }
1584 
1585           assert(sdp->dtsd_aggdata == NULL);
1586           sdp->dtsd_aggdata = aid;
1587 
1588           ap = dt_stmt_action(dtp, sdp);
1589           assert(fid->di_kind == DT_IDENT_AGGFUNC);
1590           assert(DTRACEACT_ISAGG(fid->di_id));
1591           ap->dtad_kind = fid->di_id;
1592           ap->dtad_ntuple = n;
1593           ap->dtad_arg = arg;
1594 
1595           if (dnp->dn_aggfun->dn_args != NULL) {
1596                     dt_cg(yypcb, dnp->dn_aggfun->dn_args);
1597                     ap->dtad_difo = dt_as(yypcb);
1598           }
1599 }
1600 
1601 static void
dt_compile_one_clause(dtrace_hdl_t * dtp,dt_node_t * cnp,dt_node_t * pnp)1602 dt_compile_one_clause(dtrace_hdl_t *dtp, dt_node_t *cnp, dt_node_t *pnp)
1603 {
1604           dtrace_ecbdesc_t *edp;
1605           dtrace_stmtdesc_t *sdp;
1606           dt_node_t *dnp;
1607 
1608           yylineno = pnp->dn_line;
1609           dt_setcontext(dtp, pnp->dn_desc);
1610           (void) dt_node_cook(cnp, DT_IDFLG_REF);
1611 
1612           if (DT_TREEDUMP_PASS(dtp, 2))
1613                     dt_node_printr(cnp, stderr, 0);
1614 
1615           if ((edp = dt_ecbdesc_create(dtp, pnp->dn_desc)) == NULL)
1616                     longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
1617 
1618           assert(yypcb->pcb_ecbdesc == NULL);
1619           yypcb->pcb_ecbdesc = edp;
1620 
1621           if (cnp->dn_pred != NULL) {
1622                     dt_cg(yypcb, cnp->dn_pred);
1623                     edp->dted_pred.dtpdd_difo = dt_as(yypcb);
1624           }
1625 
1626           if (cnp->dn_acts == NULL) {
1627                     dt_stmt_append(dt_stmt_create(dtp, edp,
1628                         cnp->dn_ctxattr, _dtrace_defattr), cnp);
1629           }
1630 
1631           for (dnp = cnp->dn_acts; dnp != NULL; dnp = dnp->dn_list) {
1632                     assert(yypcb->pcb_stmt == NULL);
1633                     sdp = dt_stmt_create(dtp, edp, cnp->dn_ctxattr, cnp->dn_attr);
1634 
1635                     switch (dnp->dn_kind) {
1636                     case DT_NODE_DEXPR:
1637                               if (dnp->dn_expr->dn_kind == DT_NODE_AGG)
1638                                         dt_compile_agg(dtp, dnp->dn_expr, sdp);
1639                               else
1640                                         dt_compile_exp(dtp, dnp, sdp);
1641                               break;
1642                     case DT_NODE_DFUNC:
1643                               dt_compile_fun(dtp, dnp, sdp);
1644                               break;
1645                     case DT_NODE_AGG:
1646                               dt_compile_agg(dtp, dnp, sdp);
1647                               break;
1648                     default:
1649                               dnerror(dnp, D_UNKNOWN, "internal error -- node kind "
1650                                   "%u is not a valid statement\n", dnp->dn_kind);
1651                     }
1652 
1653                     assert(yypcb->pcb_stmt == sdp);
1654                     dt_stmt_append(sdp, dnp);
1655           }
1656 
1657           assert(yypcb->pcb_ecbdesc == edp);
1658           dt_ecbdesc_release(dtp, edp);
1659           dt_endcontext(dtp);
1660           yypcb->pcb_ecbdesc = NULL;
1661 }
1662 
1663 static void
dt_compile_clause(dtrace_hdl_t * dtp,dt_node_t * cnp)1664 dt_compile_clause(dtrace_hdl_t *dtp, dt_node_t *cnp)
1665 {
1666           dt_node_t *pnp;
1667 
1668           for (pnp = cnp->dn_pdescs; pnp != NULL; pnp = pnp->dn_list)
1669                     dt_compile_one_clause(dtp, cnp, pnp);
1670 }
1671 
1672 static void
dt_compile_xlator(dt_node_t * dnp)1673 dt_compile_xlator(dt_node_t *dnp)
1674 {
1675           dt_xlator_t *dxp = dnp->dn_xlator;
1676           dt_node_t *mnp;
1677 
1678           for (mnp = dnp->dn_members; mnp != NULL; mnp = mnp->dn_list) {
1679                     assert(dxp->dx_membdif[mnp->dn_membid] == NULL);
1680                     dt_cg(yypcb, mnp);
1681                     dxp->dx_membdif[mnp->dn_membid] = dt_as(yypcb);
1682           }
1683 }
1684 
1685 void
dt_setcontext(dtrace_hdl_t * dtp,dtrace_probedesc_t * pdp)1686 dt_setcontext(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp)
1687 {
1688           const dtrace_pattr_t *pap;
1689           dt_probe_t *prp;
1690           dt_provider_t *pvp;
1691           dt_ident_t *idp;
1692           char attrstr[8];
1693           int err;
1694 
1695           /*
1696            * Both kernel and pid based providers are allowed to have names
1697            * ending with what could be interpreted as a number. We assume it's
1698            * a pid and that we may need to dynamically create probes for
1699            * that process if:
1700            *
1701            * (1) The provider doesn't exist, or,
1702            * (2) The provider exists and has DTRACE_PRIV_PROC privilege.
1703            *
1704            * On an error, dt_pid_create_probes() will set the error message
1705            * and tag -- we just have to longjmp() out of here.
1706            */
1707           if (isdigit((unsigned char)pdp->dtpd_provider[strlen(pdp->dtpd_provider) - 1]) &&
1708               ((pvp = dt_provider_lookup(dtp, pdp->dtpd_provider)) == NULL ||
1709               pvp->pv_desc.dtvd_priv.dtpp_flags & DTRACE_PRIV_PROC) &&
1710               dt_pid_create_probes(pdp, dtp, yypcb) != 0) {
1711                     longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
1712           }
1713 
1714           /*
1715            * Call dt_probe_info() to get the probe arguments and attributes.  If
1716            * a representative probe is found, set 'pap' to the probe provider's
1717            * attributes.  Otherwise set 'pap' to default Unstable attributes.
1718            */
1719           if ((prp = dt_probe_info(dtp, pdp, &yypcb->pcb_pinfo)) == NULL) {
1720                     pap = &_dtrace_prvdesc;
1721                     err = dtrace_errno(dtp);
1722                     bzero(&yypcb->pcb_pinfo, sizeof (dtrace_probeinfo_t));
1723                     yypcb->pcb_pinfo.dtp_attr = pap->dtpa_provider;
1724                     yypcb->pcb_pinfo.dtp_arga = pap->dtpa_args;
1725           } else {
1726                     pap = &prp->pr_pvp->pv_desc.dtvd_attr;
1727                     err = 0;
1728           }
1729 
1730           if (err == EDT_NOPROBE && !(yypcb->pcb_cflags & DTRACE_C_ZDEFS)) {
1731                     xyerror(D_PDESC_ZERO, "probe description %s:%s:%s:%s does not "
1732                         "match any probes\n", pdp->dtpd_provider, pdp->dtpd_mod,
1733                         pdp->dtpd_func, pdp->dtpd_name);
1734           }
1735 
1736           if (err != EDT_NOPROBE && err != EDT_UNSTABLE && err != 0)
1737                     xyerror(D_PDESC_INVAL, "%s\n", dtrace_errmsg(dtp, err));
1738 
1739           dt_dprintf("set context to %s:%s:%s:%s [%u] prp=%p attr=%s argc=%d\n",
1740               pdp->dtpd_provider, pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name,
1741               pdp->dtpd_id, (void *)prp, dt_attr_str(yypcb->pcb_pinfo.dtp_attr,
1742               attrstr, sizeof (attrstr)), yypcb->pcb_pinfo.dtp_argc);
1743 
1744           /*
1745            * Reset the stability attributes of D global variables that vary
1746            * based on the attributes of the provider and context itself.
1747            */
1748           if ((idp = dt_idhash_lookup(dtp->dt_globals, "probeprov")) != NULL)
1749                     idp->di_attr = pap->dtpa_provider;
1750           if ((idp = dt_idhash_lookup(dtp->dt_globals, "probemod")) != NULL)
1751                     idp->di_attr = pap->dtpa_mod;
1752           if ((idp = dt_idhash_lookup(dtp->dt_globals, "probefunc")) != NULL)
1753                     idp->di_attr = pap->dtpa_func;
1754           if ((idp = dt_idhash_lookup(dtp->dt_globals, "probename")) != NULL)
1755                     idp->di_attr = pap->dtpa_name;
1756           if ((idp = dt_idhash_lookup(dtp->dt_globals, "args")) != NULL)
1757                     idp->di_attr = pap->dtpa_args;
1758 
1759           yypcb->pcb_pdesc = pdp;
1760           yypcb->pcb_probe = prp;
1761 }
1762 
1763 /*
1764  * Reset context-dependent variables and state at the end of cooking a D probe
1765  * definition clause.  This ensures that external declarations between clauses
1766  * do not reference any stale context-dependent data from the previous clause.
1767  */
1768 void
dt_endcontext(dtrace_hdl_t * dtp)1769 dt_endcontext(dtrace_hdl_t *dtp)
1770 {
1771           static const char *const cvars[] = {
1772                     "probeprov", "probemod", "probefunc", "probename", "args", NULL
1773           };
1774 
1775           dt_ident_t *idp;
1776           int i;
1777 
1778           for (i = 0; cvars[i] != NULL; i++) {
1779                     if ((idp = dt_idhash_lookup(dtp->dt_globals, cvars[i])) != NULL)
1780                               idp->di_attr = _dtrace_defattr;
1781           }
1782 
1783           yypcb->pcb_pdesc = NULL;
1784           yypcb->pcb_probe = NULL;
1785 }
1786 
1787 static int
dt_reduceid(dt_idhash_t * dhp,dt_ident_t * idp,dtrace_hdl_t * dtp)1788 dt_reduceid(dt_idhash_t *dhp, dt_ident_t *idp, dtrace_hdl_t *dtp)
1789 {
1790           if (idp->di_vers != 0 && idp->di_vers > dtp->dt_vmax)
1791                     dt_idhash_delete(dhp, idp);
1792 
1793           return (0);
1794 }
1795 
1796 /*
1797  * When dtrace_setopt() is called for "version", it calls dt_reduce() to remove
1798  * any identifiers or translators that have been previously defined as bound to
1799  * a version greater than the specified version.  Therefore, in our current
1800  * version implementation, establishing a binding is a one-way transformation.
1801  * In addition, no versioning is currently provided for types as our .d library
1802  * files do not define any types and we reserve prefixes DTRACE_ and dtrace_
1803  * for our exclusive use.  If required, type versioning will require more work.
1804  */
1805 int
dt_reduce(dtrace_hdl_t * dtp,dt_version_t v)1806 dt_reduce(dtrace_hdl_t *dtp, dt_version_t v)
1807 {
1808           char s[DT_VERSION_STRMAX];
1809           dt_xlator_t *dxp, *nxp;
1810 
1811           if (v > dtp->dt_vmax)
1812                     return (dt_set_errno(dtp, EDT_VERSREDUCED));
1813           else if (v == dtp->dt_vmax)
1814                     return (0); /* no reduction necessary */
1815 
1816           dt_dprintf("reducing api version to %s\n",
1817               dt_version_num2str(v, s, sizeof (s)));
1818 
1819           dtp->dt_vmax = v;
1820 
1821           for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; dxp = nxp) {
1822                     nxp = dt_list_next(dxp);
1823                     if ((dxp->dx_souid.di_vers != 0 && dxp->dx_souid.di_vers > v) ||
1824                         (dxp->dx_ptrid.di_vers != 0 && dxp->dx_ptrid.di_vers > v))
1825                               dt_list_delete(&dtp->dt_xlators, dxp);
1826           }
1827 
1828           (void) dt_idhash_iter(dtp->dt_macros, (dt_idhash_f *)dt_reduceid, dtp);
1829           (void) dt_idhash_iter(dtp->dt_aggs, (dt_idhash_f *)dt_reduceid, dtp);
1830           (void) dt_idhash_iter(dtp->dt_globals, (dt_idhash_f *)dt_reduceid, dtp);
1831           (void) dt_idhash_iter(dtp->dt_tls, (dt_idhash_f *)dt_reduceid, dtp);
1832 
1833           return (0);
1834 }
1835 
1836 /*
1837  * Fork and exec the cpp(1) preprocessor to run over the specified input file,
1838  * and return a FILE handle for the cpp output.  We use the /dev/fd filesystem
1839  * here to simplify the code by leveraging file descriptor inheritance.
1840  */
1841 static FILE *
dt_preproc(dtrace_hdl_t * dtp,FILE * ifp)1842 dt_preproc(dtrace_hdl_t *dtp, FILE *ifp)
1843 {
1844           int argc = dtp->dt_cpp_argc;
1845           char **argv = malloc(sizeof (char *) * (argc + 5));
1846           FILE *ofp = tmpfile();
1847 
1848 #ifdef illumos
1849           char ipath[20], opath[20]; /* big enough for /dev/fd/ + INT_MAX + \0 */
1850 #endif
1851           char verdef[32]; /* big enough for -D__SUNW_D_VERSION=0x%08x + \0 */
1852 
1853           struct sigaction act, oact;
1854           sigset_t mask, omask;
1855 
1856           int wstat, estat;
1857           pid_t pid;
1858 #ifdef illumos
1859           off64_t off;
1860 #else
1861           off_t off = 0;
1862 #endif
1863           int c;
1864 
1865           if (argv == NULL || ofp == NULL) {
1866                     (void) dt_set_errno(dtp, errno);
1867                     goto err;
1868           }
1869 
1870           /*
1871            * If the input is a seekable file, see if it is an interpreter file.
1872            * If we see #!, seek past the first line because cpp will choke on it.
1873            * We start cpp just prior to the \n at the end of this line so that
1874            * it still sees the newline, ensuring that #line values are correct.
1875            */
1876           if (isatty(fileno(ifp)) == 0 && (off = ftello64(ifp)) != -1) {
1877                     if ((c = fgetc(ifp)) == '#' && (c = fgetc(ifp)) == '!') {
1878                               for (off += 2; c != '\n'; off++) {
1879                                         if ((c = fgetc(ifp)) == EOF)
1880                                                   break;
1881                               }
1882                               if (c == '\n')
1883                                         off--; /* start cpp just prior to \n */
1884                     }
1885                     (void) fflush(ifp);
1886                     (void) fseeko64(ifp, off, SEEK_SET);
1887           }
1888 
1889 #ifdef illumos
1890           (void) snprintf(ipath, sizeof (ipath), "/dev/fd/%d", fileno(ifp));
1891           (void) snprintf(opath, sizeof (opath), "/dev/fd/%d", fileno(ofp));
1892 #endif
1893 
1894           bcopy(dtp->dt_cpp_argv, argv, sizeof (char *) * argc);
1895 
1896           (void) snprintf(verdef, sizeof (verdef),
1897               "-D__SUNW_D_VERSION=0x%08x", dtp->dt_vmax);
1898           argv[argc++] = verdef;
1899 
1900 #ifdef illumos
1901           switch (dtp->dt_stdcmode) {
1902           case DT_STDC_XA:
1903           case DT_STDC_XT:
1904                     argv[argc++] = "-D__STDC__=0";
1905                     break;
1906           case DT_STDC_XC:
1907                     argv[argc++] = "-D__STDC__=1";
1908                     break;
1909           }
1910 
1911           argv[argc++] = ipath;
1912           argv[argc++] = opath;
1913 #else
1914           argv[argc++] = "-P";
1915 #endif
1916           argv[argc] = NULL;
1917 
1918           /*
1919            * libdtrace must be able to be embedded in other programs that may
1920            * include application-specific signal handlers.  Therefore, if we
1921            * need to fork to run cpp(1), we must avoid generating a SIGCHLD
1922            * that could confuse the containing application.  To do this,
1923            * we block SIGCHLD and reset its disposition to SIG_DFL.
1924            * We restore our signal state once we are done.
1925            */
1926           (void) sigemptyset(&mask);
1927           (void) sigaddset(&mask, SIGCHLD);
1928           (void) sigprocmask(SIG_BLOCK, &mask, &omask);
1929 
1930           bzero(&act, sizeof (act));
1931           act.sa_handler = SIG_DFL;
1932           (void) sigaction(SIGCHLD, &act, &oact);
1933 
1934           if ((pid = fork1()) == -1) {
1935                     (void) sigaction(SIGCHLD, &oact, NULL);
1936                     (void) sigprocmask(SIG_SETMASK, &omask, NULL);
1937                     (void) dt_set_errno(dtp, EDT_CPPFORK);
1938                     goto err;
1939           }
1940 
1941           if (pid == 0) {
1942 #ifndef illumos
1943                     if (isatty(fileno(ifp)) == 0)
1944                               lseek(fileno(ifp), off, SEEK_SET);
1945                     dup2(fileno(ifp), 0);
1946                     dup2(fileno(ofp), 1);
1947 #endif
1948                     (void) execvp(dtp->dt_cpp_path, argv);
1949                     _exit(errno == ENOENT ? 127 : 126);
1950           }
1951 
1952           do {
1953                     dt_dprintf("waiting for %s (PID %d)\n", dtp->dt_cpp_path,
1954                         (int)pid);
1955           } while (waitpid(pid, &wstat, 0) == -1 && errno == EINTR);
1956 
1957           (void) sigaction(SIGCHLD, &oact, NULL);
1958           (void) sigprocmask(SIG_SETMASK, &omask, NULL);
1959 
1960           dt_dprintf("%s returned exit status 0x%x\n", dtp->dt_cpp_path, wstat);
1961           estat = WIFEXITED(wstat) ? WEXITSTATUS(wstat) : -1;
1962 
1963           if (estat != 0) {
1964                     switch (estat) {
1965                     case 126:
1966                               (void) dt_set_errno(dtp, EDT_CPPEXEC);
1967                               break;
1968                     case 127:
1969                               (void) dt_set_errno(dtp, EDT_CPPENT);
1970                               break;
1971                     default:
1972                               (void) dt_set_errno(dtp, EDT_CPPERR);
1973                     }
1974                     goto err;
1975           }
1976 
1977           free(argv);
1978           (void) fflush(ofp);
1979           (void) fseek(ofp, 0, SEEK_SET);
1980           return (ofp);
1981 
1982 err:
1983           free(argv);
1984           (void) fclose(ofp);
1985           return (NULL);
1986 }
1987 
1988 static void
dt_lib_depend_error(dtrace_hdl_t * dtp,const char * format,...)1989 dt_lib_depend_error(dtrace_hdl_t *dtp, const char *format, ...)
1990 {
1991           va_list ap;
1992 
1993           va_start(ap, format);
1994           dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
1995           va_end(ap);
1996 }
1997 
1998 int
dt_lib_depend_add(dtrace_hdl_t * dtp,dt_list_t * dlp,const char * arg)1999 dt_lib_depend_add(dtrace_hdl_t *dtp, dt_list_t *dlp, const char *arg)
2000 {
2001           dt_lib_depend_t *dld;
2002           const char *end;
2003 
2004           assert(arg != NULL);
2005 
2006           if ((end = strrchr(arg, '/')) == NULL)
2007                     return (dt_set_errno(dtp, EINVAL));
2008 
2009           if ((dld = dt_zalloc(dtp, sizeof (dt_lib_depend_t))) == NULL)
2010                     return (-1);
2011 
2012           if ((dld->dtld_libpath = dt_alloc(dtp, MAXPATHLEN)) == NULL) {
2013                     dt_free(dtp, dld);
2014                     return (-1);
2015           }
2016 
2017           (void) strlcpy(dld->dtld_libpath, arg, end - arg + 2);
2018           if ((dld->dtld_library = strdup(arg)) == NULL) {
2019                     dt_free(dtp, dld->dtld_libpath);
2020                     dt_free(dtp, dld);
2021                     return (dt_set_errno(dtp, EDT_NOMEM));
2022           }
2023 
2024           dt_list_append(dlp, dld);
2025           return (0);
2026 }
2027 
2028 dt_lib_depend_t *
dt_lib_depend_lookup(dt_list_t * dld,const char * arg)2029 dt_lib_depend_lookup(dt_list_t *dld, const char *arg)
2030 {
2031           dt_lib_depend_t *dldn;
2032 
2033           for (dldn = dt_list_next(dld); dldn != NULL;
2034               dldn = dt_list_next(dldn)) {
2035                     if (strcmp(dldn->dtld_library, arg) == 0)
2036                               return (dldn);
2037           }
2038 
2039           return (NULL);
2040 }
2041 
2042 /*
2043  * Go through all the library files, and, if any library dependencies exist for
2044  * that file, add it to that node's list of dependents. The result of this
2045  * will be a graph which can then be topologically sorted to produce a
2046  * compilation order.
2047  */
2048 static int
dt_lib_build_graph(dtrace_hdl_t * dtp)2049 dt_lib_build_graph(dtrace_hdl_t *dtp)
2050 {
2051           dt_lib_depend_t *dld, *dpld;
2052 
2053           for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
2054               dld = dt_list_next(dld)) {
2055                     char *library = dld->dtld_library;
2056 
2057                     for (dpld = dt_list_next(&dld->dtld_dependencies); dpld != NULL;
2058                         dpld = dt_list_next(dpld)) {
2059                               dt_lib_depend_t *dlda;
2060 
2061                               if ((dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep,
2062                                   dpld->dtld_library)) == NULL) {
2063                                         dt_lib_depend_error(dtp,
2064                                             "Invalid library dependency in %s: %s\n",
2065                                             dld->dtld_library, dpld->dtld_library);
2066 
2067                                         return (dt_set_errno(dtp, EDT_COMPILER));
2068                               }
2069 
2070                               if ((dt_lib_depend_add(dtp, &dlda->dtld_dependents,
2071                                   library)) != 0) {
2072                                         return (-1); /* preserve dt_errno */
2073                               }
2074                     }
2075           }
2076           return (0);
2077 }
2078 
2079 static int
dt_topo_sort(dtrace_hdl_t * dtp,dt_lib_depend_t * dld,int * count)2080 dt_topo_sort(dtrace_hdl_t *dtp, dt_lib_depend_t *dld, int *count)
2081 {
2082           dt_lib_depend_t *dpld, *dlda, *new;
2083 
2084           dld->dtld_start = ++(*count);
2085 
2086           for (dpld = dt_list_next(&dld->dtld_dependents); dpld != NULL;
2087               dpld = dt_list_next(dpld)) {
2088                     dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep,
2089                         dpld->dtld_library);
2090                     assert(dlda != NULL);
2091 
2092                     if (dlda->dtld_start == 0 &&
2093                         dt_topo_sort(dtp, dlda, count) == -1)
2094                               return (-1);
2095           }
2096 
2097           if ((new = dt_zalloc(dtp, sizeof (dt_lib_depend_t))) == NULL)
2098                     return (-1);
2099 
2100           if ((new->dtld_library = strdup(dld->dtld_library)) == NULL) {
2101                     dt_free(dtp, new);
2102                     return (dt_set_errno(dtp, EDT_NOMEM));
2103           }
2104 
2105           new->dtld_start = dld->dtld_start;
2106           new->dtld_finish = dld->dtld_finish = ++(*count);
2107           dt_list_prepend(&dtp->dt_lib_dep_sorted, new);
2108 
2109           dt_dprintf("library %s sorted (%d/%d)\n", new->dtld_library,
2110               new->dtld_start, new->dtld_finish);
2111 
2112           return (0);
2113 }
2114 
2115 static int
dt_lib_depend_sort(dtrace_hdl_t * dtp)2116 dt_lib_depend_sort(dtrace_hdl_t *dtp)
2117 {
2118           dt_lib_depend_t *dld, *dpld, *dlda;
2119           int count = 0;
2120 
2121           if (dt_lib_build_graph(dtp) == -1)
2122                     return (-1); /* preserve dt_errno */
2123 
2124           /*
2125            * Perform a topological sort of the graph that hangs off
2126            * dtp->dt_lib_dep. The result of this process will be a
2127            * dependency ordered list located at dtp->dt_lib_dep_sorted.
2128            */
2129           for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
2130               dld = dt_list_next(dld)) {
2131                     if (dld->dtld_start == 0 &&
2132                         dt_topo_sort(dtp, dld, &count) == -1)
2133                               return (-1); /* preserve dt_errno */;
2134           }
2135 
2136           /*
2137            * Check the graph for cycles. If an ancestor's finishing time is
2138            * less than any of its dependent's finishing times then a back edge
2139            * exists in the graph and this is a cycle.
2140            */
2141           for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
2142               dld = dt_list_next(dld)) {
2143                     for (dpld = dt_list_next(&dld->dtld_dependents); dpld != NULL;
2144                         dpld = dt_list_next(dpld)) {
2145                               dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep_sorted,
2146                                   dpld->dtld_library);
2147                               assert(dlda != NULL);
2148 
2149                               if (dlda->dtld_finish > dld->dtld_finish) {
2150                                         dt_lib_depend_error(dtp,
2151                                             "Cyclic dependency detected: %s => %s\n",
2152                                             dld->dtld_library, dpld->dtld_library);
2153 
2154                                         return (dt_set_errno(dtp, EDT_COMPILER));
2155                               }
2156                     }
2157           }
2158 
2159           return (0);
2160 }
2161 
2162 static void
dt_lib_depend_free(dtrace_hdl_t * dtp)2163 dt_lib_depend_free(dtrace_hdl_t *dtp)
2164 {
2165           dt_lib_depend_t *dld, *dlda;
2166 
2167           while ((dld = dt_list_next(&dtp->dt_lib_dep)) != NULL) {
2168                     while ((dlda = dt_list_next(&dld->dtld_dependencies)) != NULL) {
2169                               dt_list_delete(&dld->dtld_dependencies, dlda);
2170                               dt_free(dtp, dlda->dtld_library);
2171                               dt_free(dtp, dlda->dtld_libpath);
2172                               dt_free(dtp, dlda);
2173                     }
2174                     while ((dlda = dt_list_next(&dld->dtld_dependents)) != NULL) {
2175                               dt_list_delete(&dld->dtld_dependents, dlda);
2176                               dt_free(dtp, dlda->dtld_library);
2177                               dt_free(dtp, dlda->dtld_libpath);
2178                               dt_free(dtp, dlda);
2179                     }
2180                     dt_list_delete(&dtp->dt_lib_dep, dld);
2181                     dt_free(dtp, dld->dtld_library);
2182                     dt_free(dtp, dld->dtld_libpath);
2183                     dt_free(dtp, dld);
2184           }
2185 
2186           while ((dld = dt_list_next(&dtp->dt_lib_dep_sorted)) != NULL) {
2187                     dt_list_delete(&dtp->dt_lib_dep_sorted, dld);
2188                     dt_free(dtp, dld->dtld_library);
2189                     dt_free(dtp, dld);
2190           }
2191 }
2192 
2193 /*
2194  * Open all the .d library files found in the specified directory and
2195  * compile each one of them.  We silently ignore any missing directories and
2196  * other files found therein.  We only fail (and thereby fail dt_load_libs()) if
2197  * we fail to compile a library and the error is something other than #pragma D
2198  * depends_on.  Dependency errors are silently ignored to permit a library
2199  * directory to contain libraries which may not be accessible depending on our
2200  * privileges.
2201  */
2202 static int
dt_load_libs_dir(dtrace_hdl_t * dtp,const char * path)2203 dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
2204 {
2205           struct dirent *dp;
2206           const char *p, *end;
2207           DIR *dirp;
2208 
2209           char fname[PATH_MAX];
2210           FILE *fp;
2211           void *rv;
2212           dt_lib_depend_t *dld;
2213 
2214           if ((dirp = opendir(path)) == NULL) {
2215                     dt_dprintf("skipping lib dir %s: %s\n", path, strerror(errno));
2216                     return (0);
2217           }
2218 
2219           /* First, parse each file for library dependencies. */
2220           while ((dp = readdir(dirp)) != NULL) {
2221                     if ((p = strrchr(dp->d_name, '.')) == NULL || strcmp(p, ".d"))
2222                               continue; /* skip any filename not ending in .d */
2223 
2224                     (void) snprintf(fname, sizeof (fname),
2225                         "%s/%s", path, dp->d_name);
2226 
2227                     if ((fp = fopen(fname, "r")) == NULL) {
2228                               dt_dprintf("skipping library %s: %s\n",
2229                                   fname, strerror(errno));
2230                               continue;
2231                     }
2232 
2233                     /*
2234                      * Skip files whose name match an already processed library
2235                      */
2236                     for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
2237                         dld = dt_list_next(dld)) {
2238                               end = strrchr(dld->dtld_library, '/');
2239                               /* dt_lib_depend_add ensures this */
2240                               assert(end != NULL);
2241                               if (strcmp(end + 1, dp->d_name) == 0)
2242                                         break;
2243                     }
2244 
2245                     if (dld != NULL) {
2246                               dt_dprintf("skipping library %s, already processed "
2247                                   "library with the same name: %s", dp->d_name,
2248                                   dld->dtld_library);
2249                               (void) fclose(fp);
2250                               continue;
2251                     }
2252 
2253                     dtp->dt_filetag = fname;
2254                     if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0) {
2255                               (void) fclose(fp);
2256                               return (-1); /* preserve dt_errno */
2257                     }
2258 
2259                     rv = dt_compile(dtp, DT_CTX_DPROG,
2260                         DTRACE_PROBESPEC_NAME, NULL,
2261                         DTRACE_C_EMPTY | DTRACE_C_CTL, 0, NULL, fp, NULL);
2262 
2263                     if (rv != NULL && dtp->dt_errno &&
2264                         (dtp->dt_errno != EDT_COMPILER ||
2265                         dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND))) {
2266                               (void) fclose(fp);
2267                               return (-1); /* preserve dt_errno */
2268                     }
2269 
2270                     if (dtp->dt_errno)
2271                               dt_dprintf("error parsing library %s: %s\n",
2272                                   fname, dtrace_errmsg(dtp, dtrace_errno(dtp)));
2273 
2274                     (void) fclose(fp);
2275                     dtp->dt_filetag = NULL;
2276           }
2277 
2278           (void) closedir(dirp);
2279 
2280           return (0);
2281 }
2282 
2283 /*
2284  * Perform a topological sorting of all the libraries found across the entire
2285  * dt_lib_path.  Once sorted, compile each one in topological order to cache its
2286  * inlines and translators, etc.  We silently ignore any missing directories and
2287  * other files found therein. We only fail (and thereby fail dt_load_libs()) if
2288  * we fail to compile a library and the error is something other than #pragma D
2289  * depends_on.  Dependency errors are silently ignored to permit a library
2290  * directory to contain libraries which may not be accessible depending on our
2291  * privileges.
2292  */
2293 static int
dt_load_libs_sort(dtrace_hdl_t * dtp)2294 dt_load_libs_sort(dtrace_hdl_t *dtp)
2295 {
2296           dtrace_prog_t *pgp;
2297           FILE *fp;
2298           dt_lib_depend_t *dld;
2299 
2300           /*
2301            * Finish building the graph containing the library dependencies
2302            * and perform a topological sort to generate an ordered list
2303            * for compilation.
2304            */
2305           if (dt_lib_depend_sort(dtp) == -1)
2306                     goto err;
2307 
2308           for (dld = dt_list_next(&dtp->dt_lib_dep_sorted); dld != NULL;
2309               dld = dt_list_next(dld)) {
2310 
2311                     if ((fp = fopen(dld->dtld_library, "r")) == NULL) {
2312                               dt_dprintf("skipping library %s: %s\n",
2313                                   dld->dtld_library, strerror(errno));
2314                               continue;
2315                     }
2316 
2317                     dtp->dt_filetag = dld->dtld_library;
2318                     pgp = dtrace_program_fcompile(dtp, fp, DTRACE_C_EMPTY, 0, NULL);
2319                     (void) fclose(fp);
2320                     dtp->dt_filetag = NULL;
2321 
2322                     if (pgp == NULL && (dtp->dt_errno != EDT_COMPILER ||
2323                         dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND)))
2324                               goto err;
2325 
2326                     if (pgp == NULL) {
2327                               dt_dprintf("skipping library %s: %s\n",
2328                                   dld->dtld_library,
2329                                   dtrace_errmsg(dtp, dtrace_errno(dtp)));
2330                     } else {
2331                               dld->dtld_loaded = B_TRUE;
2332                               dt_program_destroy(dtp, pgp);
2333                     }
2334           }
2335 
2336           dt_lib_depend_free(dtp);
2337           return (0);
2338 
2339 err:
2340           dt_lib_depend_free(dtp);
2341           return (-1); /* preserve dt_errno */
2342 }
2343 
2344 /*
2345  * Load the contents of any appropriate DTrace .d library files.  These files
2346  * contain inlines and translators that will be cached by the compiler.  We
2347  * defer this activity until the first compile to permit libdtrace clients to
2348  * add their own library directories and so that we can properly report errors.
2349  */
2350 static int
dt_load_libs(dtrace_hdl_t * dtp)2351 dt_load_libs(dtrace_hdl_t *dtp)
2352 {
2353           dt_dirpath_t *dirp;
2354 
2355           if (dtp->dt_cflags & DTRACE_C_NOLIBS)
2356                     return (0); /* libraries already processed */
2357 
2358           dtp->dt_cflags |= DTRACE_C_NOLIBS;
2359 
2360           /*
2361            * /usr/lib/dtrace is always at the head of the list. The rest of the
2362            * list is specified in the precedence order the user requested. Process
2363            * everything other than the head first. DTRACE_C_NOLIBS has already
2364            * been spcified so dt_vopen will ensure that there is always one entry
2365            * in dt_lib_path.
2366            */
2367           for (dirp = dt_list_next(dt_list_next(&dtp->dt_lib_path));
2368               dirp != NULL; dirp = dt_list_next(dirp)) {
2369                     if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) {
2370                               dtp->dt_cflags &= ~DTRACE_C_NOLIBS;
2371                               return (-1); /* errno is set for us */
2372                     }
2373           }
2374 
2375           /* Handle /usr/lib/dtrace */
2376           dirp = dt_list_next(&dtp->dt_lib_path);
2377           if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) {
2378                     dtp->dt_cflags &= ~DTRACE_C_NOLIBS;
2379                     return (-1); /* errno is set for us */
2380           }
2381 
2382           if (dt_load_libs_sort(dtp) < 0)
2383                     return (-1); /* errno is set for us */
2384 
2385           return (0);
2386 }
2387 
2388 static void *
dt_compile(dtrace_hdl_t * dtp,int context,dtrace_probespec_t pspec,void * arg,uint_t cflags,int argc,char * const argv[],FILE * fp,const char * s)2389 dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg,
2390     uint_t cflags, int argc, char *const argv[], FILE *fp, const char *s)
2391 {
2392           dt_node_t *dnp;
2393           dt_decl_t *ddp;
2394           dt_pcb_t pcb;
2395           void *volatile rv;
2396           int err;
2397 
2398           if ((fp == NULL && s == NULL) || (cflags & ~DTRACE_C_MASK) != 0) {
2399                     (void) dt_set_errno(dtp, EINVAL);
2400                     return (NULL);
2401           }
2402 
2403           if (dt_list_next(&dtp->dt_lib_path) != NULL && dt_load_libs(dtp) != 0)
2404                     return (NULL); /* errno is set for us */
2405 
2406           if (dtp->dt_globals->dh_nelems != 0)
2407                     (void) dt_idhash_iter(dtp->dt_globals, dt_idreset, NULL);
2408 
2409           if (dtp->dt_tls->dh_nelems != 0)
2410                     (void) dt_idhash_iter(dtp->dt_tls, dt_idreset, NULL);
2411 
2412           if (fp && (cflags & DTRACE_C_CPP) && (fp = dt_preproc(dtp, fp)) == NULL)
2413                     return (NULL); /* errno is set for us */
2414 
2415           dt_pcb_push(dtp, &pcb);
2416 
2417           pcb.pcb_fileptr = fp;
2418           pcb.pcb_string = s;
2419           pcb.pcb_strptr = s;
2420           pcb.pcb_strlen = s ? strlen(s) : 0;
2421           pcb.pcb_sargc = argc;
2422           pcb.pcb_sargv = argv;
2423           pcb.pcb_sflagv = argc ? calloc(argc, sizeof (ushort_t)) : NULL;
2424           pcb.pcb_pspec = pspec;
2425           pcb.pcb_cflags = dtp->dt_cflags | cflags;
2426           pcb.pcb_amin = dtp->dt_amin;
2427           pcb.pcb_yystate = -1;
2428           pcb.pcb_context = context;
2429           pcb.pcb_token = context;
2430 
2431           if (context != DT_CTX_DPROG)
2432                     yybegin(YYS_EXPR);
2433           else if (cflags & DTRACE_C_CTL)
2434                     yybegin(YYS_CONTROL);
2435           else
2436                     yybegin(YYS_CLAUSE);
2437 
2438           if ((err = setjmp(yypcb->pcb_jmpbuf)) != 0)
2439                     goto out;
2440 
2441           if (yypcb->pcb_sargc != 0 && yypcb->pcb_sflagv == NULL)
2442                     longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
2443 
2444           yypcb->pcb_idents = dt_idhash_create("ambiguous", NULL, 0, 0);
2445           yypcb->pcb_locals = dt_idhash_create("clause local", NULL,
2446               DIF_VAR_OTHER_UBASE, DIF_VAR_OTHER_MAX);
2447 
2448           if (yypcb->pcb_idents == NULL || yypcb->pcb_locals == NULL)
2449                     longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
2450 
2451           /*
2452            * Invoke the parser to evaluate the D source code.  If any errors
2453            * occur during parsing, an error function will be called and we
2454            * will longjmp back to pcb_jmpbuf to abort.  If parsing succeeds,
2455            * we optionally display the parse tree if debugging is enabled.
2456            */
2457           if (yyparse() != 0 || yypcb->pcb_root == NULL)
2458                     xyerror(D_EMPTY, "empty D program translation unit\n");
2459 
2460           yybegin(YYS_DONE);
2461 
2462           if (cflags & DTRACE_C_CTL)
2463                     goto out;
2464 
2465           if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 1))
2466                     dt_node_printr(yypcb->pcb_root, stderr, 0);
2467 
2468           if (yypcb->pcb_pragmas != NULL)
2469                     (void) dt_idhash_iter(yypcb->pcb_pragmas, dt_idpragma, NULL);
2470 
2471           if (argc > 1 && !(yypcb->pcb_cflags & DTRACE_C_ARGREF) &&
2472               !(yypcb->pcb_sflagv[argc - 1] & DT_IDFLG_REF)) {
2473                     xyerror(D_MACRO_UNUSED, "extraneous argument '%s' ($%d is "
2474                         "not referenced)\n", yypcb->pcb_sargv[argc - 1], argc - 1);
2475           }
2476 
2477           /*
2478            * Perform sugar transformations (for "if" / "else") and replace the
2479            * existing clause chain with the new one.
2480            */
2481           if (context == DT_CTX_DPROG) {
2482                     dt_node_t *dnp, *next_dnp;
2483                     dt_node_t *new_list = NULL;
2484 
2485                     for (dnp = yypcb->pcb_root->dn_list;
2486                         dnp != NULL; dnp = next_dnp) {
2487                               /* remove this node from the list */
2488                               next_dnp = dnp->dn_list;
2489                               dnp->dn_list = NULL;
2490 
2491                               if (dnp->dn_kind == DT_NODE_CLAUSE)
2492                                         dnp = dt_compile_sugar(dtp, dnp);
2493                               /* append node to the new list */
2494                               new_list = dt_node_link(new_list, dnp);
2495                     }
2496                     yypcb->pcb_root->dn_list = new_list;
2497           }
2498 
2499           /*
2500            * If we have successfully created a parse tree for a D program, loop
2501            * over the clauses and actions and instantiate the corresponding
2502            * libdtrace program.  If we are parsing a D expression, then we
2503            * simply run the code generator and assembler on the resulting tree.
2504            */
2505           switch (context) {
2506           case DT_CTX_DPROG:
2507                     assert(yypcb->pcb_root->dn_kind == DT_NODE_PROG);
2508 
2509                     if ((dnp = yypcb->pcb_root->dn_list) == NULL &&
2510                         !(yypcb->pcb_cflags & DTRACE_C_EMPTY))
2511                               xyerror(D_EMPTY, "empty D program translation unit\n");
2512 
2513                     if ((yypcb->pcb_prog = dt_program_create(dtp)) == NULL)
2514                               longjmp(yypcb->pcb_jmpbuf, dtrace_errno(dtp));
2515 
2516                     for (; dnp != NULL; dnp = dnp->dn_list) {
2517                               switch (dnp->dn_kind) {
2518                               case DT_NODE_CLAUSE:
2519                                         if (DT_TREEDUMP_PASS(dtp, 4))
2520                                                   dt_printd(dnp, stderr, 0);
2521                                         dt_compile_clause(dtp, dnp);
2522                                         break;
2523                               case DT_NODE_XLATOR:
2524                                         if (dtp->dt_xlatemode == DT_XL_DYNAMIC)
2525                                                   dt_compile_xlator(dnp);
2526                                         break;
2527                               case DT_NODE_PROVIDER:
2528                                         (void) dt_node_cook(dnp, DT_IDFLG_REF);
2529                                         break;
2530                               }
2531                     }
2532 
2533                     yypcb->pcb_prog->dp_xrefs = yypcb->pcb_asxrefs;
2534                     yypcb->pcb_prog->dp_xrefslen = yypcb->pcb_asxreflen;
2535                     yypcb->pcb_asxrefs = NULL;
2536                     yypcb->pcb_asxreflen = 0;
2537 
2538                     rv = yypcb->pcb_prog;
2539                     break;
2540 
2541           case DT_CTX_DEXPR:
2542                     (void) dt_node_cook(yypcb->pcb_root, DT_IDFLG_REF);
2543                     dt_cg(yypcb, yypcb->pcb_root);
2544                     rv = dt_as(yypcb);
2545                     break;
2546 
2547           case DT_CTX_DTYPE:
2548                     ddp = (dt_decl_t *)yypcb->pcb_root; /* root is really a decl */
2549                     err = dt_decl_type(ddp, arg);
2550                     dt_decl_free(ddp);
2551 
2552                     if (err != 0)
2553                               longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
2554 
2555                     rv = NULL;
2556                     break;
2557           }
2558 
2559 out:
2560           if (context != DT_CTX_DTYPE && yypcb->pcb_root != NULL &&
2561               DT_TREEDUMP_PASS(dtp, 3))
2562                     dt_node_printr(yypcb->pcb_root, stderr, 0);
2563 
2564           if (dtp->dt_cdefs_fd != -1 && (ftruncate64(dtp->dt_cdefs_fd, 0) == -1 ||
2565               lseek64(dtp->dt_cdefs_fd, 0, SEEK_SET) == -1 ||
2566               ctf_write(dtp->dt_cdefs->dm_ctfp, dtp->dt_cdefs_fd) == CTF_ERR))
2567                     dt_dprintf("failed to update CTF cache: %s\n", strerror(errno));
2568 
2569           if (dtp->dt_ddefs_fd != -1 && (ftruncate64(dtp->dt_ddefs_fd, 0) == -1 ||
2570               lseek64(dtp->dt_ddefs_fd, 0, SEEK_SET) == -1 ||
2571               ctf_write(dtp->dt_ddefs->dm_ctfp, dtp->dt_ddefs_fd) == CTF_ERR))
2572                     dt_dprintf("failed to update CTF cache: %s\n", strerror(errno));
2573 
2574           if (yypcb->pcb_fileptr && (cflags & DTRACE_C_CPP))
2575                     (void) fclose(yypcb->pcb_fileptr); /* close dt_preproc() file */
2576 
2577           dt_pcb_pop(dtp, err);
2578           (void) dt_set_errno(dtp, err);
2579           return (err ? NULL : rv);
2580 }
2581 
2582 dtrace_prog_t *
dtrace_program_strcompile(dtrace_hdl_t * dtp,const char * s,dtrace_probespec_t spec,uint_t cflags,int argc,char * const argv[])2583 dtrace_program_strcompile(dtrace_hdl_t *dtp, const char *s,
2584     dtrace_probespec_t spec, uint_t cflags, int argc, char *const argv[])
2585 {
2586           return (dt_compile(dtp, DT_CTX_DPROG,
2587               spec, NULL, cflags, argc, argv, NULL, s));
2588 }
2589 
2590 dtrace_prog_t *
dtrace_program_fcompile(dtrace_hdl_t * dtp,FILE * fp,uint_t cflags,int argc,char * const argv[])2591 dtrace_program_fcompile(dtrace_hdl_t *dtp, FILE *fp,
2592     uint_t cflags, int argc, char *const argv[])
2593 {
2594           return (dt_compile(dtp, DT_CTX_DPROG,
2595               DTRACE_PROBESPEC_NAME, NULL, cflags, argc, argv, fp, NULL));
2596 }
2597 
2598 int
dtrace_type_strcompile(dtrace_hdl_t * dtp,const char * s,dtrace_typeinfo_t * dtt)2599 dtrace_type_strcompile(dtrace_hdl_t *dtp, const char *s, dtrace_typeinfo_t *dtt)
2600 {
2601           (void) dt_compile(dtp, DT_CTX_DTYPE,
2602               DTRACE_PROBESPEC_NONE, dtt, 0, 0, NULL, NULL, s);
2603           return (dtp->dt_errno ? -1 : 0);
2604 }
2605 
2606 int
dtrace_type_fcompile(dtrace_hdl_t * dtp,FILE * fp,dtrace_typeinfo_t * dtt)2607 dtrace_type_fcompile(dtrace_hdl_t *dtp, FILE *fp, dtrace_typeinfo_t *dtt)
2608 {
2609           (void) dt_compile(dtp, DT_CTX_DTYPE,
2610               DTRACE_PROBESPEC_NONE, dtt, 0, 0, NULL, fp, NULL);
2611           return (dtp->dt_errno ? -1 : 0);
2612 }
2613