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