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.
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.
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]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, Joyent Inc. All rights reserved.
28 * DTrace D Language Compiler
30 * The code in this source file implements the main engine for the D language
31 * compiler. The driver routine for the compiler is dt_compile(), below. The
32 * compiler operates on either stdio FILEs or in-memory strings as its input
33 * and can produce either dtrace_prog_t structures from a D program or a single
34 * dtrace_difo_t structure from a D expression. Multiple entry points are
35 * provided as wrappers around dt_compile() for the various input/output pairs.
36 * The compiler itself is implemented across the following source files:
38 * dt_lex.l - lex scanner
39 * dt_grammar.y - yacc grammar
40 * dt_parser.c - parse tree creation and semantic checking
41 * dt_decl.c - declaration stack processing
42 * dt_xlator.c - D translator lookup and creation
43 * dt_ident.c - identifier and symbol table routines
44 * dt_pragma.c - #pragma processing and D pragmas
45 * dt_printf.c - D printf() and printa() argument checking and processing
46 * dt_cc.c - compiler driver and dtrace_prog_t construction
47 * dt_cg.c - DIF code generator
48 * dt_as.c - DIF assembler
49 * dt_dof.c - dtrace_prog_t -> DOF conversion
51 * Several other source files provide collections of utility routines used by
52 * these major files. The compiler itself is implemented in multiple passes:
54 * (1) The input program is scanned and parsed by dt_lex.l and dt_grammar.y
55 * and parse tree nodes are constructed using the routines in dt_parser.c.
56 * This node construction pass is described further in dt_parser.c.
58 * (2) The parse tree is "cooked" by assigning each clause a context (see the
59 * routine dt_setcontext(), below) based on its probe description and then
60 * recursively descending the tree performing semantic checking. The cook
61 * routines are also implemented in dt_parser.c and described there.
63 * (3) For actions that are DIF expression statements, the DIF code generator
64 * and assembler are invoked to create a finished DIFO for the statement.
66 * (4) The dtrace_prog_t data structures for the program clauses and actions
67 * are built, containing pointers to any DIFOs created in step (3).
69 * (5) The caller invokes a routine in dt_dof.c to convert the finished program
70 * into DOF format for use in anonymous tracing or enabling in the kernel.
72 * In the implementation, steps 2-4 are intertwined in that they are performed
73 * in order for each clause as part of a loop that executes over the clauses.
75 * The D compiler currently implements nearly no optimization. The compiler
76 * implements integer constant folding as part of pass (1), and a set of very
77 * simple peephole optimizations as part of pass (3). As with any C compiler,
78 * a large number of optimizations are possible on both the intermediate data
79 * structures and the generated DIF code. These possibilities should be
80 * investigated in the context of whether they will have any substantive effect
81 * on the overall DTrace probe effect before they are undertaken.
84 #include <sys/types.h>
98 #include <dt_module.h>
99 #include <dt_program.h>
100 #include <dt_provider.h>
101 #include <dt_printf.h>
103 #include <dt_grammar.h>
104 #include <dt_ident.h>
105 #include <dt_string.h>
108 static const dtrace_diftype_t dt_void_rtype
= {
109 DIF_TYPE_CTF
, CTF_K_INTEGER
, 0, 0, 0
112 static const dtrace_diftype_t dt_int_rtype
= {
113 DIF_TYPE_CTF
, CTF_K_INTEGER
, 0, 0, sizeof (uint64_t)
116 static void *dt_compile(dtrace_hdl_t
*, int, dtrace_probespec_t
, void *,
117 uint_t
, int, char *const[], FILE *, const char *);
122 dt_idreset(dt_idhash_t
*dhp
, dt_ident_t
*idp
, void *ignored
)
124 idp
->di_flags
&= ~(DT_IDFLG_REF
| DT_IDFLG_MOD
|
125 DT_IDFLG_DIFR
| DT_IDFLG_DIFW
);
131 dt_idpragma(dt_idhash_t
*dhp
, dt_ident_t
*idp
, void *ignored
)
133 yylineno
= idp
->di_lineno
;
134 xyerror(D_PRAGMA_UNUSED
, "unused #pragma %s\n", (char *)idp
->di_iarg
);
138 static dtrace_stmtdesc_t
*
139 dt_stmt_create(dtrace_hdl_t
*dtp
, dtrace_ecbdesc_t
*edp
,
140 dtrace_attribute_t descattr
, dtrace_attribute_t stmtattr
)
142 dtrace_stmtdesc_t
*sdp
= dtrace_stmt_create(dtp
, edp
);
145 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
147 assert(yypcb
->pcb_stmt
== NULL
);
148 yypcb
->pcb_stmt
= sdp
;
150 sdp
->dtsd_descattr
= descattr
;
151 sdp
->dtsd_stmtattr
= stmtattr
;
156 static dtrace_actdesc_t
*
157 dt_stmt_action(dtrace_hdl_t
*dtp
, dtrace_stmtdesc_t
*sdp
)
159 dtrace_actdesc_t
*new;
161 if ((new = dtrace_stmt_action(dtp
, sdp
)) == NULL
)
162 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
168 * Utility function to determine if a given action description is destructive.
169 * The dtdo_destructive bit is set for us by the DIF assembler (see dt_as.c).
172 dt_action_destructive(const dtrace_actdesc_t
*ap
)
174 return (DTRACEACT_ISDESTRUCTIVE(ap
->dtad_kind
) || (ap
->dtad_kind
==
175 DTRACEACT_DIFEXPR
&& ap
->dtad_difo
->dtdo_destructive
));
179 dt_stmt_append(dtrace_stmtdesc_t
*sdp
, const dt_node_t
*dnp
)
181 dtrace_ecbdesc_t
*edp
= sdp
->dtsd_ecbdesc
;
182 dtrace_actdesc_t
*ap
, *tap
;
188 * Make sure that the new statement jibes with the rest of the ECB.
190 for (ap
= edp
->dted_action
; ap
!= NULL
; ap
= ap
->dtad_next
) {
191 if (ap
->dtad_kind
== DTRACEACT_COMMIT
) {
193 dnerror(dnp
, D_COMM_COMM
, "commit( ) may "
194 "not follow commit( )\n");
198 dnerror(dnp
, D_COMM_DREC
, "commit( ) may "
199 "not follow data-recording action(s)\n");
202 for (tap
= ap
; tap
!= NULL
; tap
= tap
->dtad_next
) {
203 if (!DTRACEACT_ISAGG(tap
->dtad_kind
))
206 dnerror(dnp
, D_AGG_COMM
, "aggregating actions "
207 "may not follow commit( )\n");
214 if (ap
->dtad_kind
== DTRACEACT_SPECULATE
) {
216 dnerror(dnp
, D_SPEC_SPEC
, "speculate( ) may "
217 "not follow speculate( )\n");
221 dnerror(dnp
, D_SPEC_COMM
, "speculate( ) may "
222 "not follow commit( )\n");
226 dnerror(dnp
, D_SPEC_DREC
, "speculate( ) may "
227 "not follow data-recording action(s)\n");
234 if (DTRACEACT_ISAGG(ap
->dtad_kind
)) {
236 dnerror(dnp
, D_AGG_SPEC
, "aggregating actions "
237 "may not follow speculate( )\n");
245 if (dt_action_destructive(ap
)) {
246 dnerror(dnp
, D_ACT_SPEC
, "destructive actions "
247 "may not follow speculate( )\n");
250 if (ap
->dtad_kind
== DTRACEACT_EXIT
) {
251 dnerror(dnp
, D_EXIT_SPEC
, "exit( ) may not "
252 "follow speculate( )\n");
257 * Exclude all non data-recording actions.
259 if (dt_action_destructive(ap
) ||
260 ap
->dtad_kind
== DTRACEACT_DISCARD
)
263 if (ap
->dtad_kind
== DTRACEACT_DIFEXPR
&&
264 ap
->dtad_difo
->dtdo_rtype
.dtdt_kind
== DIF_TYPE_CTF
&&
265 ap
->dtad_difo
->dtdo_rtype
.dtdt_size
== 0)
269 dnerror(dnp
, D_DREC_COMM
, "data-recording actions "
270 "may not follow commit( )\n");
277 if (dtrace_stmt_add(yypcb
->pcb_hdl
, yypcb
->pcb_prog
, sdp
) != 0)
278 longjmp(yypcb
->pcb_jmpbuf
, dtrace_errno(yypcb
->pcb_hdl
));
280 if (yypcb
->pcb_stmt
== sdp
)
281 yypcb
->pcb_stmt
= NULL
;
285 * For the first element of an aggregation tuple or for printa(), we create a
286 * simple DIF program that simply returns the immediate value that is the ID
287 * of the aggregation itself. This could be optimized in the future by
288 * creating a new in-kernel dtad_kind that just returns an integer.
291 dt_action_difconst(dtrace_actdesc_t
*ap
, uint_t id
, dtrace_actkind_t kind
)
293 dtrace_hdl_t
*dtp
= yypcb
->pcb_hdl
;
294 dtrace_difo_t
*dp
= dt_zalloc(dtp
, sizeof (dtrace_difo_t
));
297 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
299 dp
->dtdo_buf
= dt_alloc(dtp
, sizeof (dif_instr_t
) * 2);
300 dp
->dtdo_inttab
= dt_alloc(dtp
, sizeof (uint64_t));
302 if (dp
->dtdo_buf
== NULL
|| dp
->dtdo_inttab
== NULL
) {
303 dt_difo_free(dtp
, dp
);
304 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
307 dp
->dtdo_buf
[0] = DIF_INSTR_SETX(0, 1); /* setx DIF_INTEGER[0], %r1 */
308 dp
->dtdo_buf
[1] = DIF_INSTR_RET(1); /* ret %r1 */
310 dp
->dtdo_inttab
[0] = id
;
312 dp
->dtdo_rtype
= dt_int_rtype
;
315 ap
->dtad_kind
= kind
;
319 dt_action_clear(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
322 dtrace_actdesc_t
*ap
;
325 char n
[DT_TYPE_NAMELEN
];
328 for (anp
= dnp
->dn_args
; anp
!= NULL
; anp
= anp
->dn_list
)
329 argc
++; /* count up arguments for error messages below */
332 dnerror(dnp
, D_CLEAR_PROTO
,
333 "%s( ) prototype mismatch: %d args passed, 1 expected\n",
334 dnp
->dn_ident
->di_name
, argc
);
340 if (anp
->dn_kind
!= DT_NODE_AGG
) {
341 dnerror(dnp
, D_CLEAR_AGGARG
,
342 "%s( ) argument #1 is incompatible with prototype:\n"
343 "\tprototype: aggregation\n\t argument: %s\n",
344 dnp
->dn_ident
->di_name
,
345 dt_node_type_name(anp
, n
, sizeof (n
)));
350 if (aid
->di_gen
== dtp
->dt_gen
&& !(aid
->di_flags
& DT_IDFLG_MOD
)) {
351 dnerror(dnp
, D_CLEAR_AGGBAD
,
352 "undefined aggregation: @%s\n", aid
->di_name
);
355 ap
= dt_stmt_action(dtp
, sdp
);
356 dt_action_difconst(ap
, anp
->dn_ident
->di_id
, DTRACEACT_LIBACT
);
357 ap
->dtad_arg
= DT_ACT_CLEAR
;
361 dt_action_normalize(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
364 dtrace_actdesc_t
*ap
;
365 dt_node_t
*anp
, *normal
;
366 int denormal
= (strcmp(dnp
->dn_ident
->di_name
, "denormalize") == 0);
368 char n
[DT_TYPE_NAMELEN
];
371 for (anp
= dnp
->dn_args
; anp
!= NULL
; anp
= anp
->dn_list
)
372 argc
++; /* count up arguments for error messages below */
374 if ((denormal
&& argc
!= 1) || (!denormal
&& argc
!= 2)) {
375 dnerror(dnp
, D_NORMALIZE_PROTO
,
376 "%s( ) prototype mismatch: %d args passed, %d expected\n",
377 dnp
->dn_ident
->di_name
, argc
, denormal
? 1 : 2);
383 if (anp
->dn_kind
!= DT_NODE_AGG
) {
384 dnerror(dnp
, D_NORMALIZE_AGGARG
,
385 "%s( ) argument #1 is incompatible with prototype:\n"
386 "\tprototype: aggregation\n\t argument: %s\n",
387 dnp
->dn_ident
->di_name
,
388 dt_node_type_name(anp
, n
, sizeof (n
)));
391 if ((normal
= anp
->dn_list
) != NULL
&& !dt_node_is_scalar(normal
)) {
392 dnerror(dnp
, D_NORMALIZE_SCALAR
,
393 "%s( ) argument #2 must be of scalar type\n",
394 dnp
->dn_ident
->di_name
);
399 if (aid
->di_gen
== dtp
->dt_gen
&& !(aid
->di_flags
& DT_IDFLG_MOD
)) {
400 dnerror(dnp
, D_NORMALIZE_AGGBAD
,
401 "undefined aggregation: @%s\n", aid
->di_name
);
404 ap
= dt_stmt_action(dtp
, sdp
);
405 dt_action_difconst(ap
, anp
->dn_ident
->di_id
, DTRACEACT_LIBACT
);
408 ap
->dtad_arg
= DT_ACT_DENORMALIZE
;
412 ap
->dtad_arg
= DT_ACT_NORMALIZE
;
414 assert(normal
!= NULL
);
415 ap
= dt_stmt_action(dtp
, sdp
);
416 dt_cg(yypcb
, normal
);
418 ap
->dtad_difo
= dt_as(yypcb
);
419 ap
->dtad_kind
= DTRACEACT_LIBACT
;
420 ap
->dtad_arg
= DT_ACT_NORMALIZE
;
424 dt_action_trunc(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
427 dtrace_actdesc_t
*ap
;
428 dt_node_t
*anp
, *trunc
;
430 char n
[DT_TYPE_NAMELEN
];
433 for (anp
= dnp
->dn_args
; anp
!= NULL
; anp
= anp
->dn_list
)
434 argc
++; /* count up arguments for error messages below */
436 if (argc
> 2 || argc
< 1) {
437 dnerror(dnp
, D_TRUNC_PROTO
,
438 "%s( ) prototype mismatch: %d args passed, %s expected\n",
439 dnp
->dn_ident
->di_name
, argc
,
440 argc
< 1 ? "at least 1" : "no more than 2");
445 trunc
= anp
->dn_list
;
447 if (anp
->dn_kind
!= DT_NODE_AGG
) {
448 dnerror(dnp
, D_TRUNC_AGGARG
,
449 "%s( ) argument #1 is incompatible with prototype:\n"
450 "\tprototype: aggregation\n\t argument: %s\n",
451 dnp
->dn_ident
->di_name
,
452 dt_node_type_name(anp
, n
, sizeof (n
)));
456 assert(trunc
!= NULL
);
457 if (!dt_node_is_scalar(trunc
)) {
458 dnerror(dnp
, D_TRUNC_SCALAR
,
459 "%s( ) argument #2 must be of scalar type\n",
460 dnp
->dn_ident
->di_name
);
466 if (aid
->di_gen
== dtp
->dt_gen
&& !(aid
->di_flags
& DT_IDFLG_MOD
)) {
467 dnerror(dnp
, D_TRUNC_AGGBAD
,
468 "undefined aggregation: @%s\n", aid
->di_name
);
471 ap
= dt_stmt_action(dtp
, sdp
);
472 dt_action_difconst(ap
, anp
->dn_ident
->di_id
, DTRACEACT_LIBACT
);
473 ap
->dtad_arg
= DT_ACT_TRUNC
;
475 ap
= dt_stmt_action(dtp
, sdp
);
478 dt_action_difconst(ap
, 0, DTRACEACT_LIBACT
);
480 assert(trunc
!= NULL
);
482 ap
->dtad_difo
= dt_as(yypcb
);
483 ap
->dtad_kind
= DTRACEACT_LIBACT
;
486 ap
->dtad_arg
= DT_ACT_TRUNC
;
490 dt_action_printa(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
492 dt_ident_t
*aid
, *fid
;
493 dtrace_actdesc_t
*ap
;
495 dt_node_t
*anp
, *proto
= NULL
;
497 char n
[DT_TYPE_NAMELEN
];
498 int argc
= 0, argr
= 0;
500 for (anp
= dnp
->dn_args
; anp
!= NULL
; anp
= anp
->dn_list
)
501 argc
++; /* count up arguments for error messages below */
503 switch (dnp
->dn_args
->dn_kind
) {
505 format
= dnp
->dn_args
->dn_string
;
506 anp
= dnp
->dn_args
->dn_list
;
521 dnerror(dnp
, D_PRINTA_PROTO
,
522 "%s( ) prototype mismatch: %d args passed, %d expected\n",
523 dnp
->dn_ident
->di_name
, argc
, argr
);
528 while (anp
!= NULL
) {
529 if (anp
->dn_kind
!= DT_NODE_AGG
) {
530 dnerror(dnp
, D_PRINTA_AGGARG
,
531 "%s( ) argument #%d is incompatible with "
532 "prototype:\n\tprototype: aggregation\n"
533 "\t argument: %s\n", dnp
->dn_ident
->di_name
, argr
,
534 dt_node_type_name(anp
, n
, sizeof (n
)));
540 if (aid
->di_gen
== dtp
->dt_gen
&&
541 !(aid
->di_flags
& DT_IDFLG_MOD
)) {
542 dnerror(dnp
, D_PRINTA_AGGBAD
,
543 "undefined aggregation: @%s\n", aid
->di_name
);
547 * If we have multiple aggregations, we must be sure that
548 * their key signatures match.
551 dt_printa_validate(proto
, anp
);
556 if (format
!= NULL
) {
557 yylineno
= dnp
->dn_line
;
560 dt_printf_create(yypcb
->pcb_hdl
, format
);
561 dt_printf_validate(sdp
->dtsd_fmtdata
,
562 DT_PRINTF_AGGREGATION
, dnp
->dn_ident
, 1,
563 fid
->di_id
, ((dt_idsig_t
*)aid
->di_data
)->dis_args
);
567 ap
= dt_stmt_action(dtp
, sdp
);
568 dt_action_difconst(ap
, anp
->dn_ident
->di_id
, DTRACEACT_PRINTA
);
576 dt_action_printflike(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
,
577 dtrace_actkind_t kind
)
579 dt_node_t
*anp
, *arg1
;
580 dtrace_actdesc_t
*ap
= NULL
;
581 char n
[DT_TYPE_NAMELEN
], *str
;
583 assert(DTRACEACT_ISPRINTFLIKE(kind
));
585 if (dnp
->dn_args
->dn_kind
!= DT_NODE_STRING
) {
586 dnerror(dnp
, D_PRINTF_ARG_FMT
,
587 "%s( ) argument #1 is incompatible with prototype:\n"
588 "\tprototype: string constant\n\t argument: %s\n",
589 dnp
->dn_ident
->di_name
,
590 dt_node_type_name(dnp
->dn_args
, n
, sizeof (n
)));
593 arg1
= dnp
->dn_args
->dn_list
;
594 yylineno
= dnp
->dn_line
;
595 str
= dnp
->dn_args
->dn_string
;
599 * If this is an freopen(), we use an empty string to denote that
600 * stdout should be restored. For other printf()-like actions, an
601 * empty format string is illegal: an empty format string would
602 * result in malformed DOF, and the compiler thus flags an empty
603 * format string as a compile-time error. To avoid propagating the
604 * freopen() special case throughout the system, we simply transpose
605 * an empty string into a sentinel string (DT_FREOPEN_RESTORE) that
606 * denotes that stdout should be restored.
608 if (kind
== DTRACEACT_FREOPEN
) {
609 if (strcmp(str
, DT_FREOPEN_RESTORE
) == 0) {
611 * Our sentinel is always an invalid argument to
612 * freopen(), but if it's been manually specified, we
613 * must fail now instead of when the freopen() is
614 * actually evaluated.
616 dnerror(dnp
, D_FREOPEN_INVALID
,
617 "%s( ) argument #1 cannot be \"%s\"\n",
618 dnp
->dn_ident
->di_name
, DT_FREOPEN_RESTORE
);
622 str
= DT_FREOPEN_RESTORE
;
625 sdp
->dtsd_fmtdata
= dt_printf_create(dtp
, str
);
627 dt_printf_validate(sdp
->dtsd_fmtdata
, DT_PRINTF_EXACTLEN
,
628 dnp
->dn_ident
, 1, DTRACEACT_AGGREGATION
, arg1
);
634 if ((dbuf
= dt_alloc(dtp
, sizeof (dif_instr_t
))) == NULL
||
635 (dp
= dt_zalloc(dtp
, sizeof (dtrace_difo_t
))) == NULL
) {
637 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
640 dbuf
[0] = DIF_INSTR_RET(DIF_REG_R0
); /* ret %r0 */
644 dp
->dtdo_rtype
= dt_int_rtype
;
646 ap
= dt_stmt_action(dtp
, sdp
);
648 ap
->dtad_kind
= kind
;
652 for (anp
= arg1
; anp
!= NULL
; anp
= anp
->dn_list
) {
653 ap
= dt_stmt_action(dtp
, sdp
);
655 ap
->dtad_difo
= dt_as(yypcb
);
656 ap
->dtad_kind
= kind
;
661 dt_action_trace(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
663 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
665 if (dt_node_is_void(dnp
->dn_args
)) {
666 dnerror(dnp
->dn_args
, D_TRACE_VOID
,
667 "trace( ) may not be applied to a void expression\n");
670 if (dt_node_is_dynamic(dnp
->dn_args
)) {
671 dnerror(dnp
->dn_args
, D_TRACE_DYN
,
672 "trace( ) may not be applied to a dynamic expression\n");
675 dt_cg(yypcb
, dnp
->dn_args
);
676 ap
->dtad_difo
= dt_as(yypcb
);
677 ap
->dtad_kind
= DTRACEACT_DIFEXPR
;
681 dt_action_tracemem(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
683 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
685 dt_node_t
*addr
= dnp
->dn_args
;
686 dt_node_t
*size
= dnp
->dn_args
->dn_list
;
688 char n
[DT_TYPE_NAMELEN
];
690 if (dt_node_is_integer(addr
) == 0 && dt_node_is_pointer(addr
) == 0) {
691 dnerror(addr
, D_TRACEMEM_ADDR
,
692 "tracemem( ) argument #1 is incompatible with "
693 "prototype:\n\tprototype: pointer or integer\n"
695 dt_node_type_name(addr
, n
, sizeof (n
)));
698 if (dt_node_is_posconst(size
) == 0) {
699 dnerror(size
, D_TRACEMEM_SIZE
, "tracemem( ) argument #2 must "
700 "be a non-zero positive integral constant expression\n");
704 ap
->dtad_difo
= dt_as(yypcb
);
705 ap
->dtad_kind
= DTRACEACT_DIFEXPR
;
707 ap
->dtad_difo
->dtdo_rtype
.dtdt_flags
|= DIF_TF_BYREF
;
708 ap
->dtad_difo
->dtdo_rtype
.dtdt_size
= size
->dn_value
;
712 dt_action_stack_args(dtrace_hdl_t
*dtp
, dtrace_actdesc_t
*ap
, dt_node_t
*arg0
)
714 ap
->dtad_kind
= DTRACEACT_STACK
;
716 if (dtp
->dt_options
[DTRACEOPT_STACKFRAMES
] != DTRACEOPT_UNSET
) {
717 ap
->dtad_arg
= dtp
->dt_options
[DTRACEOPT_STACKFRAMES
];
723 if (arg0
->dn_list
!= NULL
) {
724 dnerror(arg0
, D_STACK_PROTO
, "stack( ) prototype "
725 "mismatch: too many arguments\n");
728 if (dt_node_is_posconst(arg0
) == 0) {
729 dnerror(arg0
, D_STACK_SIZE
, "stack( ) size must be a "
730 "non-zero positive integral constant expression\n");
733 ap
->dtad_arg
= arg0
->dn_value
;
738 dt_action_stack(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
740 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
741 dt_action_stack_args(dtp
, ap
, dnp
->dn_args
);
745 dt_action_ustack_args(dtrace_hdl_t
*dtp
, dtrace_actdesc_t
*ap
, dt_node_t
*dnp
)
747 uint32_t nframes
= 0;
748 uint32_t strsize
= 0; /* default string table size */
749 dt_node_t
*arg0
= dnp
->dn_args
;
750 dt_node_t
*arg1
= arg0
!= NULL
? arg0
->dn_list
: NULL
;
752 assert(dnp
->dn_ident
->di_id
== DT_ACT_JSTACK
||
753 dnp
->dn_ident
->di_id
== DT_ACT_USTACK
);
755 if (dnp
->dn_ident
->di_id
== DT_ACT_JSTACK
) {
756 if (dtp
->dt_options
[DTRACEOPT_JSTACKFRAMES
] != DTRACEOPT_UNSET
)
757 nframes
= dtp
->dt_options
[DTRACEOPT_JSTACKFRAMES
];
759 if (dtp
->dt_options
[DTRACEOPT_JSTACKSTRSIZE
] != DTRACEOPT_UNSET
)
760 strsize
= dtp
->dt_options
[DTRACEOPT_JSTACKSTRSIZE
];
762 ap
->dtad_kind
= DTRACEACT_JSTACK
;
764 assert(dnp
->dn_ident
->di_id
== DT_ACT_USTACK
);
766 if (dtp
->dt_options
[DTRACEOPT_USTACKFRAMES
] != DTRACEOPT_UNSET
)
767 nframes
= dtp
->dt_options
[DTRACEOPT_USTACKFRAMES
];
769 ap
->dtad_kind
= DTRACEACT_USTACK
;
773 if (!dt_node_is_posconst(arg0
)) {
774 dnerror(arg0
, D_USTACK_FRAMES
, "ustack( ) argument #1 "
775 "must be a non-zero positive integer constant\n");
777 nframes
= (uint32_t)arg0
->dn_value
;
781 if (arg1
->dn_kind
!= DT_NODE_INT
||
782 ((arg1
->dn_flags
& DT_NF_SIGNED
) &&
783 (int64_t)arg1
->dn_value
< 0)) {
784 dnerror(arg1
, D_USTACK_STRSIZE
, "ustack( ) argument #2 "
785 "must be a positive integer constant\n");
788 if (arg1
->dn_list
!= NULL
) {
789 dnerror(arg1
, D_USTACK_PROTO
, "ustack( ) prototype "
790 "mismatch: too many arguments\n");
793 strsize
= (uint32_t)arg1
->dn_value
;
796 ap
->dtad_arg
= DTRACE_USTACK_ARG(nframes
, strsize
);
800 dt_action_ustack(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
802 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
803 dt_action_ustack_args(dtp
, ap
, dnp
);
807 dt_action_setopt(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
809 dtrace_actdesc_t
*ap
;
810 dt_node_t
*arg0
, *arg1
;
813 * The prototype guarantees that we are called with either one or
814 * two arguments, and that any arguments that are present are strings.
817 arg1
= arg0
->dn_list
;
819 ap
= dt_stmt_action(dtp
, sdp
);
821 ap
->dtad_difo
= dt_as(yypcb
);
822 ap
->dtad_kind
= DTRACEACT_LIBACT
;
823 ap
->dtad_arg
= DT_ACT_SETOPT
;
825 ap
= dt_stmt_action(dtp
, sdp
);
828 dt_action_difconst(ap
, 0, DTRACEACT_LIBACT
);
831 ap
->dtad_difo
= dt_as(yypcb
);
832 ap
->dtad_kind
= DTRACEACT_LIBACT
;
835 ap
->dtad_arg
= DT_ACT_SETOPT
;
840 dt_action_symmod_args(dtrace_hdl_t
*dtp
, dtrace_actdesc_t
*ap
,
841 dt_node_t
*dnp
, dtrace_actkind_t kind
)
843 assert(kind
== DTRACEACT_SYM
|| kind
== DTRACEACT_MOD
||
844 kind
== DTRACEACT_USYM
|| kind
== DTRACEACT_UMOD
||
845 kind
== DTRACEACT_UADDR
);
848 ap
->dtad_difo
= dt_as(yypcb
);
849 ap
->dtad_kind
= kind
;
850 ap
->dtad_difo
->dtdo_rtype
.dtdt_size
= sizeof (uint64_t);
854 dt_action_symmod(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
,
855 dtrace_actkind_t kind
)
857 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
858 dt_action_symmod_args(dtp
, ap
, dnp
->dn_args
, kind
);
863 dt_action_ftruncate(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
865 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
868 * Library actions need a DIFO that serves as an argument. As
869 * ftruncate() doesn't take an argument, we generate the constant 0
870 * in a DIFO; this constant will be ignored when the ftruncate() is
873 dt_action_difconst(ap
, 0, DTRACEACT_LIBACT
);
874 ap
->dtad_arg
= DT_ACT_FTRUNCATE
;
879 dt_action_stop(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
881 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
883 ap
->dtad_kind
= DTRACEACT_STOP
;
889 dt_action_breakpoint(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
891 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
893 ap
->dtad_kind
= DTRACEACT_BREAKPOINT
;
899 dt_action_panic(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
901 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
903 ap
->dtad_kind
= DTRACEACT_PANIC
;
908 dt_action_chill(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
910 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
912 dt_cg(yypcb
, dnp
->dn_args
);
913 ap
->dtad_difo
= dt_as(yypcb
);
914 ap
->dtad_kind
= DTRACEACT_CHILL
;
918 dt_action_raise(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
920 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
922 dt_cg(yypcb
, dnp
->dn_args
);
923 ap
->dtad_difo
= dt_as(yypcb
);
924 ap
->dtad_kind
= DTRACEACT_RAISE
;
928 dt_action_exit(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
930 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
932 dt_cg(yypcb
, dnp
->dn_args
);
933 ap
->dtad_difo
= dt_as(yypcb
);
934 ap
->dtad_kind
= DTRACEACT_EXIT
;
935 ap
->dtad_difo
->dtdo_rtype
.dtdt_size
= sizeof (int);
939 dt_action_speculate(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
941 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
943 dt_cg(yypcb
, dnp
->dn_args
);
944 ap
->dtad_difo
= dt_as(yypcb
);
945 ap
->dtad_kind
= DTRACEACT_SPECULATE
;
949 dt_action_commit(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
951 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
953 dt_cg(yypcb
, dnp
->dn_args
);
954 ap
->dtad_difo
= dt_as(yypcb
);
955 ap
->dtad_kind
= DTRACEACT_COMMIT
;
959 dt_action_discard(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
961 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
963 dt_cg(yypcb
, dnp
->dn_args
);
964 ap
->dtad_difo
= dt_as(yypcb
);
965 ap
->dtad_kind
= DTRACEACT_DISCARD
;
969 dt_compile_fun(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
971 switch (dnp
->dn_expr
->dn_ident
->di_id
) {
972 case DT_ACT_BREAKPOINT
:
973 dt_action_breakpoint(dtp
, dnp
->dn_expr
, sdp
);
976 dt_action_chill(dtp
, dnp
->dn_expr
, sdp
);
979 dt_action_clear(dtp
, dnp
->dn_expr
, sdp
);
982 dt_action_commit(dtp
, dnp
->dn_expr
, sdp
);
984 case DT_ACT_DENORMALIZE
:
985 dt_action_normalize(dtp
, dnp
->dn_expr
, sdp
);
988 dt_action_discard(dtp
, dnp
->dn_expr
, sdp
);
991 dt_action_exit(dtp
, dnp
->dn_expr
, sdp
);
994 dt_action_printflike(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_FREOPEN
);
996 case DT_ACT_FTRUNCATE
:
997 dt_action_ftruncate(dtp
, dnp
->dn_expr
, sdp
);
1000 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_MOD
);
1002 case DT_ACT_NORMALIZE
:
1003 dt_action_normalize(dtp
, dnp
->dn_expr
, sdp
);
1006 dt_action_panic(dtp
, dnp
->dn_expr
, sdp
);
1009 dt_action_printa(dtp
, dnp
->dn_expr
, sdp
);
1012 dt_action_printflike(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_PRINTF
);
1015 dt_action_raise(dtp
, dnp
->dn_expr
, sdp
);
1018 dt_action_setopt(dtp
, dnp
->dn_expr
, sdp
);
1020 case DT_ACT_SPECULATE
:
1021 dt_action_speculate(dtp
, dnp
->dn_expr
, sdp
);
1024 dt_action_stack(dtp
, dnp
->dn_expr
, sdp
);
1027 dt_action_stop(dtp
, dnp
->dn_expr
, sdp
);
1030 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_SYM
);
1033 dt_action_printflike(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_SYSTEM
);
1036 dt_action_trace(dtp
, dnp
->dn_expr
, sdp
);
1038 case DT_ACT_TRACEMEM
:
1039 dt_action_tracemem(dtp
, dnp
->dn_expr
, sdp
);
1042 dt_action_trunc(dtp
, dnp
->dn_expr
, sdp
);
1045 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_UADDR
);
1048 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_UMOD
);
1051 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_USYM
);
1055 dt_action_ustack(dtp
, dnp
->dn_expr
, sdp
);
1058 dnerror(dnp
->dn_expr
, D_UNKNOWN
, "tracing function %s( ) is "
1059 "not yet supported\n", dnp
->dn_expr
->dn_ident
->di_name
);
1064 dt_compile_exp(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
1066 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
1068 dt_cg(yypcb
, dnp
->dn_expr
);
1069 ap
->dtad_difo
= dt_as(yypcb
);
1070 ap
->dtad_difo
->dtdo_rtype
= dt_void_rtype
;
1071 ap
->dtad_kind
= DTRACEACT_DIFEXPR
;
1075 dt_compile_agg(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
1077 dt_ident_t
*aid
, *fid
;
1078 dt_node_t
*anp
, *incr
= NULL
;
1079 dtrace_actdesc_t
*ap
;
1080 uint_t n
= 1, argmax
;
1084 * If the aggregation has no aggregating function applied to it, then
1085 * this statement has no effect. Flag this as a programming error.
1087 if (dnp
->dn_aggfun
== NULL
) {
1088 dnerror(dnp
, D_AGG_NULL
, "expression has null effect: @%s\n",
1089 dnp
->dn_ident
->di_name
);
1092 aid
= dnp
->dn_ident
;
1093 fid
= dnp
->dn_aggfun
->dn_ident
;
1095 if (dnp
->dn_aggfun
->dn_args
!= NULL
&&
1096 dt_node_is_scalar(dnp
->dn_aggfun
->dn_args
) == 0) {
1097 dnerror(dnp
->dn_aggfun
, D_AGG_SCALAR
, "%s( ) argument #1 must "
1098 "be of scalar type\n", fid
->di_name
);
1102 * The ID of the aggregation itself is implicitly recorded as the first
1103 * member of each aggregation tuple so we can distinguish them later.
1105 ap
= dt_stmt_action(dtp
, sdp
);
1106 dt_action_difconst(ap
, aid
->di_id
, DTRACEACT_DIFEXPR
);
1108 for (anp
= dnp
->dn_aggtup
; anp
!= NULL
; anp
= anp
->dn_list
) {
1109 ap
= dt_stmt_action(dtp
, sdp
);
1112 if (anp
->dn_kind
== DT_NODE_FUNC
) {
1113 if (anp
->dn_ident
->di_id
== DT_ACT_STACK
) {
1114 dt_action_stack_args(dtp
, ap
, anp
->dn_args
);
1118 if (anp
->dn_ident
->di_id
== DT_ACT_USTACK
||
1119 anp
->dn_ident
->di_id
== DT_ACT_JSTACK
) {
1120 dt_action_ustack_args(dtp
, ap
, anp
);
1124 switch (anp
->dn_ident
->di_id
) {
1126 dt_action_symmod_args(dtp
, ap
,
1127 anp
->dn_args
, DTRACEACT_UADDR
);
1131 dt_action_symmod_args(dtp
, ap
,
1132 anp
->dn_args
, DTRACEACT_USYM
);
1136 dt_action_symmod_args(dtp
, ap
,
1137 anp
->dn_args
, DTRACEACT_UMOD
);
1141 dt_action_symmod_args(dtp
, ap
,
1142 anp
->dn_args
, DTRACEACT_SYM
);
1146 dt_action_symmod_args(dtp
, ap
,
1147 anp
->dn_args
, DTRACEACT_MOD
);
1156 ap
->dtad_difo
= dt_as(yypcb
);
1157 ap
->dtad_kind
= DTRACEACT_DIFEXPR
;
1160 if (fid
->di_id
== DTRACEAGG_LQUANTIZE
) {
1162 * For linear quantization, we have between two and four
1163 * arguments in addition to the expression:
1165 * arg1 => Base value
1166 * arg2 => Limit value
1167 * arg3 => Quantization level step size (defaults to 1)
1168 * arg4 => Quantization increment value (defaults to 1)
1170 dt_node_t
*arg1
= dnp
->dn_aggfun
->dn_args
->dn_list
;
1171 dt_node_t
*arg2
= arg1
->dn_list
;
1172 dt_node_t
*arg3
= arg2
->dn_list
;
1174 uint64_t nlevels
, step
= 1, oarg
;
1175 int64_t baseval
, limitval
;
1177 if (arg1
->dn_kind
!= DT_NODE_INT
) {
1178 dnerror(arg1
, D_LQUANT_BASETYPE
, "lquantize( ) "
1179 "argument #1 must be an integer constant\n");
1182 baseval
= (int64_t)arg1
->dn_value
;
1184 if (baseval
< INT32_MIN
|| baseval
> INT32_MAX
) {
1185 dnerror(arg1
, D_LQUANT_BASEVAL
, "lquantize( ) "
1186 "argument #1 must be a 32-bit quantity\n");
1189 if (arg2
->dn_kind
!= DT_NODE_INT
) {
1190 dnerror(arg2
, D_LQUANT_LIMTYPE
, "lquantize( ) "
1191 "argument #2 must be an integer constant\n");
1194 limitval
= (int64_t)arg2
->dn_value
;
1196 if (limitval
< INT32_MIN
|| limitval
> INT32_MAX
) {
1197 dnerror(arg2
, D_LQUANT_LIMVAL
, "lquantize( ) "
1198 "argument #2 must be a 32-bit quantity\n");
1201 if (limitval
< baseval
) {
1202 dnerror(dnp
, D_LQUANT_MISMATCH
,
1203 "lquantize( ) base (argument #1) must be less "
1204 "than limit (argument #2)\n");
1208 if (!dt_node_is_posconst(arg3
)) {
1209 dnerror(arg3
, D_LQUANT_STEPTYPE
, "lquantize( ) "
1210 "argument #3 must be a non-zero positive "
1211 "integer constant\n");
1214 if ((step
= arg3
->dn_value
) > UINT16_MAX
) {
1215 dnerror(arg3
, D_LQUANT_STEPVAL
, "lquantize( ) "
1216 "argument #3 must be a 16-bit quantity\n");
1220 nlevels
= (limitval
- baseval
) / step
;
1223 dnerror(dnp
, D_LQUANT_STEPLARGE
,
1224 "lquantize( ) step (argument #3) too large: must "
1225 "have at least one quantization level\n");
1228 if (nlevels
> UINT16_MAX
) {
1229 dnerror(dnp
, D_LQUANT_STEPSMALL
, "lquantize( ) step "
1230 "(argument #3) too small: number of quantization "
1231 "levels must be a 16-bit quantity\n");
1234 arg
= (step
<< DTRACE_LQUANTIZE_STEPSHIFT
) |
1235 (nlevels
<< DTRACE_LQUANTIZE_LEVELSHIFT
) |
1236 ((baseval
<< DTRACE_LQUANTIZE_BASESHIFT
) &
1237 DTRACE_LQUANTIZE_BASEMASK
);
1241 isp
= (dt_idsig_t
*)aid
->di_data
;
1243 if (isp
->dis_auxinfo
== 0) {
1245 * This is the first time we've seen an lquantize()
1246 * for this aggregation; we'll store our argument
1247 * as the auxiliary signature information.
1249 isp
->dis_auxinfo
= arg
;
1250 } else if ((oarg
= isp
->dis_auxinfo
) != arg
) {
1252 * If we have seen this lquantize() before and the
1253 * argument doesn't match the original argument, pick
1254 * the original argument apart to concisely report the
1257 int obaseval
= DTRACE_LQUANTIZE_BASE(oarg
);
1258 int onlevels
= DTRACE_LQUANTIZE_LEVELS(oarg
);
1259 int ostep
= DTRACE_LQUANTIZE_STEP(oarg
);
1261 if (obaseval
!= baseval
) {
1262 dnerror(dnp
, D_LQUANT_MATCHBASE
, "lquantize( ) "
1263 "base (argument #1) doesn't match previous "
1264 "declaration: expected %d, found %d\n",
1265 obaseval
, (int)baseval
);
1268 if (onlevels
* ostep
!= nlevels
* step
) {
1269 dnerror(dnp
, D_LQUANT_MATCHLIM
, "lquantize( ) "
1270 "limit (argument #2) doesn't match previous"
1271 " declaration: expected %d, found %d\n",
1272 obaseval
+ onlevels
* ostep
,
1273 (int)baseval
+ (int)nlevels
* (int)step
);
1276 if (ostep
!= step
) {
1277 dnerror(dnp
, D_LQUANT_MATCHSTEP
, "lquantize( ) "
1278 "step (argument #3) doesn't match previous "
1279 "declaration: expected %d, found %d\n",
1284 * We shouldn't be able to get here -- one of the
1285 * parameters must be mismatched if the arguments
1291 incr
= arg3
!= NULL
? arg3
->dn_list
: NULL
;
1295 if (fid
->di_id
== DTRACEAGG_QUANTIZE
) {
1296 incr
= dnp
->dn_aggfun
->dn_args
->dn_list
;
1301 if (!dt_node_is_scalar(incr
)) {
1302 dnerror(dnp
, D_PROTO_ARG
, "%s( ) increment value "
1303 "(argument #%d) must be of scalar type\n",
1304 fid
->di_name
, argmax
);
1307 if ((anp
= incr
->dn_list
) != NULL
) {
1310 for (; anp
!= NULL
; anp
= anp
->dn_list
)
1313 dnerror(incr
, D_PROTO_LEN
, "%s( ) prototype "
1314 "mismatch: %d args passed, at most %d expected",
1315 fid
->di_name
, argc
, argmax
);
1318 ap
= dt_stmt_action(dtp
, sdp
);
1322 ap
->dtad_difo
= dt_as(yypcb
);
1323 ap
->dtad_difo
->dtdo_rtype
= dt_void_rtype
;
1324 ap
->dtad_kind
= DTRACEACT_DIFEXPR
;
1327 assert(sdp
->dtsd_aggdata
== NULL
);
1328 sdp
->dtsd_aggdata
= aid
;
1330 ap
= dt_stmt_action(dtp
, sdp
);
1331 assert(fid
->di_kind
== DT_IDENT_AGGFUNC
);
1332 assert(DTRACEACT_ISAGG(fid
->di_id
));
1333 ap
->dtad_kind
= fid
->di_id
;
1334 ap
->dtad_ntuple
= n
;
1337 if (dnp
->dn_aggfun
->dn_args
!= NULL
) {
1338 dt_cg(yypcb
, dnp
->dn_aggfun
->dn_args
);
1339 ap
->dtad_difo
= dt_as(yypcb
);
1344 dt_compile_one_clause(dtrace_hdl_t
*dtp
, dt_node_t
*cnp
, dt_node_t
*pnp
)
1346 dtrace_ecbdesc_t
*edp
;
1347 dtrace_stmtdesc_t
*sdp
;
1350 yylineno
= pnp
->dn_line
;
1351 dt_setcontext(dtp
, pnp
->dn_desc
);
1352 (void) dt_node_cook(cnp
, DT_IDFLG_REF
);
1354 if (DT_TREEDUMP_PASS(dtp
, 2))
1355 dt_node_printr(cnp
, stderr
, 0);
1357 if ((edp
= dt_ecbdesc_create(dtp
, pnp
->dn_desc
)) == NULL
)
1358 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
1360 assert(yypcb
->pcb_ecbdesc
== NULL
);
1361 yypcb
->pcb_ecbdesc
= edp
;
1363 if (cnp
->dn_pred
!= NULL
) {
1364 dt_cg(yypcb
, cnp
->dn_pred
);
1365 edp
->dted_pred
.dtpdd_difo
= dt_as(yypcb
);
1368 if (cnp
->dn_acts
== NULL
) {
1369 dt_stmt_append(dt_stmt_create(dtp
, edp
,
1370 cnp
->dn_ctxattr
, _dtrace_defattr
), cnp
);
1373 for (dnp
= cnp
->dn_acts
; dnp
!= NULL
; dnp
= dnp
->dn_list
) {
1374 assert(yypcb
->pcb_stmt
== NULL
);
1375 sdp
= dt_stmt_create(dtp
, edp
, cnp
->dn_ctxattr
, cnp
->dn_attr
);
1377 switch (dnp
->dn_kind
) {
1379 if (dnp
->dn_expr
->dn_kind
== DT_NODE_AGG
)
1380 dt_compile_agg(dtp
, dnp
->dn_expr
, sdp
);
1382 dt_compile_exp(dtp
, dnp
, sdp
);
1385 dt_compile_fun(dtp
, dnp
, sdp
);
1388 dt_compile_agg(dtp
, dnp
, sdp
);
1391 dnerror(dnp
, D_UNKNOWN
, "internal error -- node kind "
1392 "%u is not a valid statement\n", dnp
->dn_kind
);
1395 assert(yypcb
->pcb_stmt
== sdp
);
1396 dt_stmt_append(sdp
, dnp
);
1399 assert(yypcb
->pcb_ecbdesc
== edp
);
1400 dt_ecbdesc_release(dtp
, edp
);
1402 yypcb
->pcb_ecbdesc
= NULL
;
1406 dt_compile_clause(dtrace_hdl_t
*dtp
, dt_node_t
*cnp
)
1410 for (pnp
= cnp
->dn_pdescs
; pnp
!= NULL
; pnp
= pnp
->dn_list
)
1411 dt_compile_one_clause(dtp
, cnp
, pnp
);
1415 dt_compile_xlator(dt_node_t
*dnp
)
1417 dt_xlator_t
*dxp
= dnp
->dn_xlator
;
1420 for (mnp
= dnp
->dn_members
; mnp
!= NULL
; mnp
= mnp
->dn_list
) {
1421 assert(dxp
->dx_membdif
[mnp
->dn_membid
] == NULL
);
1423 dxp
->dx_membdif
[mnp
->dn_membid
] = dt_as(yypcb
);
1428 dt_setcontext(dtrace_hdl_t
*dtp
, dtrace_probedesc_t
*pdp
)
1430 const dtrace_pattr_t
*pap
;
1438 * Both kernel and pid based providers are allowed to have names
1439 * ending with what could be interpreted as a number. We assume it's
1440 * a pid and that we may need to dynamically create probes for
1443 * (1) The provider doesn't exist, or,
1444 * (2) The provider exists and has DTRACE_PRIV_PROC privilege.
1446 * On an error, dt_pid_create_probes() will set the error message
1447 * and tag -- we just have to longjmp() out of here.
1449 if (isdigit(pdp
->dtpd_provider
[strlen(pdp
->dtpd_provider
) - 1]) &&
1450 ((pvp
= dt_provider_lookup(dtp
, pdp
->dtpd_provider
)) == NULL
||
1451 pvp
->pv_desc
.dtvd_priv
.dtpp_flags
& DTRACE_PRIV_PROC
) &&
1452 dt_pid_create_probes(pdp
, dtp
, yypcb
) != 0) {
1453 longjmp(yypcb
->pcb_jmpbuf
, EDT_COMPILER
);
1457 * Call dt_probe_info() to get the probe arguments and attributes. If
1458 * a representative probe is found, set 'pap' to the probe provider's
1459 * attributes. Otherwise set 'pap' to default Unstable attributes.
1461 if ((prp
= dt_probe_info(dtp
, pdp
, &yypcb
->pcb_pinfo
)) == NULL
) {
1462 pap
= &_dtrace_prvdesc
;
1463 err
= dtrace_errno(dtp
);
1464 bzero(&yypcb
->pcb_pinfo
, sizeof (dtrace_probeinfo_t
));
1465 yypcb
->pcb_pinfo
.dtp_attr
= pap
->dtpa_provider
;
1466 yypcb
->pcb_pinfo
.dtp_arga
= pap
->dtpa_args
;
1468 pap
= &prp
->pr_pvp
->pv_desc
.dtvd_attr
;
1472 if (err
== EDT_NOPROBE
&& !(yypcb
->pcb_cflags
& DTRACE_C_ZDEFS
)) {
1473 xyerror(D_PDESC_ZERO
, "probe description %s:%s:%s:%s does not "
1474 "match any probes\n", pdp
->dtpd_provider
, pdp
->dtpd_mod
,
1475 pdp
->dtpd_func
, pdp
->dtpd_name
);
1478 if (err
!= EDT_NOPROBE
&& err
!= EDT_UNSTABLE
&& err
!= 0)
1479 xyerror(D_PDESC_INVAL
, "%s\n", dtrace_errmsg(dtp
, err
));
1481 dt_dprintf("set context to %s:%s:%s:%s [%u] prp=%p attr=%s argc=%d\n",
1482 pdp
->dtpd_provider
, pdp
->dtpd_mod
, pdp
->dtpd_func
, pdp
->dtpd_name
,
1483 pdp
->dtpd_id
, (void *)prp
, dt_attr_str(yypcb
->pcb_pinfo
.dtp_attr
,
1484 attrstr
, sizeof (attrstr
)), yypcb
->pcb_pinfo
.dtp_argc
);
1487 * Reset the stability attributes of D global variables that vary
1488 * based on the attributes of the provider and context itself.
1490 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "probeprov")) != NULL
)
1491 idp
->di_attr
= pap
->dtpa_provider
;
1492 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "probemod")) != NULL
)
1493 idp
->di_attr
= pap
->dtpa_mod
;
1494 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "probefunc")) != NULL
)
1495 idp
->di_attr
= pap
->dtpa_func
;
1496 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "probename")) != NULL
)
1497 idp
->di_attr
= pap
->dtpa_name
;
1498 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "args")) != NULL
)
1499 idp
->di_attr
= pap
->dtpa_args
;
1501 yypcb
->pcb_pdesc
= pdp
;
1502 yypcb
->pcb_probe
= prp
;
1506 * Reset context-dependent variables and state at the end of cooking a D probe
1507 * definition clause. This ensures that external declarations between clauses
1508 * do not reference any stale context-dependent data from the previous clause.
1511 dt_endcontext(dtrace_hdl_t
*dtp
)
1513 static const char *const cvars
[] = {
1514 "probeprov", "probemod", "probefunc", "probename", "args", NULL
1520 for (i
= 0; cvars
[i
] != NULL
; i
++) {
1521 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, cvars
[i
])) != NULL
)
1522 idp
->di_attr
= _dtrace_defattr
;
1525 yypcb
->pcb_pdesc
= NULL
;
1526 yypcb
->pcb_probe
= NULL
;
1530 dt_reduceid(dt_idhash_t
*dhp
, dt_ident_t
*idp
, dtrace_hdl_t
*dtp
)
1532 if (idp
->di_vers
!= 0 && idp
->di_vers
> dtp
->dt_vmax
)
1533 dt_idhash_delete(dhp
, idp
);
1539 * When dtrace_setopt() is called for "version", it calls dt_reduce() to remove
1540 * any identifiers or translators that have been previously defined as bound to
1541 * a version greater than the specified version. Therefore, in our current
1542 * version implementation, establishing a binding is a one-way transformation.
1543 * In addition, no versioning is currently provided for types as our .d library
1544 * files do not define any types and we reserve prefixes DTRACE_ and dtrace_
1545 * for our exclusive use. If required, type versioning will require more work.
1548 dt_reduce(dtrace_hdl_t
*dtp
, dt_version_t v
)
1550 char s
[DT_VERSION_STRMAX
];
1551 dt_xlator_t
*dxp
, *nxp
;
1553 if (v
> dtp
->dt_vmax
)
1554 return (dt_set_errno(dtp
, EDT_VERSREDUCED
));
1555 else if (v
== dtp
->dt_vmax
)
1556 return (0); /* no reduction necessary */
1558 dt_dprintf("reducing api version to %s\n",
1559 dt_version_num2str(v
, s
, sizeof (s
)));
1563 for (dxp
= dt_list_next(&dtp
->dt_xlators
); dxp
!= NULL
; dxp
= nxp
) {
1564 nxp
= dt_list_next(dxp
);
1565 if ((dxp
->dx_souid
.di_vers
!= 0 && dxp
->dx_souid
.di_vers
> v
) ||
1566 (dxp
->dx_ptrid
.di_vers
!= 0 && dxp
->dx_ptrid
.di_vers
> v
))
1567 dt_list_delete(&dtp
->dt_xlators
, dxp
);
1570 (void) dt_idhash_iter(dtp
->dt_macros
, (dt_idhash_f
*)dt_reduceid
, dtp
);
1571 (void) dt_idhash_iter(dtp
->dt_aggs
, (dt_idhash_f
*)dt_reduceid
, dtp
);
1572 (void) dt_idhash_iter(dtp
->dt_globals
, (dt_idhash_f
*)dt_reduceid
, dtp
);
1573 (void) dt_idhash_iter(dtp
->dt_tls
, (dt_idhash_f
*)dt_reduceid
, dtp
);
1579 * Fork and exec the cpp(1) preprocessor to run over the specified input file,
1580 * and return a FILE handle for the cpp output. We use the /dev/fd filesystem
1581 * here to simplify the code by leveraging file descriptor inheritance.
1584 dt_preproc(dtrace_hdl_t
*dtp
, FILE *ifp
)
1586 int argc
= dtp
->dt_cpp_argc
;
1587 char **argv
= malloc(sizeof (char *) * (argc
+ 5));
1588 FILE *ofp
= tmpfile();
1590 char ipath
[20], opath
[20]; /* big enough for /dev/fd/ + INT_MAX + \0 */
1591 char verdef
[32]; /* big enough for -D__SUNW_D_VERSION=0x%08x + \0 */
1593 struct sigaction act
, oact
;
1594 sigset_t mask
, omask
;
1601 if (argv
== NULL
|| ofp
== NULL
) {
1602 (void) dt_set_errno(dtp
, errno
);
1607 * If the input is a seekable file, see if it is an interpreter file.
1608 * If we see #!, seek past the first line because cpp will choke on it.
1609 * We start cpp just prior to the \n at the end of this line so that
1610 * it still sees the newline, ensuring that #line values are correct.
1612 if (isatty(fileno(ifp
)) == 0 && (off
= ftello64(ifp
)) != -1) {
1613 if ((c
= fgetc(ifp
)) == '#' && (c
= fgetc(ifp
)) == '!') {
1614 for (off
+= 2; c
!= '\n'; off
++) {
1615 if ((c
= fgetc(ifp
)) == EOF
)
1619 off
--; /* start cpp just prior to \n */
1622 (void) fseeko64(ifp
, off
, SEEK_SET
);
1625 (void) snprintf(ipath
, sizeof (ipath
), "/dev/fd/%d", fileno(ifp
));
1626 (void) snprintf(opath
, sizeof (opath
), "/dev/fd/%d", fileno(ofp
));
1628 bcopy(dtp
->dt_cpp_argv
, argv
, sizeof (char *) * argc
);
1630 (void) snprintf(verdef
, sizeof (verdef
),
1631 "-D__SUNW_D_VERSION=0x%08x", dtp
->dt_vmax
);
1632 argv
[argc
++] = verdef
;
1634 switch (dtp
->dt_stdcmode
) {
1637 argv
[argc
++] = "-D__STDC__=0";
1640 argv
[argc
++] = "-D__STDC__=1";
1644 argv
[argc
++] = ipath
;
1645 argv
[argc
++] = opath
;
1649 * libdtrace must be able to be embedded in other programs that may
1650 * include application-specific signal handlers. Therefore, if we
1651 * need to fork to run cpp(1), we must avoid generating a SIGCHLD
1652 * that could confuse the containing application. To do this,
1653 * we block SIGCHLD and reset its disposition to SIG_DFL.
1654 * We restore our signal state once we are done.
1656 (void) sigemptyset(&mask
);
1657 (void) sigaddset(&mask
, SIGCHLD
);
1658 (void) sigprocmask(SIG_BLOCK
, &mask
, &omask
);
1660 bzero(&act
, sizeof (act
));
1661 act
.sa_handler
= SIG_DFL
;
1662 (void) sigaction(SIGCHLD
, &act
, &oact
);
1664 if ((pid
= fork1()) == -1) {
1665 (void) sigaction(SIGCHLD
, &oact
, NULL
);
1666 (void) sigprocmask(SIG_SETMASK
, &omask
, NULL
);
1667 (void) dt_set_errno(dtp
, EDT_CPPFORK
);
1672 (void) execvp(dtp
->dt_cpp_path
, argv
);
1673 _exit(errno
== ENOENT
? 127 : 126);
1677 dt_dprintf("waiting for %s (PID %d)\n", dtp
->dt_cpp_path
,
1679 } while (waitpid(pid
, &wstat
, 0) == -1 && errno
== EINTR
);
1681 (void) sigaction(SIGCHLD
, &oact
, NULL
);
1682 (void) sigprocmask(SIG_SETMASK
, &omask
, NULL
);
1684 dt_dprintf("%s returned exit status 0x%x\n", dtp
->dt_cpp_path
, wstat
);
1685 estat
= WIFEXITED(wstat
) ? WEXITSTATUS(wstat
) : -1;
1690 (void) dt_set_errno(dtp
, EDT_CPPEXEC
);
1693 (void) dt_set_errno(dtp
, EDT_CPPENT
);
1696 (void) dt_set_errno(dtp
, EDT_CPPERR
);
1703 (void) fseek(ofp
, 0, SEEK_SET
);
1713 dt_lib_depend_error(dtrace_hdl_t
*dtp
, const char *format
, ...)
1717 va_start(ap
, format
);
1718 dt_set_errmsg(dtp
, NULL
, NULL
, NULL
, 0, format
, ap
);
1723 dt_lib_depend_add(dtrace_hdl_t
*dtp
, dt_list_t
*dlp
, const char *arg
)
1725 dt_lib_depend_t
*dld
;
1728 assert(arg
!= NULL
);
1730 if ((end
= strrchr(arg
, '/')) == NULL
)
1731 return (dt_set_errno(dtp
, EINVAL
));
1733 if ((dld
= dt_zalloc(dtp
, sizeof (dt_lib_depend_t
))) == NULL
)
1736 if ((dld
->dtld_libpath
= dt_alloc(dtp
, MAXPATHLEN
)) == NULL
) {
1741 (void) strlcpy(dld
->dtld_libpath
, arg
, end
- arg
+ 2);
1742 if ((dld
->dtld_library
= strdup(arg
)) == NULL
) {
1743 dt_free(dtp
, dld
->dtld_libpath
);
1745 return (dt_set_errno(dtp
, EDT_NOMEM
));
1748 dt_list_append(dlp
, dld
);
1753 dt_lib_depend_lookup(dt_list_t
*dld
, const char *arg
)
1755 dt_lib_depend_t
*dldn
;
1757 for (dldn
= dt_list_next(dld
); dldn
!= NULL
;
1758 dldn
= dt_list_next(dldn
)) {
1759 if (strcmp(dldn
->dtld_library
, arg
) == 0)
1767 * Go through all the library files, and, if any library dependencies exist for
1768 * that file, add it to that node's list of dependents. The result of this
1769 * will be a graph which can then be topologically sorted to produce a
1770 * compilation order.
1773 dt_lib_build_graph(dtrace_hdl_t
*dtp
)
1775 dt_lib_depend_t
*dld
, *dpld
;
1777 for (dld
= dt_list_next(&dtp
->dt_lib_dep
); dld
!= NULL
;
1778 dld
= dt_list_next(dld
)) {
1779 char *library
= dld
->dtld_library
;
1781 for (dpld
= dt_list_next(&dld
->dtld_dependencies
); dpld
!= NULL
;
1782 dpld
= dt_list_next(dpld
)) {
1783 dt_lib_depend_t
*dlda
;
1785 if ((dlda
= dt_lib_depend_lookup(&dtp
->dt_lib_dep
,
1786 dpld
->dtld_library
)) == NULL
) {
1787 dt_lib_depend_error(dtp
,
1788 "Invalid library dependency in %s: %s\n",
1789 dld
->dtld_library
, dpld
->dtld_library
);
1791 return (dt_set_errno(dtp
, EDT_COMPILER
));
1794 if ((dt_lib_depend_add(dtp
, &dlda
->dtld_dependents
,
1796 return (-1); /* preserve dt_errno */
1804 dt_topo_sort(dtrace_hdl_t
*dtp
, dt_lib_depend_t
*dld
, int *count
)
1806 dt_lib_depend_t
*dpld
, *dlda
, *new;
1808 dld
->dtld_start
= ++(*count
);
1810 for (dpld
= dt_list_next(&dld
->dtld_dependents
); dpld
!= NULL
;
1811 dpld
= dt_list_next(dpld
)) {
1812 dlda
= dt_lib_depend_lookup(&dtp
->dt_lib_dep
,
1813 dpld
->dtld_library
);
1814 assert(dlda
!= NULL
);
1816 if (dlda
->dtld_start
== 0 &&
1817 dt_topo_sort(dtp
, dlda
, count
) == -1)
1821 if ((new = dt_zalloc(dtp
, sizeof (dt_lib_depend_t
))) == NULL
)
1824 if ((new->dtld_library
= strdup(dld
->dtld_library
)) == NULL
) {
1826 return (dt_set_errno(dtp
, EDT_NOMEM
));
1829 new->dtld_start
= dld
->dtld_start
;
1830 new->dtld_finish
= dld
->dtld_finish
= ++(*count
);
1831 dt_list_prepend(&dtp
->dt_lib_dep_sorted
, new);
1833 dt_dprintf("library %s sorted (%d/%d)\n", new->dtld_library
,
1834 new->dtld_start
, new->dtld_finish
);
1840 dt_lib_depend_sort(dtrace_hdl_t
*dtp
)
1842 dt_lib_depend_t
*dld
, *dpld
, *dlda
;
1845 if (dt_lib_build_graph(dtp
) == -1)
1846 return (-1); /* preserve dt_errno */
1849 * Perform a topological sort of the graph that hangs off
1850 * dtp->dt_lib_dep. The result of this process will be a
1851 * dependency ordered list located at dtp->dt_lib_dep_sorted.
1853 for (dld
= dt_list_next(&dtp
->dt_lib_dep
); dld
!= NULL
;
1854 dld
= dt_list_next(dld
)) {
1855 if (dld
->dtld_start
== 0 &&
1856 dt_topo_sort(dtp
, dld
, &count
) == -1)
1857 return (-1); /* preserve dt_errno */;
1861 * Check the graph for cycles. If an ancestor's finishing time is
1862 * less than any of its dependent's finishing times then a back edge
1863 * exists in the graph and this is a cycle.
1865 for (dld
= dt_list_next(&dtp
->dt_lib_dep
); dld
!= NULL
;
1866 dld
= dt_list_next(dld
)) {
1867 for (dpld
= dt_list_next(&dld
->dtld_dependents
); dpld
!= NULL
;
1868 dpld
= dt_list_next(dpld
)) {
1869 dlda
= dt_lib_depend_lookup(&dtp
->dt_lib_dep_sorted
,
1870 dpld
->dtld_library
);
1871 assert(dlda
!= NULL
);
1873 if (dlda
->dtld_finish
> dld
->dtld_finish
) {
1874 dt_lib_depend_error(dtp
,
1875 "Cyclic dependency detected: %s => %s\n",
1876 dld
->dtld_library
, dpld
->dtld_library
);
1878 return (dt_set_errno(dtp
, EDT_COMPILER
));
1887 dt_lib_depend_free(dtrace_hdl_t
*dtp
)
1889 dt_lib_depend_t
*dld
, *dlda
;
1891 while ((dld
= dt_list_next(&dtp
->dt_lib_dep
)) != NULL
) {
1892 while ((dlda
= dt_list_next(&dld
->dtld_dependencies
)) != NULL
) {
1893 dt_list_delete(&dld
->dtld_dependencies
, dlda
);
1894 dt_free(dtp
, dlda
->dtld_library
);
1895 dt_free(dtp
, dlda
->dtld_libpath
);
1898 while ((dlda
= dt_list_next(&dld
->dtld_dependents
)) != NULL
) {
1899 dt_list_delete(&dld
->dtld_dependents
, dlda
);
1900 dt_free(dtp
, dlda
->dtld_library
);
1901 dt_free(dtp
, dlda
->dtld_libpath
);
1904 dt_list_delete(&dtp
->dt_lib_dep
, dld
);
1905 dt_free(dtp
, dld
->dtld_library
);
1906 dt_free(dtp
, dld
->dtld_libpath
);
1910 while ((dld
= dt_list_next(&dtp
->dt_lib_dep_sorted
)) != NULL
) {
1911 dt_list_delete(&dtp
->dt_lib_dep_sorted
, dld
);
1912 dt_free(dtp
, dld
->dtld_library
);
1918 * Open all the .d library files found in the specified directory and
1919 * compile each one of them. We silently ignore any missing directories and
1920 * other files found therein. We only fail (and thereby fail dt_load_libs()) if
1921 * we fail to compile a library and the error is something other than #pragma D
1922 * depends_on. Dependency errors are silently ignored to permit a library
1923 * directory to contain libraries which may not be accessible depending on our
1927 dt_load_libs_dir(dtrace_hdl_t
*dtp
, const char *path
)
1933 char fname
[PATH_MAX
];
1937 if ((dirp
= opendir(path
)) == NULL
) {
1938 dt_dprintf("skipping lib dir %s: %s\n", path
, strerror(errno
));
1942 /* First, parse each file for library dependencies. */
1943 while ((dp
= readdir(dirp
)) != NULL
) {
1944 if ((p
= strrchr(dp
->d_name
, '.')) == NULL
|| strcmp(p
, ".d"))
1945 continue; /* skip any filename not ending in .d */
1947 (void) snprintf(fname
, sizeof (fname
),
1948 "%s/%s", path
, dp
->d_name
);
1950 if ((fp
= fopen(fname
, "r")) == NULL
) {
1951 dt_dprintf("skipping library %s: %s\n",
1952 fname
, strerror(errno
));
1956 dtp
->dt_filetag
= fname
;
1957 if (dt_lib_depend_add(dtp
, &dtp
->dt_lib_dep
, fname
) != 0)
1958 return (-1); /* preserve dt_errno */
1960 rv
= dt_compile(dtp
, DT_CTX_DPROG
,
1961 DTRACE_PROBESPEC_NAME
, NULL
,
1962 DTRACE_C_EMPTY
| DTRACE_C_CTL
, 0, NULL
, fp
, NULL
);
1964 if (rv
!= NULL
&& dtp
->dt_errno
&&
1965 (dtp
->dt_errno
!= EDT_COMPILER
||
1966 dtp
->dt_errtag
!= dt_errtag(D_PRAGMA_DEPEND
)))
1967 return (-1); /* preserve dt_errno */
1970 dt_dprintf("error parsing library %s: %s\n",
1971 fname
, dtrace_errmsg(dtp
, dtrace_errno(dtp
)));
1974 dtp
->dt_filetag
= NULL
;
1977 (void) closedir(dirp
);
1983 * Perform a topological sorting of all the libraries found across the entire
1984 * dt_lib_path. Once sorted, compile each one in topological order to cache its
1985 * inlines and translators, etc. We silently ignore any missing directories and
1986 * other files found therein. We only fail (and thereby fail dt_load_libs()) if
1987 * we fail to compile a library and the error is something other than #pragma D
1988 * depends_on. Dependency errors are silently ignored to permit a library
1989 * directory to contain libraries which may not be accessible depending on our
1993 dt_load_libs_sort(dtrace_hdl_t
*dtp
)
1997 dt_lib_depend_t
*dld
;
2000 * Finish building the graph containing the library dependencies
2001 * and perform a topological sort to generate an ordered list
2004 if (dt_lib_depend_sort(dtp
) == -1)
2007 for (dld
= dt_list_next(&dtp
->dt_lib_dep_sorted
); dld
!= NULL
;
2008 dld
= dt_list_next(dld
)) {
2010 if ((fp
= fopen(dld
->dtld_library
, "r")) == NULL
) {
2011 dt_dprintf("skipping library %s: %s\n",
2012 dld
->dtld_library
, strerror(errno
));
2016 dtp
->dt_filetag
= dld
->dtld_library
;
2017 pgp
= dtrace_program_fcompile(dtp
, fp
, DTRACE_C_EMPTY
, 0, NULL
);
2019 dtp
->dt_filetag
= NULL
;
2021 if (pgp
== NULL
&& (dtp
->dt_errno
!= EDT_COMPILER
||
2022 dtp
->dt_errtag
!= dt_errtag(D_PRAGMA_DEPEND
)))
2026 dt_dprintf("skipping library %s: %s\n",
2028 dtrace_errmsg(dtp
, dtrace_errno(dtp
)));
2030 dld
->dtld_loaded
= B_TRUE
;
2031 dt_program_destroy(dtp
, pgp
);
2035 dt_lib_depend_free(dtp
);
2039 dt_lib_depend_free(dtp
);
2040 return (-1); /* preserve dt_errno */
2044 * Load the contents of any appropriate DTrace .d library files. These files
2045 * contain inlines and translators that will be cached by the compiler. We
2046 * defer this activity until the first compile to permit libdtrace clients to
2047 * add their own library directories and so that we can properly report errors.
2050 dt_load_libs(dtrace_hdl_t
*dtp
)
2054 if (dtp
->dt_cflags
& DTRACE_C_NOLIBS
)
2055 return (0); /* libraries already processed */
2057 dtp
->dt_cflags
|= DTRACE_C_NOLIBS
;
2059 for (dirp
= dt_list_next(&dtp
->dt_lib_path
);
2060 dirp
!= NULL
; dirp
= dt_list_next(dirp
)) {
2061 if (dt_load_libs_dir(dtp
, dirp
->dir_path
) != 0) {
2062 dtp
->dt_cflags
&= ~DTRACE_C_NOLIBS
;
2063 return (-1); /* errno is set for us */
2067 if (dt_load_libs_sort(dtp
) < 0)
2068 return (-1); /* errno is set for us */
2074 dt_compile(dtrace_hdl_t
*dtp
, int context
, dtrace_probespec_t pspec
, void *arg
,
2075 uint_t cflags
, int argc
, char *const argv
[], FILE *fp
, const char *s
)
2083 if ((fp
== NULL
&& s
== NULL
) || (cflags
& ~DTRACE_C_MASK
) != 0) {
2084 (void) dt_set_errno(dtp
, EINVAL
);
2088 if (dt_list_next(&dtp
->dt_lib_path
) != NULL
&& dt_load_libs(dtp
) != 0)
2089 return (NULL
); /* errno is set for us */
2091 if (dtp
->dt_globals
->dh_nelems
!= 0)
2092 (void) dt_idhash_iter(dtp
->dt_globals
, dt_idreset
, NULL
);
2094 if (dtp
->dt_tls
->dh_nelems
!= 0)
2095 (void) dt_idhash_iter(dtp
->dt_tls
, dt_idreset
, NULL
);
2097 if (fp
&& (cflags
& DTRACE_C_CPP
) && (fp
= dt_preproc(dtp
, fp
)) == NULL
)
2098 return (NULL
); /* errno is set for us */
2100 dt_pcb_push(dtp
, &pcb
);
2102 pcb
.pcb_fileptr
= fp
;
2105 pcb
.pcb_strlen
= s
? strlen(s
) : 0;
2106 pcb
.pcb_sargc
= argc
;
2107 pcb
.pcb_sargv
= argv
;
2108 pcb
.pcb_sflagv
= argc
? calloc(argc
, sizeof (ushort_t
)) : NULL
;
2109 pcb
.pcb_pspec
= pspec
;
2110 pcb
.pcb_cflags
= dtp
->dt_cflags
| cflags
;
2111 pcb
.pcb_amin
= dtp
->dt_amin
;
2112 pcb
.pcb_yystate
= -1;
2113 pcb
.pcb_context
= context
;
2114 pcb
.pcb_token
= context
;
2116 if (context
!= DT_CTX_DPROG
)
2118 else if (cflags
& DTRACE_C_CTL
)
2119 yybegin(YYS_CONTROL
);
2121 yybegin(YYS_CLAUSE
);
2123 if ((err
= setjmp(yypcb
->pcb_jmpbuf
)) != 0)
2126 if (yypcb
->pcb_sargc
!= 0 && yypcb
->pcb_sflagv
== NULL
)
2127 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
2129 yypcb
->pcb_idents
= dt_idhash_create("ambiguous", NULL
, 0, 0);
2130 yypcb
->pcb_locals
= dt_idhash_create("clause local", NULL
,
2131 DIF_VAR_OTHER_UBASE
, DIF_VAR_OTHER_MAX
);
2133 if (yypcb
->pcb_idents
== NULL
|| yypcb
->pcb_locals
== NULL
)
2134 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
2137 * Invoke the parser to evaluate the D source code. If any errors
2138 * occur during parsing, an error function will be called and we
2139 * will longjmp back to pcb_jmpbuf to abort. If parsing succeeds,
2140 * we optionally display the parse tree if debugging is enabled.
2142 if (yyparse() != 0 || yypcb
->pcb_root
== NULL
)
2143 xyerror(D_EMPTY
, "empty D program translation unit\n");
2147 if (cflags
& DTRACE_C_CTL
)
2150 if (context
!= DT_CTX_DTYPE
&& DT_TREEDUMP_PASS(dtp
, 1))
2151 dt_node_printr(yypcb
->pcb_root
, stderr
, 0);
2153 if (yypcb
->pcb_pragmas
!= NULL
)
2154 (void) dt_idhash_iter(yypcb
->pcb_pragmas
, dt_idpragma
, NULL
);
2156 if (argc
> 1 && !(yypcb
->pcb_cflags
& DTRACE_C_ARGREF
) &&
2157 !(yypcb
->pcb_sflagv
[argc
- 1] & DT_IDFLG_REF
)) {
2158 xyerror(D_MACRO_UNUSED
, "extraneous argument '%s' ($%d is "
2159 "not referenced)\n", yypcb
->pcb_sargv
[argc
- 1], argc
- 1);
2163 * If we have successfully created a parse tree for a D program, loop
2164 * over the clauses and actions and instantiate the corresponding
2165 * libdtrace program. If we are parsing a D expression, then we
2166 * simply run the code generator and assembler on the resulting tree.
2170 assert(yypcb
->pcb_root
->dn_kind
== DT_NODE_PROG
);
2172 if ((dnp
= yypcb
->pcb_root
->dn_list
) == NULL
&&
2173 !(yypcb
->pcb_cflags
& DTRACE_C_EMPTY
))
2174 xyerror(D_EMPTY
, "empty D program translation unit\n");
2176 if ((yypcb
->pcb_prog
= dt_program_create(dtp
)) == NULL
)
2177 longjmp(yypcb
->pcb_jmpbuf
, dtrace_errno(dtp
));
2179 for (; dnp
!= NULL
; dnp
= dnp
->dn_list
) {
2180 switch (dnp
->dn_kind
) {
2181 case DT_NODE_CLAUSE
:
2182 dt_compile_clause(dtp
, dnp
);
2184 case DT_NODE_XLATOR
:
2185 if (dtp
->dt_xlatemode
== DT_XL_DYNAMIC
)
2186 dt_compile_xlator(dnp
);
2188 case DT_NODE_PROVIDER
:
2189 (void) dt_node_cook(dnp
, DT_IDFLG_REF
);
2194 yypcb
->pcb_prog
->dp_xrefs
= yypcb
->pcb_asxrefs
;
2195 yypcb
->pcb_prog
->dp_xrefslen
= yypcb
->pcb_asxreflen
;
2196 yypcb
->pcb_asxrefs
= NULL
;
2197 yypcb
->pcb_asxreflen
= 0;
2199 rv
= yypcb
->pcb_prog
;
2203 (void) dt_node_cook(yypcb
->pcb_root
, DT_IDFLG_REF
);
2204 dt_cg(yypcb
, yypcb
->pcb_root
);
2209 ddp
= (dt_decl_t
*)yypcb
->pcb_root
; /* root is really a decl */
2210 err
= dt_decl_type(ddp
, arg
);
2214 longjmp(yypcb
->pcb_jmpbuf
, EDT_COMPILER
);
2221 if (context
!= DT_CTX_DTYPE
&& DT_TREEDUMP_PASS(dtp
, 3))
2222 dt_node_printr(yypcb
->pcb_root
, stderr
, 0);
2224 if (dtp
->dt_cdefs_fd
!= -1 && (ftruncate64(dtp
->dt_cdefs_fd
, 0) == -1 ||
2225 lseek64(dtp
->dt_cdefs_fd
, 0, SEEK_SET
) == -1 ||
2226 ctf_write(dtp
->dt_cdefs
->dm_ctfp
, dtp
->dt_cdefs_fd
) == CTF_ERR
))
2227 dt_dprintf("failed to update CTF cache: %s\n", strerror(errno
));
2229 if (dtp
->dt_ddefs_fd
!= -1 && (ftruncate64(dtp
->dt_ddefs_fd
, 0) == -1 ||
2230 lseek64(dtp
->dt_ddefs_fd
, 0, SEEK_SET
) == -1 ||
2231 ctf_write(dtp
->dt_ddefs
->dm_ctfp
, dtp
->dt_ddefs_fd
) == CTF_ERR
))
2232 dt_dprintf("failed to update CTF cache: %s\n", strerror(errno
));
2234 if (yypcb
->pcb_fileptr
&& (cflags
& DTRACE_C_CPP
))
2235 (void) fclose(yypcb
->pcb_fileptr
); /* close dt_preproc() file */
2237 dt_pcb_pop(dtp
, err
);
2238 (void) dt_set_errno(dtp
, err
);
2239 return (err
? NULL
: rv
);
2243 dtrace_program_strcompile(dtrace_hdl_t
*dtp
, const char *s
,
2244 dtrace_probespec_t spec
, uint_t cflags
, int argc
, char *const argv
[])
2246 return (dt_compile(dtp
, DT_CTX_DPROG
,
2247 spec
, NULL
, cflags
, argc
, argv
, NULL
, s
));
2251 dtrace_program_fcompile(dtrace_hdl_t
*dtp
, FILE *fp
,
2252 uint_t cflags
, int argc
, char *const argv
[])
2254 return (dt_compile(dtp
, DT_CTX_DPROG
,
2255 DTRACE_PROBESPEC_NAME
, NULL
, cflags
, argc
, argv
, fp
, NULL
));
2259 dtrace_type_strcompile(dtrace_hdl_t
*dtp
, const char *s
, dtrace_typeinfo_t
*dtt
)
2261 (void) dt_compile(dtp
, DT_CTX_DTYPE
,
2262 DTRACE_PROBESPEC_NONE
, dtt
, 0, 0, NULL
, NULL
, s
);
2263 return (dtp
->dt_errno
? -1 : 0);
2267 dtrace_type_fcompile(dtrace_hdl_t
*dtp
, FILE *fp
, dtrace_typeinfo_t
*dtt
)
2269 (void) dt_compile(dtp
, DT_CTX_DTYPE
,
2270 DTRACE_PROBESPEC_NONE
, dtt
, 0, 0, NULL
, fp
, NULL
);
2271 return (dtp
->dt_errno
? -1 : 0);