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