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, 2016 by Delphix. All rights reserved.
25 * Copyright (c) 2013, Joyent Inc. All rights reserved.
26 * Copyright 2015 Gary Mills
30 * DTrace D Language Compiler
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:
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
53 * Several other source files provide collections of utility routines used by
54 * these major files. The compiler itself is implemented in multiple passes:
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.
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.
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.
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).
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.
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.
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.
86 #include <sys/types.h>
88 #include <sys/sysmacros.h>
101 #include <dt_module.h>
102 #include <dt_program.h>
103 #include <dt_provider.h>
104 #include <dt_printf.h>
106 #include <dt_grammar.h>
107 #include <dt_ident.h>
108 #include <dt_string.h>
111 static const dtrace_diftype_t dt_void_rtype
= {
112 DIF_TYPE_CTF
, CTF_K_INTEGER
, 0, 0, 0
115 static const dtrace_diftype_t dt_int_rtype
= {
116 DIF_TYPE_CTF
, CTF_K_INTEGER
, 0, 0, sizeof (uint64_t)
119 static void *dt_compile(dtrace_hdl_t
*, int, dtrace_probespec_t
, void *,
120 uint_t
, int, char *const[], FILE *, const char *);
124 dt_idreset(dt_idhash_t
*dhp
, dt_ident_t
*idp
, void *ignored
)
126 idp
->di_flags
&= ~(DT_IDFLG_REF
| DT_IDFLG_MOD
|
127 DT_IDFLG_DIFR
| DT_IDFLG_DIFW
);
133 dt_idpragma(dt_idhash_t
*dhp
, dt_ident_t
*idp
, void *ignored
)
135 yylineno
= idp
->di_lineno
;
136 xyerror(D_PRAGMA_UNUSED
, "unused #pragma %s\n", (char *)idp
->di_iarg
);
140 static dtrace_stmtdesc_t
*
141 dt_stmt_create(dtrace_hdl_t
*dtp
, dtrace_ecbdesc_t
*edp
,
142 dtrace_attribute_t descattr
, dtrace_attribute_t stmtattr
)
144 dtrace_stmtdesc_t
*sdp
= dtrace_stmt_create(dtp
, edp
);
147 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
149 assert(yypcb
->pcb_stmt
== NULL
);
150 yypcb
->pcb_stmt
= sdp
;
152 sdp
->dtsd_descattr
= descattr
;
153 sdp
->dtsd_stmtattr
= stmtattr
;
158 static dtrace_actdesc_t
*
159 dt_stmt_action(dtrace_hdl_t
*dtp
, dtrace_stmtdesc_t
*sdp
)
161 dtrace_actdesc_t
*new;
163 if ((new = dtrace_stmt_action(dtp
, sdp
)) == NULL
)
164 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
170 * Utility function to determine if a given action description is destructive.
171 * The dtdo_destructive bit is set for us by the DIF assembler (see dt_as.c).
174 dt_action_destructive(const dtrace_actdesc_t
*ap
)
176 return (DTRACEACT_ISDESTRUCTIVE(ap
->dtad_kind
) || (ap
->dtad_kind
==
177 DTRACEACT_DIFEXPR
&& ap
->dtad_difo
->dtdo_destructive
));
181 dt_stmt_append(dtrace_stmtdesc_t
*sdp
, const dt_node_t
*dnp
)
183 dtrace_ecbdesc_t
*edp
= sdp
->dtsd_ecbdesc
;
184 dtrace_actdesc_t
*ap
, *tap
;
190 * Make sure that the new statement jibes with the rest of the ECB.
192 for (ap
= edp
->dted_action
; ap
!= NULL
; ap
= ap
->dtad_next
) {
193 if (ap
->dtad_kind
== DTRACEACT_COMMIT
) {
195 dnerror(dnp
, D_COMM_COMM
, "commit( ) may "
196 "not follow commit( )\n");
200 dnerror(dnp
, D_COMM_DREC
, "commit( ) may "
201 "not follow data-recording action(s)\n");
204 for (tap
= ap
; tap
!= NULL
; tap
= tap
->dtad_next
) {
205 if (!DTRACEACT_ISAGG(tap
->dtad_kind
))
208 dnerror(dnp
, D_AGG_COMM
, "aggregating actions "
209 "may not follow commit( )\n");
216 if (ap
->dtad_kind
== DTRACEACT_SPECULATE
) {
218 dnerror(dnp
, D_SPEC_SPEC
, "speculate( ) may "
219 "not follow speculate( )\n");
223 dnerror(dnp
, D_SPEC_COMM
, "speculate( ) may "
224 "not follow commit( )\n");
228 dnerror(dnp
, D_SPEC_DREC
, "speculate( ) may "
229 "not follow data-recording action(s)\n");
236 if (DTRACEACT_ISAGG(ap
->dtad_kind
)) {
238 dnerror(dnp
, D_AGG_SPEC
, "aggregating actions "
239 "may not follow speculate( )\n");
247 if (dt_action_destructive(ap
)) {
248 dnerror(dnp
, D_ACT_SPEC
, "destructive actions "
249 "may not follow speculate( )\n");
252 if (ap
->dtad_kind
== DTRACEACT_EXIT
) {
253 dnerror(dnp
, D_EXIT_SPEC
, "exit( ) may not "
254 "follow speculate( )\n");
259 * Exclude all non data-recording actions.
261 if (dt_action_destructive(ap
) ||
262 ap
->dtad_kind
== DTRACEACT_DISCARD
)
265 if (ap
->dtad_kind
== DTRACEACT_DIFEXPR
&&
266 ap
->dtad_difo
->dtdo_rtype
.dtdt_kind
== DIF_TYPE_CTF
&&
267 ap
->dtad_difo
->dtdo_rtype
.dtdt_size
== 0)
271 dnerror(dnp
, D_DREC_COMM
, "data-recording actions "
272 "may not follow commit( )\n");
279 if (dtrace_stmt_add(yypcb
->pcb_hdl
, yypcb
->pcb_prog
, sdp
) != 0)
280 longjmp(yypcb
->pcb_jmpbuf
, dtrace_errno(yypcb
->pcb_hdl
));
282 if (yypcb
->pcb_stmt
== sdp
)
283 yypcb
->pcb_stmt
= NULL
;
287 * For the first element of an aggregation tuple or for printa(), we create a
288 * simple DIF program that simply returns the immediate value that is the ID
289 * of the aggregation itself. This could be optimized in the future by
290 * creating a new in-kernel dtad_kind that just returns an integer.
293 dt_action_difconst(dtrace_actdesc_t
*ap
, uint_t id
, dtrace_actkind_t kind
)
295 dtrace_hdl_t
*dtp
= yypcb
->pcb_hdl
;
296 dtrace_difo_t
*dp
= dt_zalloc(dtp
, sizeof (dtrace_difo_t
));
299 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
301 dp
->dtdo_buf
= dt_alloc(dtp
, sizeof (dif_instr_t
) * 2);
302 dp
->dtdo_inttab
= dt_alloc(dtp
, sizeof (uint64_t));
304 if (dp
->dtdo_buf
== NULL
|| dp
->dtdo_inttab
== NULL
) {
305 dt_difo_free(dtp
, dp
);
306 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
309 dp
->dtdo_buf
[0] = DIF_INSTR_SETX(0, 1); /* setx DIF_INTEGER[0], %r1 */
310 dp
->dtdo_buf
[1] = DIF_INSTR_RET(1); /* ret %r1 */
312 dp
->dtdo_inttab
[0] = id
;
314 dp
->dtdo_rtype
= dt_int_rtype
;
317 ap
->dtad_kind
= kind
;
321 dt_action_clear(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
324 dtrace_actdesc_t
*ap
;
327 char n
[DT_TYPE_NAMELEN
];
330 for (anp
= dnp
->dn_args
; anp
!= NULL
; anp
= anp
->dn_list
)
331 argc
++; /* count up arguments for error messages below */
334 dnerror(dnp
, D_CLEAR_PROTO
,
335 "%s( ) prototype mismatch: %d args passed, 1 expected\n",
336 dnp
->dn_ident
->di_name
, argc
);
342 if (anp
->dn_kind
!= DT_NODE_AGG
) {
343 dnerror(dnp
, D_CLEAR_AGGARG
,
344 "%s( ) argument #1 is incompatible with prototype:\n"
345 "\tprototype: aggregation\n\t argument: %s\n",
346 dnp
->dn_ident
->di_name
,
347 dt_node_type_name(anp
, n
, sizeof (n
)));
352 if (aid
->di_gen
== dtp
->dt_gen
&& !(aid
->di_flags
& DT_IDFLG_MOD
)) {
353 dnerror(dnp
, D_CLEAR_AGGBAD
,
354 "undefined aggregation: @%s\n", aid
->di_name
);
357 ap
= dt_stmt_action(dtp
, sdp
);
358 dt_action_difconst(ap
, anp
->dn_ident
->di_id
, DTRACEACT_LIBACT
);
359 ap
->dtad_arg
= DT_ACT_CLEAR
;
363 dt_action_normalize(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
366 dtrace_actdesc_t
*ap
;
367 dt_node_t
*anp
, *normal
;
368 int denormal
= (strcmp(dnp
->dn_ident
->di_name
, "denormalize") == 0);
370 char n
[DT_TYPE_NAMELEN
];
373 for (anp
= dnp
->dn_args
; anp
!= NULL
; anp
= anp
->dn_list
)
374 argc
++; /* count up arguments for error messages below */
376 if ((denormal
&& argc
!= 1) || (!denormal
&& argc
!= 2)) {
377 dnerror(dnp
, D_NORMALIZE_PROTO
,
378 "%s( ) prototype mismatch: %d args passed, %d expected\n",
379 dnp
->dn_ident
->di_name
, argc
, denormal
? 1 : 2);
385 if (anp
->dn_kind
!= DT_NODE_AGG
) {
386 dnerror(dnp
, D_NORMALIZE_AGGARG
,
387 "%s( ) argument #1 is incompatible with prototype:\n"
388 "\tprototype: aggregation\n\t argument: %s\n",
389 dnp
->dn_ident
->di_name
,
390 dt_node_type_name(anp
, n
, sizeof (n
)));
393 if ((normal
= anp
->dn_list
) != NULL
&& !dt_node_is_scalar(normal
)) {
394 dnerror(dnp
, D_NORMALIZE_SCALAR
,
395 "%s( ) argument #2 must be of scalar type\n",
396 dnp
->dn_ident
->di_name
);
401 if (aid
->di_gen
== dtp
->dt_gen
&& !(aid
->di_flags
& DT_IDFLG_MOD
)) {
402 dnerror(dnp
, D_NORMALIZE_AGGBAD
,
403 "undefined aggregation: @%s\n", aid
->di_name
);
406 ap
= dt_stmt_action(dtp
, sdp
);
407 dt_action_difconst(ap
, anp
->dn_ident
->di_id
, DTRACEACT_LIBACT
);
410 ap
->dtad_arg
= DT_ACT_DENORMALIZE
;
414 ap
->dtad_arg
= DT_ACT_NORMALIZE
;
416 assert(normal
!= NULL
);
417 ap
= dt_stmt_action(dtp
, sdp
);
418 dt_cg(yypcb
, normal
);
420 ap
->dtad_difo
= dt_as(yypcb
);
421 ap
->dtad_kind
= DTRACEACT_LIBACT
;
422 ap
->dtad_arg
= DT_ACT_NORMALIZE
;
426 dt_action_trunc(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
429 dtrace_actdesc_t
*ap
;
430 dt_node_t
*anp
, *trunc
;
432 char n
[DT_TYPE_NAMELEN
];
435 for (anp
= dnp
->dn_args
; anp
!= NULL
; anp
= anp
->dn_list
)
436 argc
++; /* count up arguments for error messages below */
438 if (argc
> 2 || argc
< 1) {
439 dnerror(dnp
, D_TRUNC_PROTO
,
440 "%s( ) prototype mismatch: %d args passed, %s expected\n",
441 dnp
->dn_ident
->di_name
, argc
,
442 argc
< 1 ? "at least 1" : "no more than 2");
447 trunc
= anp
->dn_list
;
449 if (anp
->dn_kind
!= DT_NODE_AGG
) {
450 dnerror(dnp
, D_TRUNC_AGGARG
,
451 "%s( ) argument #1 is incompatible with prototype:\n"
452 "\tprototype: aggregation\n\t argument: %s\n",
453 dnp
->dn_ident
->di_name
,
454 dt_node_type_name(anp
, n
, sizeof (n
)));
458 assert(trunc
!= NULL
);
459 if (!dt_node_is_scalar(trunc
)) {
460 dnerror(dnp
, D_TRUNC_SCALAR
,
461 "%s( ) argument #2 must be of scalar type\n",
462 dnp
->dn_ident
->di_name
);
468 if (aid
->di_gen
== dtp
->dt_gen
&& !(aid
->di_flags
& DT_IDFLG_MOD
)) {
469 dnerror(dnp
, D_TRUNC_AGGBAD
,
470 "undefined aggregation: @%s\n", aid
->di_name
);
473 ap
= dt_stmt_action(dtp
, sdp
);
474 dt_action_difconst(ap
, anp
->dn_ident
->di_id
, DTRACEACT_LIBACT
);
475 ap
->dtad_arg
= DT_ACT_TRUNC
;
477 ap
= dt_stmt_action(dtp
, sdp
);
480 dt_action_difconst(ap
, 0, DTRACEACT_LIBACT
);
482 assert(trunc
!= NULL
);
484 ap
->dtad_difo
= dt_as(yypcb
);
485 ap
->dtad_kind
= DTRACEACT_LIBACT
;
488 ap
->dtad_arg
= DT_ACT_TRUNC
;
492 dt_action_printa(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
494 dt_ident_t
*aid
, *fid
;
495 dtrace_actdesc_t
*ap
;
497 dt_node_t
*anp
, *proto
= NULL
;
499 char n
[DT_TYPE_NAMELEN
];
500 int argc
= 0, argr
= 0;
502 for (anp
= dnp
->dn_args
; anp
!= NULL
; anp
= anp
->dn_list
)
503 argc
++; /* count up arguments for error messages below */
505 switch (dnp
->dn_args
->dn_kind
) {
507 format
= dnp
->dn_args
->dn_string
;
508 anp
= dnp
->dn_args
->dn_list
;
523 dnerror(dnp
, D_PRINTA_PROTO
,
524 "%s( ) prototype mismatch: %d args passed, %d expected\n",
525 dnp
->dn_ident
->di_name
, argc
, argr
);
530 while (anp
!= NULL
) {
531 if (anp
->dn_kind
!= DT_NODE_AGG
) {
532 dnerror(dnp
, D_PRINTA_AGGARG
,
533 "%s( ) argument #%d is incompatible with "
534 "prototype:\n\tprototype: aggregation\n"
535 "\t argument: %s\n", dnp
->dn_ident
->di_name
, argr
,
536 dt_node_type_name(anp
, n
, sizeof (n
)));
542 if (aid
->di_gen
== dtp
->dt_gen
&&
543 !(aid
->di_flags
& DT_IDFLG_MOD
)) {
544 dnerror(dnp
, D_PRINTA_AGGBAD
,
545 "undefined aggregation: @%s\n", aid
->di_name
);
549 * If we have multiple aggregations, we must be sure that
550 * their key signatures match.
553 dt_printa_validate(proto
, anp
);
558 if (format
!= NULL
) {
559 yylineno
= dnp
->dn_line
;
562 dt_printf_create(yypcb
->pcb_hdl
, format
);
563 dt_printf_validate(sdp
->dtsd_fmtdata
,
564 DT_PRINTF_AGGREGATION
, dnp
->dn_ident
, 1,
565 fid
->di_id
, ((dt_idsig_t
*)aid
->di_data
)->dis_args
);
569 ap
= dt_stmt_action(dtp
, sdp
);
570 dt_action_difconst(ap
, anp
->dn_ident
->di_id
, DTRACEACT_PRINTA
);
578 dt_action_printflike(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
,
579 dtrace_actkind_t kind
)
581 dt_node_t
*anp
, *arg1
;
582 dtrace_actdesc_t
*ap
= NULL
;
583 char n
[DT_TYPE_NAMELEN
], *str
;
585 assert(DTRACEACT_ISPRINTFLIKE(kind
));
587 if (dnp
->dn_args
->dn_kind
!= DT_NODE_STRING
) {
588 dnerror(dnp
, D_PRINTF_ARG_FMT
,
589 "%s( ) argument #1 is incompatible with prototype:\n"
590 "\tprototype: string constant\n\t argument: %s\n",
591 dnp
->dn_ident
->di_name
,
592 dt_node_type_name(dnp
->dn_args
, n
, sizeof (n
)));
595 arg1
= dnp
->dn_args
->dn_list
;
596 yylineno
= dnp
->dn_line
;
597 str
= dnp
->dn_args
->dn_string
;
601 * If this is an freopen(), we use an empty string to denote that
602 * stdout should be restored. For other printf()-like actions, an
603 * empty format string is illegal: an empty format string would
604 * result in malformed DOF, and the compiler thus flags an empty
605 * format string as a compile-time error. To avoid propagating the
606 * freopen() special case throughout the system, we simply transpose
607 * an empty string into a sentinel string (DT_FREOPEN_RESTORE) that
608 * denotes that stdout should be restored.
610 if (kind
== DTRACEACT_FREOPEN
) {
611 if (strcmp(str
, DT_FREOPEN_RESTORE
) == 0) {
613 * Our sentinel is always an invalid argument to
614 * freopen(), but if it's been manually specified, we
615 * must fail now instead of when the freopen() is
616 * actually evaluated.
618 dnerror(dnp
, D_FREOPEN_INVALID
,
619 "%s( ) argument #1 cannot be \"%s\"\n",
620 dnp
->dn_ident
->di_name
, DT_FREOPEN_RESTORE
);
624 str
= DT_FREOPEN_RESTORE
;
627 sdp
->dtsd_fmtdata
= dt_printf_create(dtp
, str
);
629 dt_printf_validate(sdp
->dtsd_fmtdata
, DT_PRINTF_EXACTLEN
,
630 dnp
->dn_ident
, 1, DTRACEACT_AGGREGATION
, arg1
);
636 if ((dbuf
= dt_alloc(dtp
, sizeof (dif_instr_t
))) == NULL
||
637 (dp
= dt_zalloc(dtp
, sizeof (dtrace_difo_t
))) == NULL
) {
639 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
642 dbuf
[0] = DIF_INSTR_RET(DIF_REG_R0
); /* ret %r0 */
646 dp
->dtdo_rtype
= dt_int_rtype
;
648 ap
= dt_stmt_action(dtp
, sdp
);
650 ap
->dtad_kind
= kind
;
654 for (anp
= arg1
; anp
!= NULL
; anp
= anp
->dn_list
) {
655 ap
= dt_stmt_action(dtp
, sdp
);
657 ap
->dtad_difo
= dt_as(yypcb
);
658 ap
->dtad_kind
= kind
;
663 dt_action_trace(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
667 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
668 boolean_t istrace
= (dnp
->dn_ident
->di_id
== DT_ACT_TRACE
);
669 const char *act
= istrace
? "trace" : "print";
671 if (dt_node_is_void(dnp
->dn_args
)) {
672 dnerror(dnp
->dn_args
, istrace
? D_TRACE_VOID
: D_PRINT_VOID
,
673 "%s( ) may not be applied to a void expression\n", act
);
676 if (dt_node_resolve(dnp
->dn_args
, DT_IDENT_XLPTR
) != NULL
) {
677 dnerror(dnp
->dn_args
, istrace
? D_TRACE_DYN
: D_PRINT_DYN
,
678 "%s( ) may not be applied to a translated pointer\n", act
);
681 if (dnp
->dn_args
->dn_kind
== DT_NODE_AGG
) {
682 dnerror(dnp
->dn_args
, istrace
? D_TRACE_AGG
: D_PRINT_AGG
,
683 "%s( ) may not be applied to an aggregation%s\n", act
,
684 istrace
? "" : " -- did you mean printa()?");
687 dt_cg(yypcb
, dnp
->dn_args
);
690 * The print() action behaves identically to trace(), except that it
691 * stores the CTF type of the argument (if present) within the DOF for
692 * the DIFEXPR action. To do this, we set the 'dtsd_strdata' to point
693 * to the fully-qualified CTF type ID for the result of the DIF
694 * action. We use the ID instead of the name to handles complex types
695 * like arrays and function pointers that can't be resolved by
696 * ctf_type_lookup(). This is later processed by dtrace_dof_create()
697 * and turned into a reference into the string table so that we can
698 * get the type information when we process the data after the fact. In
699 * the case where we are referring to userland CTF data, we also need to
700 * to identify which ctf container in question we care about and encode
701 * that within the name.
703 if (dnp
->dn_ident
->di_id
== DT_ACT_PRINT
) {
708 dret
= yypcb
->pcb_dret
;
709 dmp
= dt_module_lookup_by_ctf(dtp
, dret
->dn_ctfp
);
711 if (dmp
->dm_pid
!= 0) {
712 ctflib
= dt_module_getlibid(dtp
, dmp
, dret
->dn_ctfp
);
714 n
= snprintf(NULL
, 0, "%s`%d`%d", dmp
->dm_name
,
715 ctflib
, dret
->dn_type
) + 1;
717 n
= snprintf(NULL
, 0, "%s`%d", dmp
->dm_name
,
720 sdp
->dtsd_strdata
= dt_alloc(dtp
, n
);
721 if (sdp
->dtsd_strdata
== NULL
)
722 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
723 if (dmp
->dm_pid
!= 0) {
724 (void) snprintf(sdp
->dtsd_strdata
, n
, "%s`%d`%d",
725 dmp
->dm_name
, ctflib
, dret
->dn_type
);
727 (void) snprintf(sdp
->dtsd_strdata
, n
, "%s`%d",
728 dmp
->dm_name
, dret
->dn_type
);
732 ap
->dtad_difo
= dt_as(yypcb
);
733 ap
->dtad_kind
= DTRACEACT_DIFEXPR
;
737 dt_action_tracemem(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
739 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
741 dt_node_t
*addr
= dnp
->dn_args
;
742 dt_node_t
*max
= dnp
->dn_args
->dn_list
;
745 char n
[DT_TYPE_NAMELEN
];
747 if (dt_node_is_integer(addr
) == 0 && dt_node_is_pointer(addr
) == 0) {
748 dnerror(addr
, D_TRACEMEM_ADDR
,
749 "tracemem( ) argument #1 is incompatible with "
750 "prototype:\n\tprototype: pointer or integer\n"
752 dt_node_type_name(addr
, n
, sizeof (n
)));
755 if (dt_node_is_posconst(max
) == 0) {
756 dnerror(max
, D_TRACEMEM_SIZE
, "tracemem( ) argument #2 must "
757 "be a non-zero positive integral constant expression\n");
760 if ((size
= max
->dn_list
) != NULL
) {
761 if (size
->dn_list
!= NULL
) {
762 dnerror(size
, D_TRACEMEM_ARGS
, "tracemem ( ) prototype "
763 "mismatch: expected at most 3 args\n");
766 if (!dt_node_is_scalar(size
)) {
767 dnerror(size
, D_TRACEMEM_DYNSIZE
, "tracemem ( ) "
768 "dynamic size (argument #3) must be of "
773 ap
->dtad_difo
= dt_as(yypcb
);
774 ap
->dtad_difo
->dtdo_rtype
= dt_int_rtype
;
775 ap
->dtad_kind
= DTRACEACT_TRACEMEM_DYNSIZE
;
777 ap
= dt_stmt_action(dtp
, sdp
);
781 ap
->dtad_difo
= dt_as(yypcb
);
782 ap
->dtad_kind
= DTRACEACT_TRACEMEM
;
784 ap
->dtad_difo
->dtdo_rtype
.dtdt_flags
|= DIF_TF_BYREF
;
785 ap
->dtad_difo
->dtdo_rtype
.dtdt_size
= max
->dn_value
;
789 dt_action_stack_args(dtrace_hdl_t
*dtp
, dtrace_actdesc_t
*ap
, dt_node_t
*arg0
)
791 ap
->dtad_kind
= DTRACEACT_STACK
;
793 if (dtp
->dt_options
[DTRACEOPT_STACKFRAMES
] != DTRACEOPT_UNSET
) {
794 ap
->dtad_arg
= dtp
->dt_options
[DTRACEOPT_STACKFRAMES
];
800 if (arg0
->dn_list
!= NULL
) {
801 dnerror(arg0
, D_STACK_PROTO
, "stack( ) prototype "
802 "mismatch: too many arguments\n");
805 if (dt_node_is_posconst(arg0
) == 0) {
806 dnerror(arg0
, D_STACK_SIZE
, "stack( ) size must be a "
807 "non-zero positive integral constant expression\n");
810 ap
->dtad_arg
= arg0
->dn_value
;
815 dt_action_stack(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
817 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
818 dt_action_stack_args(dtp
, ap
, dnp
->dn_args
);
822 dt_action_ustack_args(dtrace_hdl_t
*dtp
, dtrace_actdesc_t
*ap
, dt_node_t
*dnp
)
824 uint32_t nframes
= 0;
825 uint32_t strsize
= 0; /* default string table size */
826 dt_node_t
*arg0
= dnp
->dn_args
;
827 dt_node_t
*arg1
= arg0
!= NULL
? arg0
->dn_list
: NULL
;
829 assert(dnp
->dn_ident
->di_id
== DT_ACT_JSTACK
||
830 dnp
->dn_ident
->di_id
== DT_ACT_USTACK
);
832 if (dnp
->dn_ident
->di_id
== DT_ACT_JSTACK
) {
833 if (dtp
->dt_options
[DTRACEOPT_JSTACKFRAMES
] != DTRACEOPT_UNSET
)
834 nframes
= dtp
->dt_options
[DTRACEOPT_JSTACKFRAMES
];
836 if (dtp
->dt_options
[DTRACEOPT_JSTACKSTRSIZE
] != DTRACEOPT_UNSET
)
837 strsize
= dtp
->dt_options
[DTRACEOPT_JSTACKSTRSIZE
];
839 ap
->dtad_kind
= DTRACEACT_JSTACK
;
841 assert(dnp
->dn_ident
->di_id
== DT_ACT_USTACK
);
843 if (dtp
->dt_options
[DTRACEOPT_USTACKFRAMES
] != DTRACEOPT_UNSET
)
844 nframes
= dtp
->dt_options
[DTRACEOPT_USTACKFRAMES
];
846 ap
->dtad_kind
= DTRACEACT_USTACK
;
850 if (!dt_node_is_posconst(arg0
)) {
851 dnerror(arg0
, D_USTACK_FRAMES
, "ustack( ) argument #1 "
852 "must be a non-zero positive integer constant\n");
854 nframes
= (uint32_t)arg0
->dn_value
;
858 if (arg1
->dn_kind
!= DT_NODE_INT
||
859 ((arg1
->dn_flags
& DT_NF_SIGNED
) &&
860 (int64_t)arg1
->dn_value
< 0)) {
861 dnerror(arg1
, D_USTACK_STRSIZE
, "ustack( ) argument #2 "
862 "must be a positive integer constant\n");
865 if (arg1
->dn_list
!= NULL
) {
866 dnerror(arg1
, D_USTACK_PROTO
, "ustack( ) prototype "
867 "mismatch: too many arguments\n");
870 strsize
= (uint32_t)arg1
->dn_value
;
873 ap
->dtad_arg
= DTRACE_USTACK_ARG(nframes
, strsize
);
877 dt_action_ustack(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
879 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
880 dt_action_ustack_args(dtp
, ap
, dnp
);
884 dt_action_setopt(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
886 dtrace_actdesc_t
*ap
;
887 dt_node_t
*arg0
, *arg1
;
890 * The prototype guarantees that we are called with either one or
891 * two arguments, and that any arguments that are present are strings.
894 arg1
= arg0
->dn_list
;
896 ap
= dt_stmt_action(dtp
, sdp
);
898 ap
->dtad_difo
= dt_as(yypcb
);
899 ap
->dtad_kind
= DTRACEACT_LIBACT
;
900 ap
->dtad_arg
= DT_ACT_SETOPT
;
902 ap
= dt_stmt_action(dtp
, sdp
);
905 dt_action_difconst(ap
, 0, DTRACEACT_LIBACT
);
908 ap
->dtad_difo
= dt_as(yypcb
);
909 ap
->dtad_kind
= DTRACEACT_LIBACT
;
912 ap
->dtad_arg
= DT_ACT_SETOPT
;
917 dt_action_symmod_args(dtrace_hdl_t
*dtp
, dtrace_actdesc_t
*ap
,
918 dt_node_t
*dnp
, dtrace_actkind_t kind
)
920 assert(kind
== DTRACEACT_SYM
|| kind
== DTRACEACT_MOD
||
921 kind
== DTRACEACT_USYM
|| kind
== DTRACEACT_UMOD
||
922 kind
== DTRACEACT_UADDR
);
925 ap
->dtad_difo
= dt_as(yypcb
);
926 ap
->dtad_kind
= kind
;
927 ap
->dtad_difo
->dtdo_rtype
.dtdt_size
= sizeof (uint64_t);
931 dt_action_symmod(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
,
932 dtrace_actkind_t kind
)
934 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
935 dt_action_symmod_args(dtp
, ap
, dnp
->dn_args
, kind
);
940 dt_action_ftruncate(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
942 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
945 * Library actions need a DIFO that serves as an argument. As
946 * ftruncate() doesn't take an argument, we generate the constant 0
947 * in a DIFO; this constant will be ignored when the ftruncate() is
950 dt_action_difconst(ap
, 0, DTRACEACT_LIBACT
);
951 ap
->dtad_arg
= DT_ACT_FTRUNCATE
;
956 dt_action_stop(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
958 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
960 ap
->dtad_kind
= DTRACEACT_STOP
;
966 dt_action_breakpoint(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
968 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
970 ap
->dtad_kind
= DTRACEACT_BREAKPOINT
;
976 dt_action_panic(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
978 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
980 ap
->dtad_kind
= DTRACEACT_PANIC
;
985 dt_action_chill(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
987 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
989 dt_cg(yypcb
, dnp
->dn_args
);
990 ap
->dtad_difo
= dt_as(yypcb
);
991 ap
->dtad_kind
= DTRACEACT_CHILL
;
995 dt_action_raise(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
997 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
999 dt_cg(yypcb
, dnp
->dn_args
);
1000 ap
->dtad_difo
= dt_as(yypcb
);
1001 ap
->dtad_kind
= DTRACEACT_RAISE
;
1005 dt_action_exit(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
1007 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
1009 dt_cg(yypcb
, dnp
->dn_args
);
1010 ap
->dtad_difo
= dt_as(yypcb
);
1011 ap
->dtad_kind
= DTRACEACT_EXIT
;
1012 ap
->dtad_difo
->dtdo_rtype
.dtdt_size
= sizeof (int);
1016 dt_action_speculate(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
1018 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
1020 dt_cg(yypcb
, dnp
->dn_args
);
1021 ap
->dtad_difo
= dt_as(yypcb
);
1022 ap
->dtad_kind
= DTRACEACT_SPECULATE
;
1026 dt_action_commit(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
1028 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
1030 dt_cg(yypcb
, dnp
->dn_args
);
1031 ap
->dtad_difo
= dt_as(yypcb
);
1032 ap
->dtad_kind
= DTRACEACT_COMMIT
;
1036 dt_action_discard(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
1038 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
1040 dt_cg(yypcb
, dnp
->dn_args
);
1041 ap
->dtad_difo
= dt_as(yypcb
);
1042 ap
->dtad_kind
= DTRACEACT_DISCARD
;
1046 dt_compile_fun(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
1048 switch (dnp
->dn_expr
->dn_ident
->di_id
) {
1049 case DT_ACT_BREAKPOINT
:
1050 dt_action_breakpoint(dtp
, dnp
->dn_expr
, sdp
);
1053 dt_action_chill(dtp
, dnp
->dn_expr
, sdp
);
1056 dt_action_clear(dtp
, dnp
->dn_expr
, sdp
);
1059 dt_action_commit(dtp
, dnp
->dn_expr
, sdp
);
1061 case DT_ACT_DENORMALIZE
:
1062 dt_action_normalize(dtp
, dnp
->dn_expr
, sdp
);
1064 case DT_ACT_DISCARD
:
1065 dt_action_discard(dtp
, dnp
->dn_expr
, sdp
);
1068 dt_action_exit(dtp
, dnp
->dn_expr
, sdp
);
1070 case DT_ACT_FREOPEN
:
1071 dt_action_printflike(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_FREOPEN
);
1073 case DT_ACT_FTRUNCATE
:
1074 dt_action_ftruncate(dtp
, dnp
->dn_expr
, sdp
);
1077 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_MOD
);
1079 case DT_ACT_NORMALIZE
:
1080 dt_action_normalize(dtp
, dnp
->dn_expr
, sdp
);
1083 dt_action_panic(dtp
, dnp
->dn_expr
, sdp
);
1086 dt_action_trace(dtp
, dnp
->dn_expr
, sdp
);
1089 dt_action_printa(dtp
, dnp
->dn_expr
, sdp
);
1092 dt_action_printflike(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_PRINTF
);
1095 dt_action_raise(dtp
, dnp
->dn_expr
, sdp
);
1098 dt_action_setopt(dtp
, dnp
->dn_expr
, sdp
);
1100 case DT_ACT_SPECULATE
:
1101 dt_action_speculate(dtp
, dnp
->dn_expr
, sdp
);
1104 dt_action_stack(dtp
, dnp
->dn_expr
, sdp
);
1107 dt_action_stop(dtp
, dnp
->dn_expr
, sdp
);
1110 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_SYM
);
1113 dt_action_printflike(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_SYSTEM
);
1116 dt_action_trace(dtp
, dnp
->dn_expr
, sdp
);
1118 case DT_ACT_TRACEMEM
:
1119 dt_action_tracemem(dtp
, dnp
->dn_expr
, sdp
);
1122 dt_action_trunc(dtp
, dnp
->dn_expr
, sdp
);
1125 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_UADDR
);
1128 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_UMOD
);
1131 dt_action_symmod(dtp
, dnp
->dn_expr
, sdp
, DTRACEACT_USYM
);
1135 dt_action_ustack(dtp
, dnp
->dn_expr
, sdp
);
1138 dnerror(dnp
->dn_expr
, D_UNKNOWN
, "tracing function %s( ) is "
1139 "not yet supported\n", dnp
->dn_expr
->dn_ident
->di_name
);
1144 dt_compile_exp(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
1146 dtrace_actdesc_t
*ap
= dt_stmt_action(dtp
, sdp
);
1148 dt_cg(yypcb
, dnp
->dn_expr
);
1149 ap
->dtad_difo
= dt_as(yypcb
);
1150 ap
->dtad_difo
->dtdo_rtype
= dt_void_rtype
;
1151 ap
->dtad_kind
= DTRACEACT_DIFEXPR
;
1155 dt_compile_agg(dtrace_hdl_t
*dtp
, dt_node_t
*dnp
, dtrace_stmtdesc_t
*sdp
)
1157 dt_ident_t
*aid
, *fid
;
1158 dt_node_t
*anp
, *incr
= NULL
;
1159 dtrace_actdesc_t
*ap
;
1160 uint_t n
= 1, argmax
;
1164 * If the aggregation has no aggregating function applied to it, then
1165 * this statement has no effect. Flag this as a programming error.
1167 if (dnp
->dn_aggfun
== NULL
) {
1168 dnerror(dnp
, D_AGG_NULL
, "expression has null effect: @%s\n",
1169 dnp
->dn_ident
->di_name
);
1172 aid
= dnp
->dn_ident
;
1173 fid
= dnp
->dn_aggfun
->dn_ident
;
1175 if (dnp
->dn_aggfun
->dn_args
!= NULL
&&
1176 dt_node_is_scalar(dnp
->dn_aggfun
->dn_args
) == 0) {
1177 dnerror(dnp
->dn_aggfun
, D_AGG_SCALAR
, "%s( ) argument #1 must "
1178 "be of scalar type\n", fid
->di_name
);
1182 * The ID of the aggregation itself is implicitly recorded as the first
1183 * member of each aggregation tuple so we can distinguish them later.
1185 ap
= dt_stmt_action(dtp
, sdp
);
1186 dt_action_difconst(ap
, aid
->di_id
, DTRACEACT_DIFEXPR
);
1188 for (anp
= dnp
->dn_aggtup
; anp
!= NULL
; anp
= anp
->dn_list
) {
1189 ap
= dt_stmt_action(dtp
, sdp
);
1192 if (anp
->dn_kind
== DT_NODE_FUNC
) {
1193 if (anp
->dn_ident
->di_id
== DT_ACT_STACK
) {
1194 dt_action_stack_args(dtp
, ap
, anp
->dn_args
);
1198 if (anp
->dn_ident
->di_id
== DT_ACT_USTACK
||
1199 anp
->dn_ident
->di_id
== DT_ACT_JSTACK
) {
1200 dt_action_ustack_args(dtp
, ap
, anp
);
1204 switch (anp
->dn_ident
->di_id
) {
1206 dt_action_symmod_args(dtp
, ap
,
1207 anp
->dn_args
, DTRACEACT_UADDR
);
1211 dt_action_symmod_args(dtp
, ap
,
1212 anp
->dn_args
, DTRACEACT_USYM
);
1216 dt_action_symmod_args(dtp
, ap
,
1217 anp
->dn_args
, DTRACEACT_UMOD
);
1221 dt_action_symmod_args(dtp
, ap
,
1222 anp
->dn_args
, DTRACEACT_SYM
);
1226 dt_action_symmod_args(dtp
, ap
,
1227 anp
->dn_args
, DTRACEACT_MOD
);
1236 ap
->dtad_difo
= dt_as(yypcb
);
1237 ap
->dtad_kind
= DTRACEACT_DIFEXPR
;
1240 if (fid
->di_id
== DTRACEAGG_LQUANTIZE
) {
1242 * For linear quantization, we have between two and four
1243 * arguments in addition to the expression:
1245 * arg1 => Base value
1246 * arg2 => Limit value
1247 * arg3 => Quantization level step size (defaults to 1)
1248 * arg4 => Quantization increment value (defaults to 1)
1250 dt_node_t
*arg1
= dnp
->dn_aggfun
->dn_args
->dn_list
;
1251 dt_node_t
*arg2
= arg1
->dn_list
;
1252 dt_node_t
*arg3
= arg2
->dn_list
;
1254 uint64_t nlevels
, step
= 1, oarg
;
1255 int64_t baseval
, limitval
;
1257 if (arg1
->dn_kind
!= DT_NODE_INT
) {
1258 dnerror(arg1
, D_LQUANT_BASETYPE
, "lquantize( ) "
1259 "argument #1 must be an integer constant\n");
1262 baseval
= (int64_t)arg1
->dn_value
;
1264 if (baseval
< INT32_MIN
|| baseval
> INT32_MAX
) {
1265 dnerror(arg1
, D_LQUANT_BASEVAL
, "lquantize( ) "
1266 "argument #1 must be a 32-bit quantity\n");
1269 if (arg2
->dn_kind
!= DT_NODE_INT
) {
1270 dnerror(arg2
, D_LQUANT_LIMTYPE
, "lquantize( ) "
1271 "argument #2 must be an integer constant\n");
1274 limitval
= (int64_t)arg2
->dn_value
;
1276 if (limitval
< INT32_MIN
|| limitval
> INT32_MAX
) {
1277 dnerror(arg2
, D_LQUANT_LIMVAL
, "lquantize( ) "
1278 "argument #2 must be a 32-bit quantity\n");
1281 if (limitval
< baseval
) {
1282 dnerror(dnp
, D_LQUANT_MISMATCH
,
1283 "lquantize( ) base (argument #1) must be less "
1284 "than limit (argument #2)\n");
1288 if (!dt_node_is_posconst(arg3
)) {
1289 dnerror(arg3
, D_LQUANT_STEPTYPE
, "lquantize( ) "
1290 "argument #3 must be a non-zero positive "
1291 "integer constant\n");
1294 if ((step
= arg3
->dn_value
) > UINT16_MAX
) {
1295 dnerror(arg3
, D_LQUANT_STEPVAL
, "lquantize( ) "
1296 "argument #3 must be a 16-bit quantity\n");
1300 nlevels
= (limitval
- baseval
) / step
;
1303 dnerror(dnp
, D_LQUANT_STEPLARGE
,
1304 "lquantize( ) step (argument #3) too large: must "
1305 "have at least one quantization level\n");
1308 if (nlevels
> UINT16_MAX
) {
1309 dnerror(dnp
, D_LQUANT_STEPSMALL
, "lquantize( ) step "
1310 "(argument #3) too small: number of quantization "
1311 "levels must be a 16-bit quantity\n");
1314 arg
= (step
<< DTRACE_LQUANTIZE_STEPSHIFT
) |
1315 (nlevels
<< DTRACE_LQUANTIZE_LEVELSHIFT
) |
1316 ((baseval
<< DTRACE_LQUANTIZE_BASESHIFT
) &
1317 DTRACE_LQUANTIZE_BASEMASK
);
1321 isp
= (dt_idsig_t
*)aid
->di_data
;
1323 if (isp
->dis_auxinfo
== 0) {
1325 * This is the first time we've seen an lquantize()
1326 * for this aggregation; we'll store our argument
1327 * as the auxiliary signature information.
1329 isp
->dis_auxinfo
= arg
;
1330 } else if ((oarg
= isp
->dis_auxinfo
) != arg
) {
1332 * If we have seen this lquantize() before and the
1333 * argument doesn't match the original argument, pick
1334 * the original argument apart to concisely report the
1337 int obaseval
= DTRACE_LQUANTIZE_BASE(oarg
);
1338 int onlevels
= DTRACE_LQUANTIZE_LEVELS(oarg
);
1339 int ostep
= DTRACE_LQUANTIZE_STEP(oarg
);
1341 if (obaseval
!= baseval
) {
1342 dnerror(dnp
, D_LQUANT_MATCHBASE
, "lquantize( ) "
1343 "base (argument #1) doesn't match previous "
1344 "declaration: expected %d, found %d\n",
1345 obaseval
, (int)baseval
);
1348 if (onlevels
* ostep
!= nlevels
* step
) {
1349 dnerror(dnp
, D_LQUANT_MATCHLIM
, "lquantize( ) "
1350 "limit (argument #2) doesn't match previous"
1351 " declaration: expected %d, found %d\n",
1352 obaseval
+ onlevels
* ostep
,
1353 (int)baseval
+ (int)nlevels
* (int)step
);
1356 if (ostep
!= step
) {
1357 dnerror(dnp
, D_LQUANT_MATCHSTEP
, "lquantize( ) "
1358 "step (argument #3) doesn't match previous "
1359 "declaration: expected %d, found %d\n",
1364 * We shouldn't be able to get here -- one of the
1365 * parameters must be mismatched if the arguments
1371 incr
= arg3
!= NULL
? arg3
->dn_list
: NULL
;
1375 if (fid
->di_id
== DTRACEAGG_LLQUANTIZE
) {
1377 * For log/linear quantizations, we have between one and five
1378 * arguments in addition to the expression:
1381 * arg2 => Low magnitude
1382 * arg3 => High magnitude
1383 * arg4 => Number of steps per magnitude
1384 * arg5 => Quantization increment value (defaults to 1)
1386 dt_node_t
*llarg
= dnp
->dn_aggfun
->dn_args
->dn_list
;
1387 uint64_t oarg
, order
, v
;
1392 char *str
; /* string identifier */
1393 int badtype
; /* error on bad type */
1394 int badval
; /* error on bad value */
1395 int mismatch
; /* error on bad match */
1396 int shift
; /* shift value */
1397 uint16_t value
; /* value itself */
1399 { "factor", D_LLQUANT_FACTORTYPE
,
1400 D_LLQUANT_FACTORVAL
, D_LLQUANT_FACTORMATCH
,
1401 DTRACE_LLQUANTIZE_FACTORSHIFT
},
1402 { "low magnitude", D_LLQUANT_LOWTYPE
,
1403 D_LLQUANT_LOWVAL
, D_LLQUANT_LOWMATCH
,
1404 DTRACE_LLQUANTIZE_LOWSHIFT
},
1405 { "high magnitude", D_LLQUANT_HIGHTYPE
,
1406 D_LLQUANT_HIGHVAL
, D_LLQUANT_HIGHMATCH
,
1407 DTRACE_LLQUANTIZE_HIGHSHIFT
},
1408 { "linear steps per magnitude", D_LLQUANT_NSTEPTYPE
,
1409 D_LLQUANT_NSTEPVAL
, D_LLQUANT_NSTEPMATCH
,
1410 DTRACE_LLQUANTIZE_NSTEPSHIFT
},
1416 for (i
= 0; args
[i
].str
!= NULL
; i
++) {
1417 if (llarg
->dn_kind
!= DT_NODE_INT
) {
1418 dnerror(llarg
, args
[i
].badtype
, "llquantize( ) "
1419 "argument #%d (%s) must be an "
1420 "integer constant\n", i
+ 1, args
[i
].str
);
1423 if ((uint64_t)llarg
->dn_value
> UINT16_MAX
) {
1424 dnerror(llarg
, args
[i
].badval
, "llquantize( ) "
1425 "argument #%d (%s) must be an unsigned "
1426 "16-bit quantity\n", i
+ 1, args
[i
].str
);
1429 args
[i
].value
= (uint16_t)llarg
->dn_value
;
1431 assert(!(arg
& (UINT16_MAX
<< args
[i
].shift
)));
1432 arg
|= ((uint64_t)args
[i
].value
<< args
[i
].shift
);
1433 llarg
= llarg
->dn_list
;
1438 if (args
[0].value
< 2) {
1439 dnerror(dnp
, D_LLQUANT_FACTORSMALL
, "llquantize( ) "
1440 "factor (argument #1) must be two or more\n");
1443 if (args
[1].value
>= args
[2].value
) {
1444 dnerror(dnp
, D_LLQUANT_MAGRANGE
, "llquantize( ) "
1445 "high magnitude (argument #3) must be greater "
1446 "than low magnitude (argument #2)\n");
1449 if (args
[3].value
< args
[0].value
) {
1450 dnerror(dnp
, D_LLQUANT_FACTORNSTEPS
, "llquantize( ) "
1451 "factor (argument #1) must be less than or "
1452 "equal to the number of linear steps per "
1453 "magnitude (argument #4)\n");
1456 for (v
= args
[0].value
; v
< args
[3].value
; v
*= args
[0].value
)
1459 if ((args
[3].value
% args
[0].value
) || (v
% args
[3].value
)) {
1460 dnerror(dnp
, D_LLQUANT_FACTOREVEN
, "llquantize( ) "
1461 "factor (argument #1) must evenly divide the "
1462 "number of steps per magnitude (argument #4), "
1463 "and the number of steps per magnitude must evenly "
1464 "divide a power of the factor\n");
1467 for (i
= 0, order
= 1; i
< args
[2].value
; i
++) {
1468 if (order
* args
[0].value
> order
) {
1469 order
*= args
[0].value
;
1473 dnerror(dnp
, D_LLQUANT_MAGTOOBIG
, "llquantize( ) "
1474 "factor (%d) raised to power of high magnitude "
1475 "(%d) overflows 64-bits\n", args
[0].value
,
1479 isp
= (dt_idsig_t
*)aid
->di_data
;
1481 if (isp
->dis_auxinfo
== 0) {
1483 * This is the first time we've seen an llquantize()
1484 * for this aggregation; we'll store our argument
1485 * as the auxiliary signature information.
1487 isp
->dis_auxinfo
= arg
;
1488 } else if ((oarg
= isp
->dis_auxinfo
) != arg
) {
1490 * If we have seen this llquantize() before and the
1491 * argument doesn't match the original argument, pick
1492 * the original argument apart to concisely report the
1495 int expected
= 0, found
= 0;
1497 for (i
= 0; expected
== found
; i
++) {
1498 assert(args
[i
].str
!= NULL
);
1500 expected
= (oarg
>> args
[i
].shift
) & UINT16_MAX
;
1501 found
= (arg
>> args
[i
].shift
) & UINT16_MAX
;
1504 dnerror(dnp
, args
[i
- 1].mismatch
, "llquantize( ) "
1505 "%s (argument #%d) doesn't match previous "
1506 "declaration: expected %d, found %d\n",
1507 args
[i
- 1].str
, i
, expected
, found
);
1514 if (fid
->di_id
== DTRACEAGG_QUANTIZE
) {
1515 incr
= dnp
->dn_aggfun
->dn_args
->dn_list
;
1520 if (!dt_node_is_scalar(incr
)) {
1521 dnerror(dnp
, D_PROTO_ARG
, "%s( ) increment value "
1522 "(argument #%d) must be of scalar type\n",
1523 fid
->di_name
, argmax
);
1526 if ((anp
= incr
->dn_list
) != NULL
) {
1529 for (; anp
!= NULL
; anp
= anp
->dn_list
)
1532 dnerror(incr
, D_PROTO_LEN
, "%s( ) prototype "
1533 "mismatch: %d args passed, at most %d expected",
1534 fid
->di_name
, argc
, argmax
);
1537 ap
= dt_stmt_action(dtp
, sdp
);
1541 ap
->dtad_difo
= dt_as(yypcb
);
1542 ap
->dtad_difo
->dtdo_rtype
= dt_void_rtype
;
1543 ap
->dtad_kind
= DTRACEACT_DIFEXPR
;
1546 assert(sdp
->dtsd_aggdata
== NULL
);
1547 sdp
->dtsd_aggdata
= aid
;
1549 ap
= dt_stmt_action(dtp
, sdp
);
1550 assert(fid
->di_kind
== DT_IDENT_AGGFUNC
);
1551 assert(DTRACEACT_ISAGG(fid
->di_id
));
1552 ap
->dtad_kind
= fid
->di_id
;
1553 ap
->dtad_ntuple
= n
;
1556 if (dnp
->dn_aggfun
->dn_args
!= NULL
) {
1557 dt_cg(yypcb
, dnp
->dn_aggfun
->dn_args
);
1558 ap
->dtad_difo
= dt_as(yypcb
);
1563 dt_compile_one_clause(dtrace_hdl_t
*dtp
, dt_node_t
*cnp
, dt_node_t
*pnp
)
1565 dtrace_ecbdesc_t
*edp
;
1566 dtrace_stmtdesc_t
*sdp
;
1569 yylineno
= pnp
->dn_line
;
1570 dt_setcontext(dtp
, pnp
->dn_desc
);
1571 (void) dt_node_cook(cnp
, DT_IDFLG_REF
);
1573 if (DT_TREEDUMP_PASS(dtp
, 2))
1574 dt_node_printr(cnp
, stderr
, 0);
1576 if ((edp
= dt_ecbdesc_create(dtp
, pnp
->dn_desc
)) == NULL
)
1577 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
1579 assert(yypcb
->pcb_ecbdesc
== NULL
);
1580 yypcb
->pcb_ecbdesc
= edp
;
1582 if (cnp
->dn_pred
!= NULL
) {
1583 dt_cg(yypcb
, cnp
->dn_pred
);
1584 edp
->dted_pred
.dtpdd_difo
= dt_as(yypcb
);
1587 if (cnp
->dn_acts
== NULL
) {
1588 dt_stmt_append(dt_stmt_create(dtp
, edp
,
1589 cnp
->dn_ctxattr
, _dtrace_defattr
), cnp
);
1592 for (dnp
= cnp
->dn_acts
; dnp
!= NULL
; dnp
= dnp
->dn_list
) {
1593 assert(yypcb
->pcb_stmt
== NULL
);
1594 sdp
= dt_stmt_create(dtp
, edp
, cnp
->dn_ctxattr
, cnp
->dn_attr
);
1596 switch (dnp
->dn_kind
) {
1598 if (dnp
->dn_expr
->dn_kind
== DT_NODE_AGG
)
1599 dt_compile_agg(dtp
, dnp
->dn_expr
, sdp
);
1601 dt_compile_exp(dtp
, dnp
, sdp
);
1604 dt_compile_fun(dtp
, dnp
, sdp
);
1607 dt_compile_agg(dtp
, dnp
, sdp
);
1610 dnerror(dnp
, D_UNKNOWN
, "internal error -- node kind "
1611 "%u is not a valid statement\n", dnp
->dn_kind
);
1614 assert(yypcb
->pcb_stmt
== sdp
);
1615 dt_stmt_append(sdp
, dnp
);
1618 assert(yypcb
->pcb_ecbdesc
== edp
);
1619 dt_ecbdesc_release(dtp
, edp
);
1621 yypcb
->pcb_ecbdesc
= NULL
;
1625 dt_compile_clause(dtrace_hdl_t
*dtp
, dt_node_t
*cnp
)
1629 for (pnp
= cnp
->dn_pdescs
; pnp
!= NULL
; pnp
= pnp
->dn_list
)
1630 dt_compile_one_clause(dtp
, cnp
, pnp
);
1634 dt_compile_xlator(dt_node_t
*dnp
)
1636 dt_xlator_t
*dxp
= dnp
->dn_xlator
;
1639 for (mnp
= dnp
->dn_members
; mnp
!= NULL
; mnp
= mnp
->dn_list
) {
1640 assert(dxp
->dx_membdif
[mnp
->dn_membid
] == NULL
);
1642 dxp
->dx_membdif
[mnp
->dn_membid
] = dt_as(yypcb
);
1647 dt_setcontext(dtrace_hdl_t
*dtp
, dtrace_probedesc_t
*pdp
)
1649 const dtrace_pattr_t
*pap
;
1657 * Both kernel and pid based providers are allowed to have names
1658 * ending with what could be interpreted as a number. We assume it's
1659 * a pid and that we may need to dynamically create probes for
1662 * (1) The provider doesn't exist, or,
1663 * (2) The provider exists and has DTRACE_PRIV_PROC privilege.
1665 * On an error, dt_pid_create_probes() will set the error message
1666 * and tag -- we just have to longjmp() out of here.
1668 if (isdigit(pdp
->dtpd_provider
[strlen(pdp
->dtpd_provider
) - 1]) &&
1669 ((pvp
= dt_provider_lookup(dtp
, pdp
->dtpd_provider
)) == NULL
||
1670 pvp
->pv_desc
.dtvd_priv
.dtpp_flags
& DTRACE_PRIV_PROC
) &&
1671 dt_pid_create_probes(pdp
, dtp
, yypcb
) != 0) {
1672 longjmp(yypcb
->pcb_jmpbuf
, EDT_COMPILER
);
1676 * Call dt_probe_info() to get the probe arguments and attributes. If
1677 * a representative probe is found, set 'pap' to the probe provider's
1678 * attributes. Otherwise set 'pap' to default Unstable attributes.
1680 if ((prp
= dt_probe_info(dtp
, pdp
, &yypcb
->pcb_pinfo
)) == NULL
) {
1681 pap
= &_dtrace_prvdesc
;
1682 err
= dtrace_errno(dtp
);
1683 bzero(&yypcb
->pcb_pinfo
, sizeof (dtrace_probeinfo_t
));
1684 yypcb
->pcb_pinfo
.dtp_attr
= pap
->dtpa_provider
;
1685 yypcb
->pcb_pinfo
.dtp_arga
= pap
->dtpa_args
;
1687 pap
= &prp
->pr_pvp
->pv_desc
.dtvd_attr
;
1691 if (err
== EDT_NOPROBE
&& !(yypcb
->pcb_cflags
& DTRACE_C_ZDEFS
)) {
1692 xyerror(D_PDESC_ZERO
, "probe description %s:%s:%s:%s does not "
1693 "match any probes\n", pdp
->dtpd_provider
, pdp
->dtpd_mod
,
1694 pdp
->dtpd_func
, pdp
->dtpd_name
);
1697 if (err
!= EDT_NOPROBE
&& err
!= EDT_UNSTABLE
&& err
!= 0)
1698 xyerror(D_PDESC_INVAL
, "%s\n", dtrace_errmsg(dtp
, err
));
1700 dt_dprintf("set context to %s:%s:%s:%s [%u] prp=%p attr=%s argc=%d\n",
1701 pdp
->dtpd_provider
, pdp
->dtpd_mod
, pdp
->dtpd_func
, pdp
->dtpd_name
,
1702 pdp
->dtpd_id
, (void *)prp
, dt_attr_str(yypcb
->pcb_pinfo
.dtp_attr
,
1703 attrstr
, sizeof (attrstr
)), yypcb
->pcb_pinfo
.dtp_argc
);
1706 * Reset the stability attributes of D global variables that vary
1707 * based on the attributes of the provider and context itself.
1709 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "probeprov")) != NULL
)
1710 idp
->di_attr
= pap
->dtpa_provider
;
1711 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "probemod")) != NULL
)
1712 idp
->di_attr
= pap
->dtpa_mod
;
1713 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "probefunc")) != NULL
)
1714 idp
->di_attr
= pap
->dtpa_func
;
1715 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "probename")) != NULL
)
1716 idp
->di_attr
= pap
->dtpa_name
;
1717 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, "args")) != NULL
)
1718 idp
->di_attr
= pap
->dtpa_args
;
1720 yypcb
->pcb_pdesc
= pdp
;
1721 yypcb
->pcb_probe
= prp
;
1725 * Reset context-dependent variables and state at the end of cooking a D probe
1726 * definition clause. This ensures that external declarations between clauses
1727 * do not reference any stale context-dependent data from the previous clause.
1730 dt_endcontext(dtrace_hdl_t
*dtp
)
1732 static const char *const cvars
[] = {
1733 "probeprov", "probemod", "probefunc", "probename", "args", NULL
1739 for (i
= 0; cvars
[i
] != NULL
; i
++) {
1740 if ((idp
= dt_idhash_lookup(dtp
->dt_globals
, cvars
[i
])) != NULL
)
1741 idp
->di_attr
= _dtrace_defattr
;
1744 yypcb
->pcb_pdesc
= NULL
;
1745 yypcb
->pcb_probe
= NULL
;
1749 dt_reduceid(dt_idhash_t
*dhp
, dt_ident_t
*idp
, dtrace_hdl_t
*dtp
)
1751 if (idp
->di_vers
!= 0 && idp
->di_vers
> dtp
->dt_vmax
)
1752 dt_idhash_delete(dhp
, idp
);
1758 * When dtrace_setopt() is called for "version", it calls dt_reduce() to remove
1759 * any identifiers or translators that have been previously defined as bound to
1760 * a version greater than the specified version. Therefore, in our current
1761 * version implementation, establishing a binding is a one-way transformation.
1762 * In addition, no versioning is currently provided for types as our .d library
1763 * files do not define any types and we reserve prefixes DTRACE_ and dtrace_
1764 * for our exclusive use. If required, type versioning will require more work.
1767 dt_reduce(dtrace_hdl_t
*dtp
, dt_version_t v
)
1769 char s
[DT_VERSION_STRMAX
];
1770 dt_xlator_t
*dxp
, *nxp
;
1772 if (v
> dtp
->dt_vmax
)
1773 return (dt_set_errno(dtp
, EDT_VERSREDUCED
));
1774 else if (v
== dtp
->dt_vmax
)
1775 return (0); /* no reduction necessary */
1777 dt_dprintf("reducing api version to %s\n",
1778 dt_version_num2str(v
, s
, sizeof (s
)));
1782 for (dxp
= dt_list_next(&dtp
->dt_xlators
); dxp
!= NULL
; dxp
= nxp
) {
1783 nxp
= dt_list_next(dxp
);
1784 if ((dxp
->dx_souid
.di_vers
!= 0 && dxp
->dx_souid
.di_vers
> v
) ||
1785 (dxp
->dx_ptrid
.di_vers
!= 0 && dxp
->dx_ptrid
.di_vers
> v
))
1786 dt_list_delete(&dtp
->dt_xlators
, dxp
);
1789 (void) dt_idhash_iter(dtp
->dt_macros
, (dt_idhash_f
*)dt_reduceid
, dtp
);
1790 (void) dt_idhash_iter(dtp
->dt_aggs
, (dt_idhash_f
*)dt_reduceid
, dtp
);
1791 (void) dt_idhash_iter(dtp
->dt_globals
, (dt_idhash_f
*)dt_reduceid
, dtp
);
1792 (void) dt_idhash_iter(dtp
->dt_tls
, (dt_idhash_f
*)dt_reduceid
, dtp
);
1798 * Fork and exec the cpp(1) preprocessor to run over the specified input file,
1799 * and return a FILE handle for the cpp output. We use the /dev/fd filesystem
1800 * here to simplify the code by leveraging file descriptor inheritance.
1803 dt_preproc(dtrace_hdl_t
*dtp
, FILE *ifp
)
1805 int argc
= dtp
->dt_cpp_argc
;
1806 char **argv
= malloc(sizeof (char *) * (argc
+ 5));
1807 FILE *ofp
= tmpfile();
1809 char ipath
[20], opath
[20]; /* big enough for /dev/fd/ + INT_MAX + \0 */
1810 char verdef
[32]; /* big enough for -D__SUNW_D_VERSION=0x%08x + \0 */
1812 struct sigaction act
, oact
;
1813 sigset_t mask
, omask
;
1820 if (argv
== NULL
|| ofp
== NULL
) {
1821 (void) dt_set_errno(dtp
, errno
);
1826 * If the input is a seekable file, see if it is an interpreter file.
1827 * If we see #!, seek past the first line because cpp will choke on it.
1828 * We start cpp just prior to the \n at the end of this line so that
1829 * it still sees the newline, ensuring that #line values are correct.
1831 if (isatty(fileno(ifp
)) == 0 && (off
= ftello64(ifp
)) != -1) {
1832 if ((c
= fgetc(ifp
)) == '#' && (c
= fgetc(ifp
)) == '!') {
1833 for (off
+= 2; c
!= '\n'; off
++) {
1834 if ((c
= fgetc(ifp
)) == EOF
)
1838 off
--; /* start cpp just prior to \n */
1841 (void) fseeko64(ifp
, off
, SEEK_SET
);
1844 (void) snprintf(ipath
, sizeof (ipath
), "/dev/fd/%d", fileno(ifp
));
1845 (void) snprintf(opath
, sizeof (opath
), "/dev/fd/%d", fileno(ofp
));
1847 bcopy(dtp
->dt_cpp_argv
, argv
, sizeof (char *) * argc
);
1849 (void) snprintf(verdef
, sizeof (verdef
),
1850 "-D__SUNW_D_VERSION=0x%08x", dtp
->dt_vmax
);
1851 argv
[argc
++] = verdef
;
1853 switch (dtp
->dt_stdcmode
) {
1856 argv
[argc
++] = "-D__STDC__=0";
1859 argv
[argc
++] = "-D__STDC__=1";
1863 argv
[argc
++] = ipath
;
1864 argv
[argc
++] = opath
;
1868 * libdtrace must be able to be embedded in other programs that may
1869 * include application-specific signal handlers. Therefore, if we
1870 * need to fork to run cpp(1), we must avoid generating a SIGCHLD
1871 * that could confuse the containing application. To do this,
1872 * we block SIGCHLD and reset its disposition to SIG_DFL.
1873 * We restore our signal state once we are done.
1875 (void) sigemptyset(&mask
);
1876 (void) sigaddset(&mask
, SIGCHLD
);
1877 (void) sigprocmask(SIG_BLOCK
, &mask
, &omask
);
1879 bzero(&act
, sizeof (act
));
1880 act
.sa_handler
= SIG_DFL
;
1881 (void) sigaction(SIGCHLD
, &act
, &oact
);
1883 if ((pid
= fork1()) == -1) {
1884 (void) sigaction(SIGCHLD
, &oact
, NULL
);
1885 (void) sigprocmask(SIG_SETMASK
, &omask
, NULL
);
1886 (void) dt_set_errno(dtp
, EDT_CPPFORK
);
1891 (void) execvp(dtp
->dt_cpp_path
, argv
);
1892 _exit(errno
== ENOENT
? 127 : 126);
1896 dt_dprintf("waiting for %s (PID %d)\n", dtp
->dt_cpp_path
,
1898 } while (waitpid(pid
, &wstat
, 0) == -1 && errno
== EINTR
);
1900 (void) sigaction(SIGCHLD
, &oact
, NULL
);
1901 (void) sigprocmask(SIG_SETMASK
, &omask
, NULL
);
1903 dt_dprintf("%s returned exit status 0x%x\n", dtp
->dt_cpp_path
, wstat
);
1904 estat
= WIFEXITED(wstat
) ? WEXITSTATUS(wstat
) : -1;
1909 (void) dt_set_errno(dtp
, EDT_CPPEXEC
);
1912 (void) dt_set_errno(dtp
, EDT_CPPENT
);
1915 (void) dt_set_errno(dtp
, EDT_CPPERR
);
1922 (void) fseek(ofp
, 0, SEEK_SET
);
1932 dt_lib_depend_error(dtrace_hdl_t
*dtp
, const char *format
, ...)
1936 va_start(ap
, format
);
1937 dt_set_errmsg(dtp
, NULL
, NULL
, NULL
, 0, format
, ap
);
1942 dt_lib_depend_add(dtrace_hdl_t
*dtp
, dt_list_t
*dlp
, const char *arg
)
1944 dt_lib_depend_t
*dld
;
1947 assert(arg
!= NULL
);
1949 if ((end
= strrchr(arg
, '/')) == NULL
)
1950 return (dt_set_errno(dtp
, EINVAL
));
1952 if ((dld
= dt_zalloc(dtp
, sizeof (dt_lib_depend_t
))) == NULL
)
1955 if ((dld
->dtld_libpath
= dt_alloc(dtp
, MAXPATHLEN
)) == NULL
) {
1960 (void) strlcpy(dld
->dtld_libpath
, arg
, end
- arg
+ 2);
1961 if ((dld
->dtld_library
= strdup(arg
)) == NULL
) {
1962 dt_free(dtp
, dld
->dtld_libpath
);
1964 return (dt_set_errno(dtp
, EDT_NOMEM
));
1967 dt_list_append(dlp
, dld
);
1972 dt_lib_depend_lookup(dt_list_t
*dld
, const char *arg
)
1974 dt_lib_depend_t
*dldn
;
1976 for (dldn
= dt_list_next(dld
); dldn
!= NULL
;
1977 dldn
= dt_list_next(dldn
)) {
1978 if (strcmp(dldn
->dtld_library
, arg
) == 0)
1986 * Go through all the library files, and, if any library dependencies exist for
1987 * that file, add it to that node's list of dependents. The result of this
1988 * will be a graph which can then be topologically sorted to produce a
1989 * compilation order.
1992 dt_lib_build_graph(dtrace_hdl_t
*dtp
)
1994 dt_lib_depend_t
*dld
, *dpld
;
1996 for (dld
= dt_list_next(&dtp
->dt_lib_dep
); dld
!= NULL
;
1997 dld
= dt_list_next(dld
)) {
1998 char *library
= dld
->dtld_library
;
2000 for (dpld
= dt_list_next(&dld
->dtld_dependencies
); dpld
!= NULL
;
2001 dpld
= dt_list_next(dpld
)) {
2002 dt_lib_depend_t
*dlda
;
2004 if ((dlda
= dt_lib_depend_lookup(&dtp
->dt_lib_dep
,
2005 dpld
->dtld_library
)) == NULL
) {
2006 dt_lib_depend_error(dtp
,
2007 "Invalid library dependency in %s: %s\n",
2008 dld
->dtld_library
, dpld
->dtld_library
);
2010 return (dt_set_errno(dtp
, EDT_COMPILER
));
2013 if ((dt_lib_depend_add(dtp
, &dlda
->dtld_dependents
,
2015 return (-1); /* preserve dt_errno */
2023 dt_topo_sort(dtrace_hdl_t
*dtp
, dt_lib_depend_t
*dld
, int *count
)
2025 dt_lib_depend_t
*dpld
, *dlda
, *new;
2027 dld
->dtld_start
= ++(*count
);
2029 for (dpld
= dt_list_next(&dld
->dtld_dependents
); dpld
!= NULL
;
2030 dpld
= dt_list_next(dpld
)) {
2031 dlda
= dt_lib_depend_lookup(&dtp
->dt_lib_dep
,
2032 dpld
->dtld_library
);
2033 assert(dlda
!= NULL
);
2035 if (dlda
->dtld_start
== 0 &&
2036 dt_topo_sort(dtp
, dlda
, count
) == -1)
2040 if ((new = dt_zalloc(dtp
, sizeof (dt_lib_depend_t
))) == NULL
)
2043 if ((new->dtld_library
= strdup(dld
->dtld_library
)) == NULL
) {
2045 return (dt_set_errno(dtp
, EDT_NOMEM
));
2048 new->dtld_start
= dld
->dtld_start
;
2049 new->dtld_finish
= dld
->dtld_finish
= ++(*count
);
2050 dt_list_prepend(&dtp
->dt_lib_dep_sorted
, new);
2052 dt_dprintf("library %s sorted (%d/%d)\n", new->dtld_library
,
2053 new->dtld_start
, new->dtld_finish
);
2059 dt_lib_depend_sort(dtrace_hdl_t
*dtp
)
2061 dt_lib_depend_t
*dld
, *dpld
, *dlda
;
2064 if (dt_lib_build_graph(dtp
) == -1)
2065 return (-1); /* preserve dt_errno */
2068 * Perform a topological sort of the graph that hangs off
2069 * dtp->dt_lib_dep. The result of this process will be a
2070 * dependency ordered list located at dtp->dt_lib_dep_sorted.
2072 for (dld
= dt_list_next(&dtp
->dt_lib_dep
); dld
!= NULL
;
2073 dld
= dt_list_next(dld
)) {
2074 if (dld
->dtld_start
== 0 &&
2075 dt_topo_sort(dtp
, dld
, &count
) == -1)
2076 return (-1); /* preserve dt_errno */;
2080 * Check the graph for cycles. If an ancestor's finishing time is
2081 * less than any of its dependent's finishing times then a back edge
2082 * exists in the graph and this is a cycle.
2084 for (dld
= dt_list_next(&dtp
->dt_lib_dep
); dld
!= NULL
;
2085 dld
= dt_list_next(dld
)) {
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_sorted
,
2089 dpld
->dtld_library
);
2090 assert(dlda
!= NULL
);
2092 if (dlda
->dtld_finish
> dld
->dtld_finish
) {
2093 dt_lib_depend_error(dtp
,
2094 "Cyclic dependency detected: %s => %s\n",
2095 dld
->dtld_library
, dpld
->dtld_library
);
2097 return (dt_set_errno(dtp
, EDT_COMPILER
));
2106 dt_lib_depend_free(dtrace_hdl_t
*dtp
)
2108 dt_lib_depend_t
*dld
, *dlda
;
2110 while ((dld
= dt_list_next(&dtp
->dt_lib_dep
)) != NULL
) {
2111 while ((dlda
= dt_list_next(&dld
->dtld_dependencies
)) != NULL
) {
2112 dt_list_delete(&dld
->dtld_dependencies
, dlda
);
2113 dt_free(dtp
, dlda
->dtld_library
);
2114 dt_free(dtp
, dlda
->dtld_libpath
);
2117 while ((dlda
= dt_list_next(&dld
->dtld_dependents
)) != NULL
) {
2118 dt_list_delete(&dld
->dtld_dependents
, dlda
);
2119 dt_free(dtp
, dlda
->dtld_library
);
2120 dt_free(dtp
, dlda
->dtld_libpath
);
2123 dt_list_delete(&dtp
->dt_lib_dep
, dld
);
2124 dt_free(dtp
, dld
->dtld_library
);
2125 dt_free(dtp
, dld
->dtld_libpath
);
2129 while ((dld
= dt_list_next(&dtp
->dt_lib_dep_sorted
)) != NULL
) {
2130 dt_list_delete(&dtp
->dt_lib_dep_sorted
, dld
);
2131 dt_free(dtp
, dld
->dtld_library
);
2137 * Open all the .d library files found in the specified directory and
2138 * compile each one of them. We silently ignore any missing directories and
2139 * other files found therein. We only fail (and thereby fail dt_load_libs()) if
2140 * we fail to compile a library and the error is something other than #pragma D
2141 * depends_on. Dependency errors are silently ignored to permit a library
2142 * directory to contain libraries which may not be accessible depending on our
2146 dt_load_libs_dir(dtrace_hdl_t
*dtp
, const char *path
)
2149 const char *p
, *end
;
2152 char fname
[PATH_MAX
];
2155 dt_lib_depend_t
*dld
;
2157 if ((dirp
= opendir(path
)) == NULL
) {
2158 dt_dprintf("skipping lib dir %s: %s\n", path
, strerror(errno
));
2162 /* First, parse each file for library dependencies. */
2163 while ((dp
= readdir(dirp
)) != NULL
) {
2164 if ((p
= strrchr(dp
->d_name
, '.')) == NULL
|| strcmp(p
, ".d"))
2165 continue; /* skip any filename not ending in .d */
2167 (void) snprintf(fname
, sizeof (fname
),
2168 "%s/%s", path
, dp
->d_name
);
2170 if ((fp
= fopen(fname
, "rF")) == NULL
) {
2171 dt_dprintf("skipping library %s: %s\n",
2172 fname
, strerror(errno
));
2177 * Skip files whose name match an already processed library
2179 for (dld
= dt_list_next(&dtp
->dt_lib_dep
); dld
!= NULL
;
2180 dld
= dt_list_next(dld
)) {
2181 end
= strrchr(dld
->dtld_library
, '/');
2182 /* dt_lib_depend_add ensures this */
2183 assert(end
!= NULL
);
2184 if (strcmp(end
+ 1, dp
->d_name
) == 0)
2189 dt_dprintf("skipping library %s, already processed "
2190 "library with the same name: %s", dp
->d_name
,
2196 dtp
->dt_filetag
= fname
;
2197 if (dt_lib_depend_add(dtp
, &dtp
->dt_lib_dep
, fname
) != 0) {
2199 return (-1); /* preserve dt_errno */
2202 rv
= dt_compile(dtp
, DT_CTX_DPROG
,
2203 DTRACE_PROBESPEC_NAME
, NULL
,
2204 DTRACE_C_EMPTY
| DTRACE_C_CTL
, 0, NULL
, fp
, NULL
);
2206 if (rv
!= NULL
&& dtp
->dt_errno
&&
2207 (dtp
->dt_errno
!= EDT_COMPILER
||
2208 dtp
->dt_errtag
!= dt_errtag(D_PRAGMA_DEPEND
))) {
2210 return (-1); /* preserve dt_errno */
2214 dt_dprintf("error parsing library %s: %s\n",
2215 fname
, dtrace_errmsg(dtp
, dtrace_errno(dtp
)));
2218 dtp
->dt_filetag
= NULL
;
2221 (void) closedir(dirp
);
2227 * Perform a topological sorting of all the libraries found across the entire
2228 * dt_lib_path. Once sorted, compile each one in topological order to cache its
2229 * inlines and translators, etc. We silently ignore any missing directories and
2230 * other files found therein. We only fail (and thereby fail dt_load_libs()) if
2231 * we fail to compile a library and the error is something other than #pragma D
2232 * depends_on. Dependency errors are silently ignored to permit a library
2233 * directory to contain libraries which may not be accessible depending on our
2237 dt_load_libs_sort(dtrace_hdl_t
*dtp
)
2241 dt_lib_depend_t
*dld
;
2244 * Finish building the graph containing the library dependencies
2245 * and perform a topological sort to generate an ordered list
2248 if (dt_lib_depend_sort(dtp
) == -1)
2251 for (dld
= dt_list_next(&dtp
->dt_lib_dep_sorted
); dld
!= NULL
;
2252 dld
= dt_list_next(dld
)) {
2254 if ((fp
= fopen(dld
->dtld_library
, "r")) == NULL
) {
2255 dt_dprintf("skipping library %s: %s\n",
2256 dld
->dtld_library
, strerror(errno
));
2260 dtp
->dt_filetag
= dld
->dtld_library
;
2261 pgp
= dtrace_program_fcompile(dtp
, fp
, DTRACE_C_EMPTY
, 0, NULL
);
2263 dtp
->dt_filetag
= NULL
;
2265 if (pgp
== NULL
&& (dtp
->dt_errno
!= EDT_COMPILER
||
2266 dtp
->dt_errtag
!= dt_errtag(D_PRAGMA_DEPEND
)))
2270 dt_dprintf("skipping library %s: %s\n",
2272 dtrace_errmsg(dtp
, dtrace_errno(dtp
)));
2274 dld
->dtld_loaded
= B_TRUE
;
2275 dt_program_destroy(dtp
, pgp
);
2279 dt_lib_depend_free(dtp
);
2283 dt_lib_depend_free(dtp
);
2284 return (-1); /* preserve dt_errno */
2288 * Load the contents of any appropriate DTrace .d library files. These files
2289 * contain inlines and translators that will be cached by the compiler. We
2290 * defer this activity until the first compile to permit libdtrace clients to
2291 * add their own library directories and so that we can properly report errors.
2294 dt_load_libs(dtrace_hdl_t
*dtp
)
2298 if (dtp
->dt_cflags
& DTRACE_C_NOLIBS
)
2299 return (0); /* libraries already processed */
2301 dtp
->dt_cflags
|= DTRACE_C_NOLIBS
;
2304 * /usr/lib/dtrace is always at the head of the list. The rest of the
2305 * list is specified in the precedence order the user requested. Process
2306 * everything other than the head first. DTRACE_C_NOLIBS has already
2307 * been spcified so dt_vopen will ensure that there is always one entry
2310 for (dirp
= dt_list_next(dt_list_next(&dtp
->dt_lib_path
));
2311 dirp
!= NULL
; dirp
= dt_list_next(dirp
)) {
2312 if (dt_load_libs_dir(dtp
, dirp
->dir_path
) != 0) {
2313 dtp
->dt_cflags
&= ~DTRACE_C_NOLIBS
;
2314 return (-1); /* errno is set for us */
2318 /* Handle /usr/lib/dtrace */
2319 dirp
= dt_list_next(&dtp
->dt_lib_path
);
2320 if (dt_load_libs_dir(dtp
, dirp
->dir_path
) != 0) {
2321 dtp
->dt_cflags
&= ~DTRACE_C_NOLIBS
;
2322 return (-1); /* errno is set for us */
2325 if (dt_load_libs_sort(dtp
) < 0)
2326 return (-1); /* errno is set for us */
2332 dt_compile(dtrace_hdl_t
*dtp
, int context
, dtrace_probespec_t pspec
, void *arg
,
2333 uint_t cflags
, int argc
, char *const argv
[], FILE *fp
, const char *s
)
2341 if ((fp
== NULL
&& s
== NULL
) || (cflags
& ~DTRACE_C_MASK
) != 0) {
2342 (void) dt_set_errno(dtp
, EINVAL
);
2346 if (dt_list_next(&dtp
->dt_lib_path
) != NULL
&& dt_load_libs(dtp
) != 0)
2347 return (NULL
); /* errno is set for us */
2349 if (dtp
->dt_globals
->dh_nelems
!= 0)
2350 (void) dt_idhash_iter(dtp
->dt_globals
, dt_idreset
, NULL
);
2352 if (dtp
->dt_tls
->dh_nelems
!= 0)
2353 (void) dt_idhash_iter(dtp
->dt_tls
, dt_idreset
, NULL
);
2355 if (fp
&& (cflags
& DTRACE_C_CPP
) && (fp
= dt_preproc(dtp
, fp
)) == NULL
)
2356 return (NULL
); /* errno is set for us */
2358 dt_pcb_push(dtp
, &pcb
);
2360 pcb
.pcb_fileptr
= fp
;
2363 pcb
.pcb_strlen
= s
? strlen(s
) : 0;
2364 pcb
.pcb_sargc
= argc
;
2365 pcb
.pcb_sargv
= argv
;
2366 pcb
.pcb_sflagv
= argc
? calloc(argc
, sizeof (ushort_t
)) : NULL
;
2367 pcb
.pcb_pspec
= pspec
;
2368 pcb
.pcb_cflags
= dtp
->dt_cflags
| cflags
;
2369 pcb
.pcb_amin
= dtp
->dt_amin
;
2370 pcb
.pcb_yystate
= -1;
2371 pcb
.pcb_context
= context
;
2372 pcb
.pcb_token
= context
;
2374 if (context
!= DT_CTX_DPROG
)
2376 else if (cflags
& DTRACE_C_CTL
)
2377 yybegin(YYS_CONTROL
);
2379 yybegin(YYS_CLAUSE
);
2381 if ((err
= setjmp(yypcb
->pcb_jmpbuf
)) != 0)
2384 if (yypcb
->pcb_sargc
!= 0 && yypcb
->pcb_sflagv
== NULL
)
2385 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
2387 yypcb
->pcb_idents
= dt_idhash_create("ambiguous", NULL
, 0, 0);
2388 yypcb
->pcb_locals
= dt_idhash_create("clause local", NULL
,
2389 DIF_VAR_OTHER_UBASE
, DIF_VAR_OTHER_MAX
);
2391 if (yypcb
->pcb_idents
== NULL
|| yypcb
->pcb_locals
== NULL
)
2392 longjmp(yypcb
->pcb_jmpbuf
, EDT_NOMEM
);
2395 * Invoke the parser to evaluate the D source code. If any errors
2396 * occur during parsing, an error function will be called and we
2397 * will longjmp back to pcb_jmpbuf to abort. If parsing succeeds,
2398 * we optionally display the parse tree if debugging is enabled.
2400 if (yyparse() != 0 || yypcb
->pcb_root
== NULL
)
2401 xyerror(D_EMPTY
, "empty D program translation unit\n");
2405 if (cflags
& DTRACE_C_CTL
)
2408 if (context
!= DT_CTX_DTYPE
&& DT_TREEDUMP_PASS(dtp
, 1))
2409 dt_node_printr(yypcb
->pcb_root
, stderr
, 0);
2411 if (yypcb
->pcb_pragmas
!= NULL
)
2412 (void) dt_idhash_iter(yypcb
->pcb_pragmas
, dt_idpragma
, NULL
);
2414 if (argc
> 1 && !(yypcb
->pcb_cflags
& DTRACE_C_ARGREF
) &&
2415 !(yypcb
->pcb_sflagv
[argc
- 1] & DT_IDFLG_REF
)) {
2416 xyerror(D_MACRO_UNUSED
, "extraneous argument '%s' ($%d is "
2417 "not referenced)\n", yypcb
->pcb_sargv
[argc
- 1], argc
- 1);
2421 * Perform sugar transformations (for "if" / "else") and replace the
2422 * existing clause chain with the new one.
2424 if (context
== DT_CTX_DPROG
) {
2425 dt_node_t
*dnp
, *next_dnp
;
2426 dt_node_t
*new_list
= NULL
;
2428 for (dnp
= yypcb
->pcb_root
->dn_list
;
2429 dnp
!= NULL
; dnp
= next_dnp
) {
2430 /* remove this node from the list */
2431 next_dnp
= dnp
->dn_list
;
2432 dnp
->dn_list
= NULL
;
2434 if (dnp
->dn_kind
== DT_NODE_CLAUSE
)
2435 dnp
= dt_compile_sugar(dtp
, dnp
);
2436 /* append node to the new list */
2437 new_list
= dt_node_link(new_list
, dnp
);
2439 yypcb
->pcb_root
->dn_list
= new_list
;
2443 * If we have successfully created a parse tree for a D program, loop
2444 * over the clauses and actions and instantiate the corresponding
2445 * libdtrace program. If we are parsing a D expression, then we
2446 * simply run the code generator and assembler on the resulting tree.
2450 assert(yypcb
->pcb_root
->dn_kind
== DT_NODE_PROG
);
2452 if ((dnp
= yypcb
->pcb_root
->dn_list
) == NULL
&&
2453 !(yypcb
->pcb_cflags
& DTRACE_C_EMPTY
))
2454 xyerror(D_EMPTY
, "empty D program translation unit\n");
2456 if ((yypcb
->pcb_prog
= dt_program_create(dtp
)) == NULL
)
2457 longjmp(yypcb
->pcb_jmpbuf
, dtrace_errno(dtp
));
2459 for (; dnp
!= NULL
; dnp
= dnp
->dn_list
) {
2460 switch (dnp
->dn_kind
) {
2461 case DT_NODE_CLAUSE
:
2462 if (DT_TREEDUMP_PASS(dtp
, 4))
2463 dt_printd(dnp
, stderr
, 0);
2464 dt_compile_clause(dtp
, dnp
);
2466 case DT_NODE_XLATOR
:
2467 if (dtp
->dt_xlatemode
== DT_XL_DYNAMIC
)
2468 dt_compile_xlator(dnp
);
2470 case DT_NODE_PROVIDER
:
2471 (void) dt_node_cook(dnp
, DT_IDFLG_REF
);
2476 yypcb
->pcb_prog
->dp_xrefs
= yypcb
->pcb_asxrefs
;
2477 yypcb
->pcb_prog
->dp_xrefslen
= yypcb
->pcb_asxreflen
;
2478 yypcb
->pcb_asxrefs
= NULL
;
2479 yypcb
->pcb_asxreflen
= 0;
2481 rv
= yypcb
->pcb_prog
;
2485 (void) dt_node_cook(yypcb
->pcb_root
, DT_IDFLG_REF
);
2486 dt_cg(yypcb
, yypcb
->pcb_root
);
2491 ddp
= (dt_decl_t
*)yypcb
->pcb_root
; /* root is really a decl */
2492 err
= dt_decl_type(ddp
, arg
);
2496 longjmp(yypcb
->pcb_jmpbuf
, EDT_COMPILER
);
2503 if (context
!= DT_CTX_DTYPE
&& yypcb
->pcb_root
!= NULL
&&
2504 DT_TREEDUMP_PASS(dtp
, 3))
2505 dt_node_printr(yypcb
->pcb_root
, stderr
, 0);
2507 if (dtp
->dt_cdefs_fd
!= -1 && (ftruncate64(dtp
->dt_cdefs_fd
, 0) == -1 ||
2508 lseek64(dtp
->dt_cdefs_fd
, 0, SEEK_SET
) == -1 ||
2509 ctf_write(dtp
->dt_cdefs
->dm_ctfp
, dtp
->dt_cdefs_fd
) == CTF_ERR
))
2510 dt_dprintf("failed to update CTF cache: %s\n", strerror(errno
));
2512 if (dtp
->dt_ddefs_fd
!= -1 && (ftruncate64(dtp
->dt_ddefs_fd
, 0) == -1 ||
2513 lseek64(dtp
->dt_ddefs_fd
, 0, SEEK_SET
) == -1 ||
2514 ctf_write(dtp
->dt_ddefs
->dm_ctfp
, dtp
->dt_ddefs_fd
) == CTF_ERR
))
2515 dt_dprintf("failed to update CTF cache: %s\n", strerror(errno
));
2517 if (yypcb
->pcb_fileptr
&& (cflags
& DTRACE_C_CPP
))
2518 (void) fclose(yypcb
->pcb_fileptr
); /* close dt_preproc() file */
2520 dt_pcb_pop(dtp
, err
);
2521 (void) dt_set_errno(dtp
, err
);
2522 return (err
? NULL
: rv
);
2526 dtrace_program_strcompile(dtrace_hdl_t
*dtp
, const char *s
,
2527 dtrace_probespec_t spec
, uint_t cflags
, int argc
, char *const argv
[])
2529 return (dt_compile(dtp
, DT_CTX_DPROG
,
2530 spec
, NULL
, cflags
, argc
, argv
, NULL
, s
));
2534 dtrace_program_fcompile(dtrace_hdl_t
*dtp
, FILE *fp
,
2535 uint_t cflags
, int argc
, char *const argv
[])
2537 return (dt_compile(dtp
, DT_CTX_DPROG
,
2538 DTRACE_PROBESPEC_NAME
, NULL
, cflags
, argc
, argv
, fp
, NULL
));
2542 dtrace_type_strcompile(dtrace_hdl_t
*dtp
, const char *s
, dtrace_typeinfo_t
*dtt
)
2544 (void) dt_compile(dtp
, DT_CTX_DTYPE
,
2545 DTRACE_PROBESPEC_NONE
, dtt
, 0, 0, NULL
, NULL
, s
);
2546 return (dtp
->dt_errno
? -1 : 0);
2550 dtrace_type_fcompile(dtrace_hdl_t
*dtp
, FILE *fp
, dtrace_typeinfo_t
*dtt
)
2552 (void) dt_compile(dtp
, DT_CTX_DTYPE
,
2553 DTRACE_PROBESPEC_NONE
, dtt
, 0, 0, NULL
, fp
, NULL
);
2554 return (dtp
->dt_errno
? -1 : 0);