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 *size = dnp->dn_args->dn_list; 688 689 char n[DT_TYPE_NAMELEN]; 690 691 if (dt_node_is_integer(addr) == 0 && dt_node_is_pointer(addr) == 0) { 692 dnerror(addr, D_TRACEMEM_ADDR, 693 "tracemem( ) argument #1 is incompatible with " 694 "prototype:\n\tprototype: pointer or integer\n" 695 "\t argument: %s\n", 696 dt_node_type_name(addr, n, sizeof (n))); 697 } 698 699 if (dt_node_is_posconst(size) == 0) { 700 dnerror(size, D_TRACEMEM_SIZE, "tracemem( ) argument #2 must " 701 "be a non-zero positive integral constant expression\n"); 702 } 703 704 dt_cg(yypcb, addr); 705 ap->dtad_difo = dt_as(yypcb); 706 ap->dtad_kind = DTRACEACT_DIFEXPR; 707 708 ap->dtad_difo->dtdo_rtype.dtdt_flags |= DIF_TF_BYREF; 709 ap->dtad_difo->dtdo_rtype.dtdt_size = size->dn_value; 710 } 711 712 static void 713 dt_action_stack_args(dtrace_hdl_t *dtp, dtrace_actdesc_t *ap, dt_node_t *arg0) 714 { 715 ap->dtad_kind = DTRACEACT_STACK; 716 717 if (dtp->dt_options[DTRACEOPT_STACKFRAMES] != DTRACEOPT_UNSET) { 718 ap->dtad_arg = dtp->dt_options[DTRACEOPT_STACKFRAMES]; 719 } else { 720 ap->dtad_arg = 0; 721 } 722 723 if (arg0 != NULL) { 724 if (arg0->dn_list != NULL) { 725 dnerror(arg0, D_STACK_PROTO, "stack( ) prototype " 726 "mismatch: too many arguments\n"); 727 } 728 729 if (dt_node_is_posconst(arg0) == 0) { 730 dnerror(arg0, D_STACK_SIZE, "stack( ) size must be a " 731 "non-zero positive integral constant expression\n"); 732 } 733 734 ap->dtad_arg = arg0->dn_value; 735 } 736 } 737 738 static void 739 dt_action_stack(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 740 { 741 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 742 dt_action_stack_args(dtp, ap, dnp->dn_args); 743 } 744 745 static void 746 dt_action_ustack_args(dtrace_hdl_t *dtp, dtrace_actdesc_t *ap, dt_node_t *dnp) 747 { 748 uint32_t nframes = 0; 749 uint32_t strsize = 0; /* default string table size */ 750 dt_node_t *arg0 = dnp->dn_args; 751 dt_node_t *arg1 = arg0 != NULL ? arg0->dn_list : NULL; 752 753 assert(dnp->dn_ident->di_id == DT_ACT_JSTACK || 754 dnp->dn_ident->di_id == DT_ACT_USTACK); 755 756 if (dnp->dn_ident->di_id == DT_ACT_JSTACK) { 757 if (dtp->dt_options[DTRACEOPT_JSTACKFRAMES] != DTRACEOPT_UNSET) 758 nframes = dtp->dt_options[DTRACEOPT_JSTACKFRAMES]; 759 760 if (dtp->dt_options[DTRACEOPT_JSTACKSTRSIZE] != DTRACEOPT_UNSET) 761 strsize = dtp->dt_options[DTRACEOPT_JSTACKSTRSIZE]; 762 763 ap->dtad_kind = DTRACEACT_JSTACK; 764 } else { 765 assert(dnp->dn_ident->di_id == DT_ACT_USTACK); 766 767 if (dtp->dt_options[DTRACEOPT_USTACKFRAMES] != DTRACEOPT_UNSET) 768 nframes = dtp->dt_options[DTRACEOPT_USTACKFRAMES]; 769 770 ap->dtad_kind = DTRACEACT_USTACK; 771 } 772 773 if (arg0 != NULL) { 774 if (!dt_node_is_posconst(arg0)) { 775 dnerror(arg0, D_USTACK_FRAMES, "ustack( ) argument #1 " 776 "must be a non-zero positive integer constant\n"); 777 } 778 nframes = (uint32_t)arg0->dn_value; 779 } 780 781 if (arg1 != NULL) { 782 if (arg1->dn_kind != DT_NODE_INT || 783 ((arg1->dn_flags & DT_NF_SIGNED) && 784 (int64_t)arg1->dn_value < 0)) { 785 dnerror(arg1, D_USTACK_STRSIZE, "ustack( ) argument #2 " 786 "must be a positive integer constant\n"); 787 } 788 789 if (arg1->dn_list != NULL) { 790 dnerror(arg1, D_USTACK_PROTO, "ustack( ) prototype " 791 "mismatch: too many arguments\n"); 792 } 793 794 strsize = (uint32_t)arg1->dn_value; 795 } 796 797 ap->dtad_arg = DTRACE_USTACK_ARG(nframes, strsize); 798 } 799 800 static void 801 dt_action_ustack(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 802 { 803 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 804 dt_action_ustack_args(dtp, ap, dnp); 805 } 806 807 static void 808 dt_action_setopt(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 809 { 810 dtrace_actdesc_t *ap; 811 dt_node_t *arg0, *arg1; 812 813 /* 814 * The prototype guarantees that we are called with either one or 815 * two arguments, and that any arguments that are present are strings. 816 */ 817 arg0 = dnp->dn_args; 818 arg1 = arg0->dn_list; 819 820 ap = dt_stmt_action(dtp, sdp); 821 dt_cg(yypcb, arg0); 822 ap->dtad_difo = dt_as(yypcb); 823 ap->dtad_kind = DTRACEACT_LIBACT; 824 ap->dtad_arg = DT_ACT_SETOPT; 825 826 ap = dt_stmt_action(dtp, sdp); 827 828 if (arg1 == NULL) { 829 dt_action_difconst(ap, 0, DTRACEACT_LIBACT); 830 } else { 831 dt_cg(yypcb, arg1); 832 ap->dtad_difo = dt_as(yypcb); 833 ap->dtad_kind = DTRACEACT_LIBACT; 834 } 835 836 ap->dtad_arg = DT_ACT_SETOPT; 837 } 838 839 /*ARGSUSED*/ 840 static void 841 dt_action_symmod_args(dtrace_hdl_t *dtp, dtrace_actdesc_t *ap, 842 dt_node_t *dnp, dtrace_actkind_t kind) 843 { 844 assert(kind == DTRACEACT_SYM || kind == DTRACEACT_MOD || 845 kind == DTRACEACT_USYM || kind == DTRACEACT_UMOD || 846 kind == DTRACEACT_UADDR); 847 848 dt_cg(yypcb, dnp); 849 ap->dtad_difo = dt_as(yypcb); 850 ap->dtad_kind = kind; 851 ap->dtad_difo->dtdo_rtype.dtdt_size = sizeof (uint64_t); 852 } 853 854 static void 855 dt_action_symmod(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp, 856 dtrace_actkind_t kind) 857 { 858 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 859 dt_action_symmod_args(dtp, ap, dnp->dn_args, kind); 860 } 861 862 /*ARGSUSED*/ 863 static void 864 dt_action_ftruncate(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 865 { 866 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 867 868 /* 869 * Library actions need a DIFO that serves as an argument. As 870 * ftruncate() doesn't take an argument, we generate the constant 0 871 * in a DIFO; this constant will be ignored when the ftruncate() is 872 * processed. 873 */ 874 dt_action_difconst(ap, 0, DTRACEACT_LIBACT); 875 ap->dtad_arg = DT_ACT_FTRUNCATE; 876 } 877 878 /*ARGSUSED*/ 879 static void 880 dt_action_stop(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 881 { 882 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 883 884 ap->dtad_kind = DTRACEACT_STOP; 885 ap->dtad_arg = 0; 886 } 887 888 /*ARGSUSED*/ 889 static void 890 dt_action_breakpoint(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 891 { 892 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 893 894 ap->dtad_kind = DTRACEACT_BREAKPOINT; 895 ap->dtad_arg = 0; 896 } 897 898 /*ARGSUSED*/ 899 static void 900 dt_action_panic(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 901 { 902 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 903 904 ap->dtad_kind = DTRACEACT_PANIC; 905 ap->dtad_arg = 0; 906 } 907 908 static void 909 dt_action_chill(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 910 { 911 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 912 913 dt_cg(yypcb, dnp->dn_args); 914 ap->dtad_difo = dt_as(yypcb); 915 ap->dtad_kind = DTRACEACT_CHILL; 916 } 917 918 static void 919 dt_action_raise(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 920 { 921 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 922 923 dt_cg(yypcb, dnp->dn_args); 924 ap->dtad_difo = dt_as(yypcb); 925 ap->dtad_kind = DTRACEACT_RAISE; 926 } 927 928 static void 929 dt_action_exit(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 930 { 931 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 932 933 dt_cg(yypcb, dnp->dn_args); 934 ap->dtad_difo = dt_as(yypcb); 935 ap->dtad_kind = DTRACEACT_EXIT; 936 ap->dtad_difo->dtdo_rtype.dtdt_size = sizeof (int); 937 } 938 939 static void 940 dt_action_speculate(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_SPECULATE; 947 } 948 949 static void 950 dt_action_commit(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_COMMIT; 957 } 958 959 static void 960 dt_action_discard(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 961 { 962 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 963 964 dt_cg(yypcb, dnp->dn_args); 965 ap->dtad_difo = dt_as(yypcb); 966 ap->dtad_kind = DTRACEACT_DISCARD; 967 } 968 969 static void 970 dt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 971 { 972 switch (dnp->dn_expr->dn_ident->di_id) { 973 case DT_ACT_BREAKPOINT: 974 dt_action_breakpoint(dtp, dnp->dn_expr, sdp); 975 break; 976 case DT_ACT_CHILL: 977 dt_action_chill(dtp, dnp->dn_expr, sdp); 978 break; 979 case DT_ACT_CLEAR: 980 dt_action_clear(dtp, dnp->dn_expr, sdp); 981 break; 982 case DT_ACT_COMMIT: 983 dt_action_commit(dtp, dnp->dn_expr, sdp); 984 break; 985 case DT_ACT_DENORMALIZE: 986 dt_action_normalize(dtp, dnp->dn_expr, sdp); 987 break; 988 case DT_ACT_DISCARD: 989 dt_action_discard(dtp, dnp->dn_expr, sdp); 990 break; 991 case DT_ACT_EXIT: 992 dt_action_exit(dtp, dnp->dn_expr, sdp); 993 break; 994 case DT_ACT_FREOPEN: 995 dt_action_printflike(dtp, dnp->dn_expr, sdp, DTRACEACT_FREOPEN); 996 break; 997 case DT_ACT_FTRUNCATE: 998 dt_action_ftruncate(dtp, dnp->dn_expr, sdp); 999 break; 1000 case DT_ACT_MOD: 1001 dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_MOD); 1002 break; 1003 case DT_ACT_NORMALIZE: 1004 dt_action_normalize(dtp, dnp->dn_expr, sdp); 1005 break; 1006 case DT_ACT_PANIC: 1007 dt_action_panic(dtp, dnp->dn_expr, sdp); 1008 break; 1009 case DT_ACT_PRINTA: 1010 dt_action_printa(dtp, dnp->dn_expr, sdp); 1011 break; 1012 case DT_ACT_PRINTF: 1013 dt_action_printflike(dtp, dnp->dn_expr, sdp, DTRACEACT_PRINTF); 1014 break; 1015 case DT_ACT_RAISE: 1016 dt_action_raise(dtp, dnp->dn_expr, sdp); 1017 break; 1018 case DT_ACT_SETOPT: 1019 dt_action_setopt(dtp, dnp->dn_expr, sdp); 1020 break; 1021 case DT_ACT_SPECULATE: 1022 dt_action_speculate(dtp, dnp->dn_expr, sdp); 1023 break; 1024 case DT_ACT_STACK: 1025 dt_action_stack(dtp, dnp->dn_expr, sdp); 1026 break; 1027 case DT_ACT_STOP: 1028 dt_action_stop(dtp, dnp->dn_expr, sdp); 1029 break; 1030 case DT_ACT_SYM: 1031 dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_SYM); 1032 break; 1033 case DT_ACT_SYSTEM: 1034 dt_action_printflike(dtp, dnp->dn_expr, sdp, DTRACEACT_SYSTEM); 1035 break; 1036 case DT_ACT_TRACE: 1037 dt_action_trace(dtp, dnp->dn_expr, sdp); 1038 break; 1039 case DT_ACT_TRACEMEM: 1040 dt_action_tracemem(dtp, dnp->dn_expr, sdp); 1041 break; 1042 case DT_ACT_TRUNC: 1043 dt_action_trunc(dtp, dnp->dn_expr, sdp); 1044 break; 1045 case DT_ACT_UADDR: 1046 dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_UADDR); 1047 break; 1048 case DT_ACT_UMOD: 1049 dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_UMOD); 1050 break; 1051 case DT_ACT_USYM: 1052 dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_USYM); 1053 break; 1054 case DT_ACT_USTACK: 1055 case DT_ACT_JSTACK: 1056 dt_action_ustack(dtp, dnp->dn_expr, sdp); 1057 break; 1058 default: 1059 dnerror(dnp->dn_expr, D_UNKNOWN, "tracing function %s( ) is " 1060 "not yet supported\n", dnp->dn_expr->dn_ident->di_name); 1061 } 1062 } 1063 1064 static void 1065 dt_compile_exp(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 1066 { 1067 dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); 1068 1069 dt_cg(yypcb, dnp->dn_expr); 1070 ap->dtad_difo = dt_as(yypcb); 1071 ap->dtad_difo->dtdo_rtype = dt_void_rtype; 1072 ap->dtad_kind = DTRACEACT_DIFEXPR; 1073 } 1074 1075 static void 1076 dt_compile_agg(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) 1077 { 1078 dt_ident_t *aid, *fid; 1079 dt_node_t *anp, *incr = NULL; 1080 dtrace_actdesc_t *ap; 1081 uint_t n = 1, argmax; 1082 uint64_t arg = 0; 1083 1084 /* 1085 * If the aggregation has no aggregating function applied to it, then 1086 * this statement has no effect. Flag this as a programming error. 1087 */ 1088 if (dnp->dn_aggfun == NULL) { 1089 dnerror(dnp, D_AGG_NULL, "expression has null effect: @%s\n", 1090 dnp->dn_ident->di_name); 1091 } 1092 1093 aid = dnp->dn_ident; 1094 fid = dnp->dn_aggfun->dn_ident; 1095 1096 if (dnp->dn_aggfun->dn_args != NULL && 1097 dt_node_is_scalar(dnp->dn_aggfun->dn_args) == 0) { 1098 dnerror(dnp->dn_aggfun, D_AGG_SCALAR, "%s( ) argument #1 must " 1099 "be of scalar type\n", fid->di_name); 1100 } 1101 1102 /* 1103 * The ID of the aggregation itself is implicitly recorded as the first 1104 * member of each aggregation tuple so we can distinguish them later. 1105 */ 1106 ap = dt_stmt_action(dtp, sdp); 1107 dt_action_difconst(ap, aid->di_id, DTRACEACT_DIFEXPR); 1108 1109 for (anp = dnp->dn_aggtup; anp != NULL; anp = anp->dn_list) { 1110 ap = dt_stmt_action(dtp, sdp); 1111 n++; 1112 1113 if (anp->dn_kind == DT_NODE_FUNC) { 1114 if (anp->dn_ident->di_id == DT_ACT_STACK) { 1115 dt_action_stack_args(dtp, ap, anp->dn_args); 1116 continue; 1117 } 1118 1119 if (anp->dn_ident->di_id == DT_ACT_USTACK || 1120 anp->dn_ident->di_id == DT_ACT_JSTACK) { 1121 dt_action_ustack_args(dtp, ap, anp); 1122 continue; 1123 } 1124 1125 switch (anp->dn_ident->di_id) { 1126 case DT_ACT_UADDR: 1127 dt_action_symmod_args(dtp, ap, 1128 anp->dn_args, DTRACEACT_UADDR); 1129 continue; 1130 1131 case DT_ACT_USYM: 1132 dt_action_symmod_args(dtp, ap, 1133 anp->dn_args, DTRACEACT_USYM); 1134 continue; 1135 1136 case DT_ACT_UMOD: 1137 dt_action_symmod_args(dtp, ap, 1138 anp->dn_args, DTRACEACT_UMOD); 1139 continue; 1140 1141 case DT_ACT_SYM: 1142 dt_action_symmod_args(dtp, ap, 1143 anp->dn_args, DTRACEACT_SYM); 1144 continue; 1145 1146 case DT_ACT_MOD: 1147 dt_action_symmod_args(dtp, ap, 1148 anp->dn_args, DTRACEACT_MOD); 1149 continue; 1150 1151 default: 1152 break; 1153 } 1154 } 1155 1156 dt_cg(yypcb, anp); 1157 ap->dtad_difo = dt_as(yypcb); 1158 ap->dtad_kind = DTRACEACT_DIFEXPR; 1159 } 1160 1161 if (fid->di_id == DTRACEAGG_LQUANTIZE) { 1162 /* 1163 * For linear quantization, we have between two and four 1164 * arguments in addition to the expression: 1165 * 1166 * arg1 => Base value 1167 * arg2 => Limit value 1168 * arg3 => Quantization level step size (defaults to 1) 1169 * arg4 => Quantization increment value (defaults to 1) 1170 */ 1171 dt_node_t *arg1 = dnp->dn_aggfun->dn_args->dn_list; 1172 dt_node_t *arg2 = arg1->dn_list; 1173 dt_node_t *arg3 = arg2->dn_list; 1174 dt_idsig_t *isp; 1175 uint64_t nlevels, step = 1, oarg; 1176 int64_t baseval, limitval; 1177 1178 if (arg1->dn_kind != DT_NODE_INT) { 1179 dnerror(arg1, D_LQUANT_BASETYPE, "lquantize( ) " 1180 "argument #1 must be an integer constant\n"); 1181 } 1182 1183 baseval = (int64_t)arg1->dn_value; 1184 1185 if (baseval < INT32_MIN || baseval > INT32_MAX) { 1186 dnerror(arg1, D_LQUANT_BASEVAL, "lquantize( ) " 1187 "argument #1 must be a 32-bit quantity\n"); 1188 } 1189 1190 if (arg2->dn_kind != DT_NODE_INT) { 1191 dnerror(arg2, D_LQUANT_LIMTYPE, "lquantize( ) " 1192 "argument #2 must be an integer constant\n"); 1193 } 1194 1195 limitval = (int64_t)arg2->dn_value; 1196 1197 if (limitval < INT32_MIN || limitval > INT32_MAX) { 1198 dnerror(arg2, D_LQUANT_LIMVAL, "lquantize( ) " 1199 "argument #2 must be a 32-bit quantity\n"); 1200 } 1201 1202 if (limitval < baseval) { 1203 dnerror(dnp, D_LQUANT_MISMATCH, 1204 "lquantize( ) base (argument #1) must be less " 1205 "than limit (argument #2)\n"); 1206 } 1207 1208 if (arg3 != NULL) { 1209 if (!dt_node_is_posconst(arg3)) { 1210 dnerror(arg3, D_LQUANT_STEPTYPE, "lquantize( ) " 1211 "argument #3 must be a non-zero positive " 1212 "integer constant\n"); 1213 } 1214 1215 if ((step = arg3->dn_value) > UINT16_MAX) { 1216 dnerror(arg3, D_LQUANT_STEPVAL, "lquantize( ) " 1217 "argument #3 must be a 16-bit quantity\n"); 1218 } 1219 } 1220 1221 nlevels = (limitval - baseval) / step; 1222 1223 if (nlevels == 0) { 1224 dnerror(dnp, D_LQUANT_STEPLARGE, 1225 "lquantize( ) step (argument #3) too large: must " 1226 "have at least one quantization level\n"); 1227 } 1228 1229 if (nlevels > UINT16_MAX) { 1230 dnerror(dnp, D_LQUANT_STEPSMALL, "lquantize( ) step " 1231 "(argument #3) too small: number of quantization " 1232 "levels must be a 16-bit quantity\n"); 1233 } 1234 1235 arg = (step << DTRACE_LQUANTIZE_STEPSHIFT) | 1236 (nlevels << DTRACE_LQUANTIZE_LEVELSHIFT) | 1237 ((baseval << DTRACE_LQUANTIZE_BASESHIFT) & 1238 DTRACE_LQUANTIZE_BASEMASK); 1239 1240 assert(arg != 0); 1241 1242 isp = (dt_idsig_t *)aid->di_data; 1243 1244 if (isp->dis_auxinfo == 0) { 1245 /* 1246 * This is the first time we've seen an lquantize() 1247 * for this aggregation; we'll store our argument 1248 * as the auxiliary signature information. 1249 */ 1250 isp->dis_auxinfo = arg; 1251 } else if ((oarg = isp->dis_auxinfo) != arg) { 1252 /* 1253 * If we have seen this lquantize() before and the 1254 * argument doesn't match the original argument, pick 1255 * the original argument apart to concisely report the 1256 * mismatch. 1257 */ 1258 int obaseval = DTRACE_LQUANTIZE_BASE(oarg); 1259 int onlevels = DTRACE_LQUANTIZE_LEVELS(oarg); 1260 int ostep = DTRACE_LQUANTIZE_STEP(oarg); 1261 1262 if (obaseval != baseval) { 1263 dnerror(dnp, D_LQUANT_MATCHBASE, "lquantize( ) " 1264 "base (argument #1) doesn't match previous " 1265 "declaration: expected %d, found %d\n", 1266 obaseval, (int)baseval); 1267 } 1268 1269 if (onlevels * ostep != nlevels * step) { 1270 dnerror(dnp, D_LQUANT_MATCHLIM, "lquantize( ) " 1271 "limit (argument #2) doesn't match previous" 1272 " declaration: expected %d, found %d\n", 1273 obaseval + onlevels * ostep, 1274 (int)baseval + (int)nlevels * (int)step); 1275 } 1276 1277 if (ostep != step) { 1278 dnerror(dnp, D_LQUANT_MATCHSTEP, "lquantize( ) " 1279 "step (argument #3) doesn't match previous " 1280 "declaration: expected %d, found %d\n", 1281 ostep, (int)step); 1282 } 1283 1284 /* 1285 * We shouldn't be able to get here -- one of the 1286 * parameters must be mismatched if the arguments 1287 * didn't match. 1288 */ 1289 assert(0); 1290 } 1291 1292 incr = arg3 != NULL ? arg3->dn_list : NULL; 1293 argmax = 5; 1294 } 1295 1296 if (fid->di_id == DTRACEAGG_LLQUANTIZE) { 1297 /* 1298 * For log/linear quantizations, we have between one and five 1299 * arguments in addition to the expression: 1300 * 1301 * arg1 => Factor 1302 * arg2 => Low magnitude 1303 * arg3 => High magnitude 1304 * arg4 => Number of steps per magnitude 1305 * arg5 => Quantization increment value (defaults to 1) 1306 */ 1307 dt_node_t *llarg = dnp->dn_aggfun->dn_args->dn_list; 1308 uint64_t oarg, order, v; 1309 dt_idsig_t *isp; 1310 int i; 1311 1312 struct { 1313 char *str; /* string identifier */ 1314 int badtype; /* error on bad type */ 1315 int badval; /* error on bad value */ 1316 int mismatch; /* error on bad match */ 1317 int shift; /* shift value */ 1318 uint16_t value; /* value itself */ 1319 } args[] = { 1320 { "factor", D_LLQUANT_FACTORTYPE, 1321 D_LLQUANT_FACTORVAL, D_LLQUANT_FACTORMATCH, 1322 DTRACE_LLQUANTIZE_FACTORSHIFT }, 1323 { "low magnitude", D_LLQUANT_LOWTYPE, 1324 D_LLQUANT_LOWVAL, D_LLQUANT_LOWMATCH, 1325 DTRACE_LLQUANTIZE_LOWSHIFT }, 1326 { "high magnitude", D_LLQUANT_HIGHTYPE, 1327 D_LLQUANT_HIGHVAL, D_LLQUANT_HIGHMATCH, 1328 DTRACE_LLQUANTIZE_HIGHSHIFT }, 1329 { "linear steps per magnitude", D_LLQUANT_NSTEPTYPE, 1330 D_LLQUANT_NSTEPVAL, D_LLQUANT_NSTEPMATCH, 1331 DTRACE_LLQUANTIZE_NSTEPSHIFT }, 1332 { NULL } 1333 }; 1334 1335 assert(arg == 0); 1336 1337 for (i = 0; args[i].str != NULL; i++) { 1338 if (llarg->dn_kind != DT_NODE_INT) { 1339 dnerror(llarg, args[i].badtype, "llquantize( ) " 1340 "argument #%d (%s) must be an " 1341 "integer constant\n", i + 1, args[i].str); 1342 } 1343 1344 if ((uint64_t)llarg->dn_value > UINT16_MAX) { 1345 dnerror(llarg, args[i].badval, "llquantize( ) " 1346 "argument #%d (%s) must be an unsigned " 1347 "16-bit quantity\n", i + 1, args[i].str); 1348 } 1349 1350 args[i].value = (uint16_t)llarg->dn_value; 1351 1352 assert(!(arg & (UINT16_MAX << args[i].shift))); 1353 arg |= ((uint64_t)args[i].value << args[i].shift); 1354 llarg = llarg->dn_list; 1355 } 1356 1357 assert(arg != 0); 1358 1359 if (args[0].value < 2) { 1360 dnerror(dnp, D_LLQUANT_FACTORSMALL, "llquantize( ) " 1361 "factor (argument #1) must be two or more\n"); 1362 } 1363 1364 if (args[1].value >= args[2].value) { 1365 dnerror(dnp, D_LLQUANT_MAGRANGE, "llquantize( ) " 1366 "high magnitude (argument #3) must be greater " 1367 "than low magnitude (argument #2)\n"); 1368 } 1369 1370 if (args[3].value < args[0].value) { 1371 dnerror(dnp, D_LLQUANT_FACTORNSTEPS, "llquantize( ) " 1372 "factor (argument #1) must be less than or " 1373 "equal to the number of linear steps per " 1374 "magnitude (argument #4)\n"); 1375 } 1376 1377 for (v = args[0].value; v < args[3].value; v *= args[0].value) 1378 continue; 1379 1380 if ((args[3].value % args[0].value) || (v % args[3].value)) { 1381 dnerror(dnp, D_LLQUANT_FACTOREVEN, "llquantize( ) " 1382 "factor (argument #1) must evenly divide the " 1383 "number of steps per magnitude (argument #4), " 1384 "and the number of steps per magnitude must evenly " 1385 "divide a power of the factor\n"); 1386 } 1387 1388 for (i = 0, order = 1; i < args[2].value; i++) { 1389 if (order * args[0].value > order) { 1390 order *= args[0].value; 1391 continue; 1392 } 1393 1394 dnerror(dnp, D_LLQUANT_MAGTOOBIG, "llquantize( ) " 1395 "factor (%d) raised to power of high magnitude " 1396 "(%d) overflows 64-bits\n", args[0].value, 1397 args[2].value); 1398 } 1399 1400 isp = (dt_idsig_t *)aid->di_data; 1401 1402 if (isp->dis_auxinfo == 0) { 1403 /* 1404 * This is the first time we've seen an llquantize() 1405 * for this aggregation; we'll store our argument 1406 * as the auxiliary signature information. 1407 */ 1408 isp->dis_auxinfo = arg; 1409 } else if ((oarg = isp->dis_auxinfo) != arg) { 1410 /* 1411 * If we have seen this llquantize() before and the 1412 * argument doesn't match the original argument, pick 1413 * the original argument apart to concisely report the 1414 * mismatch. 1415 */ 1416 int expected = 0, found = 0; 1417 1418 for (i = 0; expected == found; i++) { 1419 assert(args[i].str != NULL); 1420 1421 expected = (oarg >> args[i].shift) & UINT16_MAX; 1422 found = (arg >> args[i].shift) & UINT16_MAX; 1423 } 1424 1425 dnerror(dnp, args[i - 1].mismatch, "llquantize( ) " 1426 "%s (argument #%d) doesn't match previous " 1427 "declaration: expected %d, found %d\n", 1428 args[i - 1].str, i, expected, found); 1429 } 1430 1431 incr = llarg; 1432 argmax = 6; 1433 } 1434 1435 if (fid->di_id == DTRACEAGG_QUANTIZE) { 1436 incr = dnp->dn_aggfun->dn_args->dn_list; 1437 argmax = 2; 1438 } 1439 1440 if (incr != NULL) { 1441 if (!dt_node_is_scalar(incr)) { 1442 dnerror(dnp, D_PROTO_ARG, "%s( ) increment value " 1443 "(argument #%d) must be of scalar type\n", 1444 fid->di_name, argmax); 1445 } 1446 1447 if ((anp = incr->dn_list) != NULL) { 1448 int argc = argmax; 1449 1450 for (; anp != NULL; anp = anp->dn_list) 1451 argc++; 1452 1453 dnerror(incr, D_PROTO_LEN, "%s( ) prototype " 1454 "mismatch: %d args passed, at most %d expected", 1455 fid->di_name, argc, argmax); 1456 } 1457 1458 ap = dt_stmt_action(dtp, sdp); 1459 n++; 1460 1461 dt_cg(yypcb, incr); 1462 ap->dtad_difo = dt_as(yypcb); 1463 ap->dtad_difo->dtdo_rtype = dt_void_rtype; 1464 ap->dtad_kind = DTRACEACT_DIFEXPR; 1465 } 1466 1467 assert(sdp->dtsd_aggdata == NULL); 1468 sdp->dtsd_aggdata = aid; 1469 1470 ap = dt_stmt_action(dtp, sdp); 1471 assert(fid->di_kind == DT_IDENT_AGGFUNC); 1472 assert(DTRACEACT_ISAGG(fid->di_id)); 1473 ap->dtad_kind = fid->di_id; 1474 ap->dtad_ntuple = n; 1475 ap->dtad_arg = arg; 1476 1477 if (dnp->dn_aggfun->dn_args != NULL) { 1478 dt_cg(yypcb, dnp->dn_aggfun->dn_args); 1479 ap->dtad_difo = dt_as(yypcb); 1480 } 1481 } 1482 1483 static void 1484 dt_compile_one_clause(dtrace_hdl_t *dtp, dt_node_t *cnp, dt_node_t *pnp) 1485 { 1486 dtrace_ecbdesc_t *edp; 1487 dtrace_stmtdesc_t *sdp; 1488 dt_node_t *dnp; 1489 1490 yylineno = pnp->dn_line; 1491 dt_setcontext(dtp, pnp->dn_desc); 1492 (void) dt_node_cook(cnp, DT_IDFLG_REF); 1493 1494 if (DT_TREEDUMP_PASS(dtp, 2)) 1495 dt_node_printr(cnp, stderr, 0); 1496 1497 if ((edp = dt_ecbdesc_create(dtp, pnp->dn_desc)) == NULL) 1498 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 1499 1500 assert(yypcb->pcb_ecbdesc == NULL); 1501 yypcb->pcb_ecbdesc = edp; 1502 1503 if (cnp->dn_pred != NULL) { 1504 dt_cg(yypcb, cnp->dn_pred); 1505 edp->dted_pred.dtpdd_difo = dt_as(yypcb); 1506 } 1507 1508 if (cnp->dn_acts == NULL) { 1509 dt_stmt_append(dt_stmt_create(dtp, edp, 1510 cnp->dn_ctxattr, _dtrace_defattr), cnp); 1511 } 1512 1513 for (dnp = cnp->dn_acts; dnp != NULL; dnp = dnp->dn_list) { 1514 assert(yypcb->pcb_stmt == NULL); 1515 sdp = dt_stmt_create(dtp, edp, cnp->dn_ctxattr, cnp->dn_attr); 1516 1517 switch (dnp->dn_kind) { 1518 case DT_NODE_DEXPR: 1519 if (dnp->dn_expr->dn_kind == DT_NODE_AGG) 1520 dt_compile_agg(dtp, dnp->dn_expr, sdp); 1521 else 1522 dt_compile_exp(dtp, dnp, sdp); 1523 break; 1524 case DT_NODE_DFUNC: 1525 dt_compile_fun(dtp, dnp, sdp); 1526 break; 1527 case DT_NODE_AGG: 1528 dt_compile_agg(dtp, dnp, sdp); 1529 break; 1530 default: 1531 dnerror(dnp, D_UNKNOWN, "internal error -- node kind " 1532 "%u is not a valid statement\n", dnp->dn_kind); 1533 } 1534 1535 assert(yypcb->pcb_stmt == sdp); 1536 dt_stmt_append(sdp, dnp); 1537 } 1538 1539 assert(yypcb->pcb_ecbdesc == edp); 1540 dt_ecbdesc_release(dtp, edp); 1541 dt_endcontext(dtp); 1542 yypcb->pcb_ecbdesc = NULL; 1543 } 1544 1545 static void 1546 dt_compile_clause(dtrace_hdl_t *dtp, dt_node_t *cnp) 1547 { 1548 dt_node_t *pnp; 1549 1550 for (pnp = cnp->dn_pdescs; pnp != NULL; pnp = pnp->dn_list) 1551 dt_compile_one_clause(dtp, cnp, pnp); 1552 } 1553 1554 static void 1555 dt_compile_xlator(dt_node_t *dnp) 1556 { 1557 dt_xlator_t *dxp = dnp->dn_xlator; 1558 dt_node_t *mnp; 1559 1560 for (mnp = dnp->dn_members; mnp != NULL; mnp = mnp->dn_list) { 1561 assert(dxp->dx_membdif[mnp->dn_membid] == NULL); 1562 dt_cg(yypcb, mnp); 1563 dxp->dx_membdif[mnp->dn_membid] = dt_as(yypcb); 1564 } 1565 } 1566 1567 void 1568 dt_setcontext(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp) 1569 { 1570 const dtrace_pattr_t *pap; 1571 dt_probe_t *prp; 1572 dt_provider_t *pvp; 1573 dt_ident_t *idp; 1574 char attrstr[8]; 1575 int err; 1576 1577 /* 1578 * Both kernel and pid based providers are allowed to have names 1579 * ending with what could be interpreted as a number. We assume it's 1580 * a pid and that we may need to dynamically create probes for 1581 * that process if: 1582 * 1583 * (1) The provider doesn't exist, or, 1584 * (2) The provider exists and has DTRACE_PRIV_PROC privilege. 1585 * 1586 * On an error, dt_pid_create_probes() will set the error message 1587 * and tag -- we just have to longjmp() out of here. 1588 */ 1589 if (isdigit(pdp->dtpd_provider[strlen(pdp->dtpd_provider) - 1]) && 1590 ((pvp = dt_provider_lookup(dtp, pdp->dtpd_provider)) == NULL || 1591 pvp->pv_desc.dtvd_priv.dtpp_flags & DTRACE_PRIV_PROC) && 1592 dt_pid_create_probes(pdp, dtp, yypcb) != 0) { 1593 longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 1594 } 1595 1596 /* 1597 * Call dt_probe_info() to get the probe arguments and attributes. If 1598 * a representative probe is found, set 'pap' to the probe provider's 1599 * attributes. Otherwise set 'pap' to default Unstable attributes. 1600 */ 1601 if ((prp = dt_probe_info(dtp, pdp, &yypcb->pcb_pinfo)) == NULL) { 1602 pap = &_dtrace_prvdesc; 1603 err = dtrace_errno(dtp); 1604 bzero(&yypcb->pcb_pinfo, sizeof (dtrace_probeinfo_t)); 1605 yypcb->pcb_pinfo.dtp_attr = pap->dtpa_provider; 1606 yypcb->pcb_pinfo.dtp_arga = pap->dtpa_args; 1607 } else { 1608 pap = &prp->pr_pvp->pv_desc.dtvd_attr; 1609 err = 0; 1610 } 1611 1612 if (err == EDT_NOPROBE && !(yypcb->pcb_cflags & DTRACE_C_ZDEFS)) { 1613 xyerror(D_PDESC_ZERO, "probe description %s:%s:%s:%s does not " 1614 "match any probes\n", pdp->dtpd_provider, pdp->dtpd_mod, 1615 pdp->dtpd_func, pdp->dtpd_name); 1616 } 1617 1618 if (err != EDT_NOPROBE && err != EDT_UNSTABLE && err != 0) 1619 xyerror(D_PDESC_INVAL, "%s\n", dtrace_errmsg(dtp, err)); 1620 1621 dt_dprintf("set context to %s:%s:%s:%s [%u] prp=%p attr=%s argc=%d\n", 1622 pdp->dtpd_provider, pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name, 1623 pdp->dtpd_id, (void *)prp, dt_attr_str(yypcb->pcb_pinfo.dtp_attr, 1624 attrstr, sizeof (attrstr)), yypcb->pcb_pinfo.dtp_argc); 1625 1626 /* 1627 * Reset the stability attributes of D global variables that vary 1628 * based on the attributes of the provider and context itself. 1629 */ 1630 if ((idp = dt_idhash_lookup(dtp->dt_globals, "probeprov")) != NULL) 1631 idp->di_attr = pap->dtpa_provider; 1632 if ((idp = dt_idhash_lookup(dtp->dt_globals, "probemod")) != NULL) 1633 idp->di_attr = pap->dtpa_mod; 1634 if ((idp = dt_idhash_lookup(dtp->dt_globals, "probefunc")) != NULL) 1635 idp->di_attr = pap->dtpa_func; 1636 if ((idp = dt_idhash_lookup(dtp->dt_globals, "probename")) != NULL) 1637 idp->di_attr = pap->dtpa_name; 1638 if ((idp = dt_idhash_lookup(dtp->dt_globals, "args")) != NULL) 1639 idp->di_attr = pap->dtpa_args; 1640 1641 yypcb->pcb_pdesc = pdp; 1642 yypcb->pcb_probe = prp; 1643 } 1644 1645 /* 1646 * Reset context-dependent variables and state at the end of cooking a D probe 1647 * definition clause. This ensures that external declarations between clauses 1648 * do not reference any stale context-dependent data from the previous clause. 1649 */ 1650 void 1651 dt_endcontext(dtrace_hdl_t *dtp) 1652 { 1653 static const char *const cvars[] = { 1654 "probeprov", "probemod", "probefunc", "probename", "args", NULL 1655 }; 1656 1657 dt_ident_t *idp; 1658 int i; 1659 1660 for (i = 0; cvars[i] != NULL; i++) { 1661 if ((idp = dt_idhash_lookup(dtp->dt_globals, cvars[i])) != NULL) 1662 idp->di_attr = _dtrace_defattr; 1663 } 1664 1665 yypcb->pcb_pdesc = NULL; 1666 yypcb->pcb_probe = NULL; 1667 } 1668 1669 static int 1670 dt_reduceid(dt_idhash_t *dhp, dt_ident_t *idp, dtrace_hdl_t *dtp) 1671 { 1672 if (idp->di_vers != 0 && idp->di_vers > dtp->dt_vmax) 1673 dt_idhash_delete(dhp, idp); 1674 1675 return (0); 1676 } 1677 1678 /* 1679 * When dtrace_setopt() is called for "version", it calls dt_reduce() to remove 1680 * any identifiers or translators that have been previously defined as bound to 1681 * a version greater than the specified version. Therefore, in our current 1682 * version implementation, establishing a binding is a one-way transformation. 1683 * In addition, no versioning is currently provided for types as our .d library 1684 * files do not define any types and we reserve prefixes DTRACE_ and dtrace_ 1685 * for our exclusive use. If required, type versioning will require more work. 1686 */ 1687 int 1688 dt_reduce(dtrace_hdl_t *dtp, dt_version_t v) 1689 { 1690 char s[DT_VERSION_STRMAX]; 1691 dt_xlator_t *dxp, *nxp; 1692 1693 if (v > dtp->dt_vmax) 1694 return (dt_set_errno(dtp, EDT_VERSREDUCED)); 1695 else if (v == dtp->dt_vmax) 1696 return (0); /* no reduction necessary */ 1697 1698 dt_dprintf("reducing api version to %s\n", 1699 dt_version_num2str(v, s, sizeof (s))); 1700 1701 dtp->dt_vmax = v; 1702 1703 for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; dxp = nxp) { 1704 nxp = dt_list_next(dxp); 1705 if ((dxp->dx_souid.di_vers != 0 && dxp->dx_souid.di_vers > v) || 1706 (dxp->dx_ptrid.di_vers != 0 && dxp->dx_ptrid.di_vers > v)) 1707 dt_list_delete(&dtp->dt_xlators, dxp); 1708 } 1709 1710 (void) dt_idhash_iter(dtp->dt_macros, (dt_idhash_f *)dt_reduceid, dtp); 1711 (void) dt_idhash_iter(dtp->dt_aggs, (dt_idhash_f *)dt_reduceid, dtp); 1712 (void) dt_idhash_iter(dtp->dt_globals, (dt_idhash_f *)dt_reduceid, dtp); 1713 (void) dt_idhash_iter(dtp->dt_tls, (dt_idhash_f *)dt_reduceid, dtp); 1714 1715 return (0); 1716 } 1717 1718 /* 1719 * Fork and exec the cpp(1) preprocessor to run over the specified input file, 1720 * and return a FILE handle for the cpp output. We use the /dev/fd filesystem 1721 * here to simplify the code by leveraging file descriptor inheritance. 1722 */ 1723 static FILE * 1724 dt_preproc(dtrace_hdl_t *dtp, FILE *ifp) 1725 { 1726 int argc = dtp->dt_cpp_argc; 1727 char **argv = malloc(sizeof (char *) * (argc + 5)); 1728 FILE *ofp = tmpfile(); 1729 1730 char ipath[20], opath[20]; /* big enough for /dev/fd/ + INT_MAX + \0 */ 1731 char verdef[32]; /* big enough for -D__SUNW_D_VERSION=0x%08x + \0 */ 1732 1733 struct sigaction act, oact; 1734 sigset_t mask, omask; 1735 1736 int wstat, estat; 1737 pid_t pid; 1738 off64_t off; 1739 int c; 1740 1741 if (argv == NULL || ofp == NULL) { 1742 (void) dt_set_errno(dtp, errno); 1743 goto err; 1744 } 1745 1746 /* 1747 * If the input is a seekable file, see if it is an interpreter file. 1748 * If we see #!, seek past the first line because cpp will choke on it. 1749 * We start cpp just prior to the \n at the end of this line so that 1750 * it still sees the newline, ensuring that #line values are correct. 1751 */ 1752 if (isatty(fileno(ifp)) == 0 && (off = ftello64(ifp)) != -1) { 1753 if ((c = fgetc(ifp)) == '#' && (c = fgetc(ifp)) == '!') { 1754 for (off += 2; c != '\n'; off++) { 1755 if ((c = fgetc(ifp)) == EOF) 1756 break; 1757 } 1758 if (c == '\n') 1759 off--; /* start cpp just prior to \n */ 1760 } 1761 (void) fflush(ifp); 1762 (void) fseeko64(ifp, off, SEEK_SET); 1763 } 1764 1765 (void) snprintf(ipath, sizeof (ipath), "/dev/fd/%d", fileno(ifp)); 1766 (void) snprintf(opath, sizeof (opath), "/dev/fd/%d", fileno(ofp)); 1767 1768 bcopy(dtp->dt_cpp_argv, argv, sizeof (char *) * argc); 1769 1770 (void) snprintf(verdef, sizeof (verdef), 1771 "-D__SUNW_D_VERSION=0x%08x", dtp->dt_vmax); 1772 argv[argc++] = verdef; 1773 1774 switch (dtp->dt_stdcmode) { 1775 case DT_STDC_XA: 1776 case DT_STDC_XT: 1777 argv[argc++] = "-D__STDC__=0"; 1778 break; 1779 case DT_STDC_XC: 1780 argv[argc++] = "-D__STDC__=1"; 1781 break; 1782 } 1783 1784 argv[argc++] = ipath; 1785 argv[argc++] = opath; 1786 argv[argc] = NULL; 1787 1788 /* 1789 * libdtrace must be able to be embedded in other programs that may 1790 * include application-specific signal handlers. Therefore, if we 1791 * need to fork to run cpp(1), we must avoid generating a SIGCHLD 1792 * that could confuse the containing application. To do this, 1793 * we block SIGCHLD and reset its disposition to SIG_DFL. 1794 * We restore our signal state once we are done. 1795 */ 1796 (void) sigemptyset(&mask); 1797 (void) sigaddset(&mask, SIGCHLD); 1798 (void) sigprocmask(SIG_BLOCK, &mask, &omask); 1799 1800 bzero(&act, sizeof (act)); 1801 act.sa_handler = SIG_DFL; 1802 (void) sigaction(SIGCHLD, &act, &oact); 1803 1804 if ((pid = fork1()) == -1) { 1805 (void) sigaction(SIGCHLD, &oact, NULL); 1806 (void) sigprocmask(SIG_SETMASK, &omask, NULL); 1807 (void) dt_set_errno(dtp, EDT_CPPFORK); 1808 goto err; 1809 } 1810 1811 if (pid == 0) { 1812 (void) execvp(dtp->dt_cpp_path, argv); 1813 _exit(errno == ENOENT ? 127 : 126); 1814 } 1815 1816 do { 1817 dt_dprintf("waiting for %s (PID %d)\n", dtp->dt_cpp_path, 1818 (int)pid); 1819 } while (waitpid(pid, &wstat, 0) == -1 && errno == EINTR); 1820 1821 (void) sigaction(SIGCHLD, &oact, NULL); 1822 (void) sigprocmask(SIG_SETMASK, &omask, NULL); 1823 1824 dt_dprintf("%s returned exit status 0x%x\n", dtp->dt_cpp_path, wstat); 1825 estat = WIFEXITED(wstat) ? WEXITSTATUS(wstat) : -1; 1826 1827 if (estat != 0) { 1828 switch (estat) { 1829 case 126: 1830 (void) dt_set_errno(dtp, EDT_CPPEXEC); 1831 break; 1832 case 127: 1833 (void) dt_set_errno(dtp, EDT_CPPENT); 1834 break; 1835 default: 1836 (void) dt_set_errno(dtp, EDT_CPPERR); 1837 } 1838 goto err; 1839 } 1840 1841 free(argv); 1842 (void) fflush(ofp); 1843 (void) fseek(ofp, 0, SEEK_SET); 1844 return (ofp); 1845 1846 err: 1847 free(argv); 1848 (void) fclose(ofp); 1849 return (NULL); 1850 } 1851 1852 static void 1853 dt_lib_depend_error(dtrace_hdl_t *dtp, const char *format, ...) 1854 { 1855 va_list ap; 1856 1857 va_start(ap, format); 1858 dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap); 1859 va_end(ap); 1860 } 1861 1862 int 1863 dt_lib_depend_add(dtrace_hdl_t *dtp, dt_list_t *dlp, const char *arg) 1864 { 1865 dt_lib_depend_t *dld; 1866 const char *end; 1867 1868 assert(arg != NULL); 1869 1870 if ((end = strrchr(arg, '/')) == NULL) 1871 return (dt_set_errno(dtp, EINVAL)); 1872 1873 if ((dld = dt_zalloc(dtp, sizeof (dt_lib_depend_t))) == NULL) 1874 return (-1); 1875 1876 if ((dld->dtld_libpath = dt_alloc(dtp, MAXPATHLEN)) == NULL) { 1877 dt_free(dtp, dld); 1878 return (-1); 1879 } 1880 1881 (void) strlcpy(dld->dtld_libpath, arg, end - arg + 2); 1882 if ((dld->dtld_library = strdup(arg)) == NULL) { 1883 dt_free(dtp, dld->dtld_libpath); 1884 dt_free(dtp, dld); 1885 return (dt_set_errno(dtp, EDT_NOMEM)); 1886 } 1887 1888 dt_list_append(dlp, dld); 1889 return (0); 1890 } 1891 1892 dt_lib_depend_t * 1893 dt_lib_depend_lookup(dt_list_t *dld, const char *arg) 1894 { 1895 dt_lib_depend_t *dldn; 1896 1897 for (dldn = dt_list_next(dld); dldn != NULL; 1898 dldn = dt_list_next(dldn)) { 1899 if (strcmp(dldn->dtld_library, arg) == 0) 1900 return (dldn); 1901 } 1902 1903 return (NULL); 1904 } 1905 1906 /* 1907 * Go through all the library files, and, if any library dependencies exist for 1908 * that file, add it to that node's list of dependents. The result of this 1909 * will be a graph which can then be topologically sorted to produce a 1910 * compilation order. 1911 */ 1912 static int 1913 dt_lib_build_graph(dtrace_hdl_t *dtp) 1914 { 1915 dt_lib_depend_t *dld, *dpld; 1916 1917 for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL; 1918 dld = dt_list_next(dld)) { 1919 char *library = dld->dtld_library; 1920 1921 for (dpld = dt_list_next(&dld->dtld_dependencies); dpld != NULL; 1922 dpld = dt_list_next(dpld)) { 1923 dt_lib_depend_t *dlda; 1924 1925 if ((dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep, 1926 dpld->dtld_library)) == NULL) { 1927 dt_lib_depend_error(dtp, 1928 "Invalid library dependency in %s: %s\n", 1929 dld->dtld_library, dpld->dtld_library); 1930 1931 return (dt_set_errno(dtp, EDT_COMPILER)); 1932 } 1933 1934 if ((dt_lib_depend_add(dtp, &dlda->dtld_dependents, 1935 library)) != 0) { 1936 return (-1); /* preserve dt_errno */ 1937 } 1938 } 1939 } 1940 return (0); 1941 } 1942 1943 static int 1944 dt_topo_sort(dtrace_hdl_t *dtp, dt_lib_depend_t *dld, int *count) 1945 { 1946 dt_lib_depend_t *dpld, *dlda, *new; 1947 1948 dld->dtld_start = ++(*count); 1949 1950 for (dpld = dt_list_next(&dld->dtld_dependents); dpld != NULL; 1951 dpld = dt_list_next(dpld)) { 1952 dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep, 1953 dpld->dtld_library); 1954 assert(dlda != NULL); 1955 1956 if (dlda->dtld_start == 0 && 1957 dt_topo_sort(dtp, dlda, count) == -1) 1958 return (-1); 1959 } 1960 1961 if ((new = dt_zalloc(dtp, sizeof (dt_lib_depend_t))) == NULL) 1962 return (-1); 1963 1964 if ((new->dtld_library = strdup(dld->dtld_library)) == NULL) { 1965 dt_free(dtp, new); 1966 return (dt_set_errno(dtp, EDT_NOMEM)); 1967 } 1968 1969 new->dtld_start = dld->dtld_start; 1970 new->dtld_finish = dld->dtld_finish = ++(*count); 1971 dt_list_prepend(&dtp->dt_lib_dep_sorted, new); 1972 1973 dt_dprintf("library %s sorted (%d/%d)\n", new->dtld_library, 1974 new->dtld_start, new->dtld_finish); 1975 1976 return (0); 1977 } 1978 1979 static int 1980 dt_lib_depend_sort(dtrace_hdl_t *dtp) 1981 { 1982 dt_lib_depend_t *dld, *dpld, *dlda; 1983 int count = 0; 1984 1985 if (dt_lib_build_graph(dtp) == -1) 1986 return (-1); /* preserve dt_errno */ 1987 1988 /* 1989 * Perform a topological sort of the graph that hangs off 1990 * dtp->dt_lib_dep. The result of this process will be a 1991 * dependency ordered list located at dtp->dt_lib_dep_sorted. 1992 */ 1993 for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL; 1994 dld = dt_list_next(dld)) { 1995 if (dld->dtld_start == 0 && 1996 dt_topo_sort(dtp, dld, &count) == -1) 1997 return (-1); /* preserve dt_errno */; 1998 } 1999 2000 /* 2001 * Check the graph for cycles. If an ancestor's finishing time is 2002 * less than any of its dependent's finishing times then a back edge 2003 * exists in the graph and this is a cycle. 2004 */ 2005 for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL; 2006 dld = dt_list_next(dld)) { 2007 for (dpld = dt_list_next(&dld->dtld_dependents); dpld != NULL; 2008 dpld = dt_list_next(dpld)) { 2009 dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep_sorted, 2010 dpld->dtld_library); 2011 assert(dlda != NULL); 2012 2013 if (dlda->dtld_finish > dld->dtld_finish) { 2014 dt_lib_depend_error(dtp, 2015 "Cyclic dependency detected: %s => %s\n", 2016 dld->dtld_library, dpld->dtld_library); 2017 2018 return (dt_set_errno(dtp, EDT_COMPILER)); 2019 } 2020 } 2021 } 2022 2023 return (0); 2024 } 2025 2026 static void 2027 dt_lib_depend_free(dtrace_hdl_t *dtp) 2028 { 2029 dt_lib_depend_t *dld, *dlda; 2030 2031 while ((dld = dt_list_next(&dtp->dt_lib_dep)) != NULL) { 2032 while ((dlda = dt_list_next(&dld->dtld_dependencies)) != NULL) { 2033 dt_list_delete(&dld->dtld_dependencies, dlda); 2034 dt_free(dtp, dlda->dtld_library); 2035 dt_free(dtp, dlda->dtld_libpath); 2036 dt_free(dtp, dlda); 2037 } 2038 while ((dlda = dt_list_next(&dld->dtld_dependents)) != NULL) { 2039 dt_list_delete(&dld->dtld_dependents, dlda); 2040 dt_free(dtp, dlda->dtld_library); 2041 dt_free(dtp, dlda->dtld_libpath); 2042 dt_free(dtp, dlda); 2043 } 2044 dt_list_delete(&dtp->dt_lib_dep, dld); 2045 dt_free(dtp, dld->dtld_library); 2046 dt_free(dtp, dld->dtld_libpath); 2047 dt_free(dtp, dld); 2048 } 2049 2050 while ((dld = dt_list_next(&dtp->dt_lib_dep_sorted)) != NULL) { 2051 dt_list_delete(&dtp->dt_lib_dep_sorted, dld); 2052 dt_free(dtp, dld->dtld_library); 2053 dt_free(dtp, dld); 2054 } 2055 } 2056 2057 /* 2058 * Open all the .d library files found in the specified directory and 2059 * compile each one of them. We silently ignore any missing directories and 2060 * other files found therein. We only fail (and thereby fail dt_load_libs()) if 2061 * we fail to compile a library and the error is something other than #pragma D 2062 * depends_on. Dependency errors are silently ignored to permit a library 2063 * directory to contain libraries which may not be accessible depending on our 2064 * privileges. 2065 */ 2066 static int 2067 dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path) 2068 { 2069 struct dirent *dp; 2070 const char *p, *end; 2071 DIR *dirp; 2072 2073 char fname[PATH_MAX]; 2074 FILE *fp; 2075 void *rv; 2076 dt_lib_depend_t *dld; 2077 2078 if ((dirp = opendir(path)) == NULL) { 2079 dt_dprintf("skipping lib dir %s: %s\n", path, strerror(errno)); 2080 return (0); 2081 } 2082 2083 /* First, parse each file for library dependencies. */ 2084 while ((dp = readdir(dirp)) != NULL) { 2085 if ((p = strrchr(dp->d_name, '.')) == NULL || strcmp(p, ".d")) 2086 continue; /* skip any filename not ending in .d */ 2087 2088 (void) snprintf(fname, sizeof (fname), 2089 "%s/%s", path, dp->d_name); 2090 2091 if ((fp = fopen(fname, "r")) == NULL) { 2092 dt_dprintf("skipping library %s: %s\n", 2093 fname, strerror(errno)); 2094 continue; 2095 } 2096 2097 /* 2098 * Skip files whose name match an already processed library 2099 */ 2100 for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL; 2101 dld = dt_list_next(dld)) { 2102 end = strrchr(dld->dtld_library, '/'); 2103 /* dt_lib_depend_add ensures this */ 2104 assert(end != NULL); 2105 if (strcmp(end + 1, dp->d_name) == 0) 2106 break; 2107 } 2108 2109 if (dld != NULL) { 2110 dt_dprintf("skipping library %s, already processed " 2111 "library with the same name: %s", dp->d_name, 2112 dld->dtld_library); 2113 continue; 2114 } 2115 2116 dtp->dt_filetag = fname; 2117 if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0) 2118 return (-1); /* preserve dt_errno */ 2119 2120 rv = dt_compile(dtp, DT_CTX_DPROG, 2121 DTRACE_PROBESPEC_NAME, NULL, 2122 DTRACE_C_EMPTY | DTRACE_C_CTL, 0, NULL, fp, NULL); 2123 2124 if (rv != NULL && dtp->dt_errno && 2125 (dtp->dt_errno != EDT_COMPILER || 2126 dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND))) 2127 return (-1); /* preserve dt_errno */ 2128 2129 if (dtp->dt_errno) 2130 dt_dprintf("error parsing library %s: %s\n", 2131 fname, dtrace_errmsg(dtp, dtrace_errno(dtp))); 2132 2133 (void) fclose(fp); 2134 dtp->dt_filetag = NULL; 2135 } 2136 2137 (void) closedir(dirp); 2138 2139 return (0); 2140 } 2141 2142 /* 2143 * Perform a topological sorting of all the libraries found across the entire 2144 * dt_lib_path. Once sorted, compile each one in topological order to cache its 2145 * inlines and translators, etc. We silently ignore any missing directories and 2146 * other files found therein. We only fail (and thereby fail dt_load_libs()) if 2147 * we fail to compile a library and the error is something other than #pragma D 2148 * depends_on. Dependency errors are silently ignored to permit a library 2149 * directory to contain libraries which may not be accessible depending on our 2150 * privileges. 2151 */ 2152 static int 2153 dt_load_libs_sort(dtrace_hdl_t *dtp) 2154 { 2155 dtrace_prog_t *pgp; 2156 FILE *fp; 2157 dt_lib_depend_t *dld; 2158 2159 /* 2160 * Finish building the graph containing the library dependencies 2161 * and perform a topological sort to generate an ordered list 2162 * for compilation. 2163 */ 2164 if (dt_lib_depend_sort(dtp) == -1) 2165 goto err; 2166 2167 for (dld = dt_list_next(&dtp->dt_lib_dep_sorted); dld != NULL; 2168 dld = dt_list_next(dld)) { 2169 2170 if ((fp = fopen(dld->dtld_library, "r")) == NULL) { 2171 dt_dprintf("skipping library %s: %s\n", 2172 dld->dtld_library, strerror(errno)); 2173 continue; 2174 } 2175 2176 dtp->dt_filetag = dld->dtld_library; 2177 pgp = dtrace_program_fcompile(dtp, fp, DTRACE_C_EMPTY, 0, NULL); 2178 (void) fclose(fp); 2179 dtp->dt_filetag = NULL; 2180 2181 if (pgp == NULL && (dtp->dt_errno != EDT_COMPILER || 2182 dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND))) 2183 goto err; 2184 2185 if (pgp == NULL) { 2186 dt_dprintf("skipping library %s: %s\n", 2187 dld->dtld_library, 2188 dtrace_errmsg(dtp, dtrace_errno(dtp))); 2189 } else { 2190 dld->dtld_loaded = B_TRUE; 2191 dt_program_destroy(dtp, pgp); 2192 } 2193 } 2194 2195 dt_lib_depend_free(dtp); 2196 return (0); 2197 2198 err: 2199 dt_lib_depend_free(dtp); 2200 return (-1); /* preserve dt_errno */ 2201 } 2202 2203 /* 2204 * Load the contents of any appropriate DTrace .d library files. These files 2205 * contain inlines and translators that will be cached by the compiler. We 2206 * defer this activity until the first compile to permit libdtrace clients to 2207 * add their own library directories and so that we can properly report errors. 2208 */ 2209 static int 2210 dt_load_libs(dtrace_hdl_t *dtp) 2211 { 2212 dt_dirpath_t *dirp; 2213 2214 if (dtp->dt_cflags & DTRACE_C_NOLIBS) 2215 return (0); /* libraries already processed */ 2216 2217 dtp->dt_cflags |= DTRACE_C_NOLIBS; 2218 2219 /* 2220 * /usr/lib/dtrace is always at the head of the list. The rest of the 2221 * list is specified in the precedence order the user requested. Process 2222 * everything other than the head first. DTRACE_C_NOLIBS has already 2223 * been spcified so dt_vopen will ensure that there is always one entry 2224 * in dt_lib_path. 2225 */ 2226 for (dirp = dt_list_next(dt_list_next(&dtp->dt_lib_path)); 2227 dirp != NULL; dirp = dt_list_next(dirp)) { 2228 if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) { 2229 dtp->dt_cflags &= ~DTRACE_C_NOLIBS; 2230 return (-1); /* errno is set for us */ 2231 } 2232 } 2233 2234 /* Handle /usr/lib/dtrace */ 2235 dirp = dt_list_next(&dtp->dt_lib_path); 2236 if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) { 2237 dtp->dt_cflags &= ~DTRACE_C_NOLIBS; 2238 return (-1); /* errno is set for us */ 2239 } 2240 2241 if (dt_load_libs_sort(dtp) < 0) 2242 return (-1); /* errno is set for us */ 2243 2244 return (0); 2245 } 2246 2247 static void * 2248 dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg, 2249 uint_t cflags, int argc, char *const argv[], FILE *fp, const char *s) 2250 { 2251 dt_node_t *dnp; 2252 dt_decl_t *ddp; 2253 dt_pcb_t pcb; 2254 void *rv; 2255 int err; 2256 2257 if ((fp == NULL && s == NULL) || (cflags & ~DTRACE_C_MASK) != 0) { 2258 (void) dt_set_errno(dtp, EINVAL); 2259 return (NULL); 2260 } 2261 2262 if (dt_list_next(&dtp->dt_lib_path) != NULL && dt_load_libs(dtp) != 0) 2263 return (NULL); /* errno is set for us */ 2264 2265 if (dtp->dt_globals->dh_nelems != 0) 2266 (void) dt_idhash_iter(dtp->dt_globals, dt_idreset, NULL); 2267 2268 if (dtp->dt_tls->dh_nelems != 0) 2269 (void) dt_idhash_iter(dtp->dt_tls, dt_idreset, NULL); 2270 2271 if (fp && (cflags & DTRACE_C_CPP) && (fp = dt_preproc(dtp, fp)) == NULL) 2272 return (NULL); /* errno is set for us */ 2273 2274 dt_pcb_push(dtp, &pcb); 2275 2276 pcb.pcb_fileptr = fp; 2277 pcb.pcb_string = s; 2278 pcb.pcb_strptr = s; 2279 pcb.pcb_strlen = s ? strlen(s) : 0; 2280 pcb.pcb_sargc = argc; 2281 pcb.pcb_sargv = argv; 2282 pcb.pcb_sflagv = argc ? calloc(argc, sizeof (ushort_t)) : NULL; 2283 pcb.pcb_pspec = pspec; 2284 pcb.pcb_cflags = dtp->dt_cflags | cflags; 2285 pcb.pcb_amin = dtp->dt_amin; 2286 pcb.pcb_yystate = -1; 2287 pcb.pcb_context = context; 2288 pcb.pcb_token = context; 2289 2290 if (context != DT_CTX_DPROG) 2291 yybegin(YYS_EXPR); 2292 else if (cflags & DTRACE_C_CTL) 2293 yybegin(YYS_CONTROL); 2294 else 2295 yybegin(YYS_CLAUSE); 2296 2297 if ((err = setjmp(yypcb->pcb_jmpbuf)) != 0) 2298 goto out; 2299 2300 if (yypcb->pcb_sargc != 0 && yypcb->pcb_sflagv == NULL) 2301 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2302 2303 yypcb->pcb_idents = dt_idhash_create("ambiguous", NULL, 0, 0); 2304 yypcb->pcb_locals = dt_idhash_create("clause local", NULL, 2305 DIF_VAR_OTHER_UBASE, DIF_VAR_OTHER_MAX); 2306 2307 if (yypcb->pcb_idents == NULL || yypcb->pcb_locals == NULL) 2308 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2309 2310 /* 2311 * Invoke the parser to evaluate the D source code. If any errors 2312 * occur during parsing, an error function will be called and we 2313 * will longjmp back to pcb_jmpbuf to abort. If parsing succeeds, 2314 * we optionally display the parse tree if debugging is enabled. 2315 */ 2316 if (yyparse() != 0 || yypcb->pcb_root == NULL) 2317 xyerror(D_EMPTY, "empty D program translation unit\n"); 2318 2319 yybegin(YYS_DONE); 2320 2321 if (cflags & DTRACE_C_CTL) 2322 goto out; 2323 2324 if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 1)) 2325 dt_node_printr(yypcb->pcb_root, stderr, 0); 2326 2327 if (yypcb->pcb_pragmas != NULL) 2328 (void) dt_idhash_iter(yypcb->pcb_pragmas, dt_idpragma, NULL); 2329 2330 if (argc > 1 && !(yypcb->pcb_cflags & DTRACE_C_ARGREF) && 2331 !(yypcb->pcb_sflagv[argc - 1] & DT_IDFLG_REF)) { 2332 xyerror(D_MACRO_UNUSED, "extraneous argument '%s' ($%d is " 2333 "not referenced)\n", yypcb->pcb_sargv[argc - 1], argc - 1); 2334 } 2335 2336 /* 2337 * If we have successfully created a parse tree for a D program, loop 2338 * over the clauses and actions and instantiate the corresponding 2339 * libdtrace program. If we are parsing a D expression, then we 2340 * simply run the code generator and assembler on the resulting tree. 2341 */ 2342 switch (context) { 2343 case DT_CTX_DPROG: 2344 assert(yypcb->pcb_root->dn_kind == DT_NODE_PROG); 2345 2346 if ((dnp = yypcb->pcb_root->dn_list) == NULL && 2347 !(yypcb->pcb_cflags & DTRACE_C_EMPTY)) 2348 xyerror(D_EMPTY, "empty D program translation unit\n"); 2349 2350 if ((yypcb->pcb_prog = dt_program_create(dtp)) == NULL) 2351 longjmp(yypcb->pcb_jmpbuf, dtrace_errno(dtp)); 2352 2353 for (; dnp != NULL; dnp = dnp->dn_list) { 2354 switch (dnp->dn_kind) { 2355 case DT_NODE_CLAUSE: 2356 dt_compile_clause(dtp, dnp); 2357 break; 2358 case DT_NODE_XLATOR: 2359 if (dtp->dt_xlatemode == DT_XL_DYNAMIC) 2360 dt_compile_xlator(dnp); 2361 break; 2362 case DT_NODE_PROVIDER: 2363 (void) dt_node_cook(dnp, DT_IDFLG_REF); 2364 break; 2365 } 2366 } 2367 2368 yypcb->pcb_prog->dp_xrefs = yypcb->pcb_asxrefs; 2369 yypcb->pcb_prog->dp_xrefslen = yypcb->pcb_asxreflen; 2370 yypcb->pcb_asxrefs = NULL; 2371 yypcb->pcb_asxreflen = 0; 2372 2373 rv = yypcb->pcb_prog; 2374 break; 2375 2376 case DT_CTX_DEXPR: 2377 (void) dt_node_cook(yypcb->pcb_root, DT_IDFLG_REF); 2378 dt_cg(yypcb, yypcb->pcb_root); 2379 rv = dt_as(yypcb); 2380 break; 2381 2382 case DT_CTX_DTYPE: 2383 ddp = (dt_decl_t *)yypcb->pcb_root; /* root is really a decl */ 2384 err = dt_decl_type(ddp, arg); 2385 dt_decl_free(ddp); 2386 2387 if (err != 0) 2388 longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 2389 2390 rv = NULL; 2391 break; 2392 } 2393 2394 out: 2395 if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 3)) 2396 dt_node_printr(yypcb->pcb_root, stderr, 0); 2397 2398 if (dtp->dt_cdefs_fd != -1 && (ftruncate64(dtp->dt_cdefs_fd, 0) == -1 || 2399 lseek64(dtp->dt_cdefs_fd, 0, SEEK_SET) == -1 || 2400 ctf_write(dtp->dt_cdefs->dm_ctfp, dtp->dt_cdefs_fd) == CTF_ERR)) 2401 dt_dprintf("failed to update CTF cache: %s\n", strerror(errno)); 2402 2403 if (dtp->dt_ddefs_fd != -1 && (ftruncate64(dtp->dt_ddefs_fd, 0) == -1 || 2404 lseek64(dtp->dt_ddefs_fd, 0, SEEK_SET) == -1 || 2405 ctf_write(dtp->dt_ddefs->dm_ctfp, dtp->dt_ddefs_fd) == CTF_ERR)) 2406 dt_dprintf("failed to update CTF cache: %s\n", strerror(errno)); 2407 2408 if (yypcb->pcb_fileptr && (cflags & DTRACE_C_CPP)) 2409 (void) fclose(yypcb->pcb_fileptr); /* close dt_preproc() file */ 2410 2411 dt_pcb_pop(dtp, err); 2412 (void) dt_set_errno(dtp, err); 2413 return (err ? NULL : rv); 2414 } 2415 2416 dtrace_prog_t * 2417 dtrace_program_strcompile(dtrace_hdl_t *dtp, const char *s, 2418 dtrace_probespec_t spec, uint_t cflags, int argc, char *const argv[]) 2419 { 2420 return (dt_compile(dtp, DT_CTX_DPROG, 2421 spec, NULL, cflags, argc, argv, NULL, s)); 2422 } 2423 2424 dtrace_prog_t * 2425 dtrace_program_fcompile(dtrace_hdl_t *dtp, FILE *fp, 2426 uint_t cflags, int argc, char *const argv[]) 2427 { 2428 return (dt_compile(dtp, DT_CTX_DPROG, 2429 DTRACE_PROBESPEC_NAME, NULL, cflags, argc, argv, fp, NULL)); 2430 } 2431 2432 int 2433 dtrace_type_strcompile(dtrace_hdl_t *dtp, const char *s, dtrace_typeinfo_t *dtt) 2434 { 2435 (void) dt_compile(dtp, DT_CTX_DTYPE, 2436 DTRACE_PROBESPEC_NONE, dtt, 0, 0, NULL, NULL, s); 2437 return (dtp->dt_errno ? -1 : 0); 2438 } 2439 2440 int 2441 dtrace_type_fcompile(dtrace_hdl_t *dtp, FILE *fp, dtrace_typeinfo_t *dtt) 2442 { 2443 (void) dt_compile(dtp, DT_CTX_DTYPE, 2444 DTRACE_PROBESPEC_NONE, dtt, 0, 0, NULL, fp, NULL); 2445 return (dtp->dt_errno ? -1 : 0); 2446 } 2447