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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/resource.h> 28 #include <sys/mman.h> 29 #include <sys/types.h> 30 31 #include <strings.h> 32 #include <signal.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <limits.h> 36 #include <alloca.h> 37 #include <errno.h> 38 #include <fcntl.h> 39 40 #include <dt_impl.h> 41 #include <dt_string.h> 42 43 static int 44 dt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 45 { 46 dt_aggregate_t *agp = &dtp->dt_aggregate; 47 48 if (arg != NULL) 49 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 50 51 agp->dtat_flags |= option; 52 return (0); 53 } 54 55 /*ARGSUSED*/ 56 static int 57 dt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 58 { 59 char str[DTRACE_ATTR2STR_MAX]; 60 dtrace_attribute_t attr; 61 62 if (arg == NULL || dtrace_str2attr(arg, &attr) == -1) 63 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 64 65 dt_dprintf("set compiler attribute minimum to %s\n", 66 dtrace_attr2str(attr, str, sizeof (str))); 67 68 if (dtp->dt_pcb != NULL) { 69 dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR; 70 dtp->dt_pcb->pcb_amin = attr; 71 } else { 72 dtp->dt_cflags |= DTRACE_C_EATTR; 73 dtp->dt_amin = attr; 74 } 75 76 return (0); 77 } 78 79 static void 80 dt_coredump(void) 81 { 82 const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n"; 83 84 struct sigaction act; 85 struct rlimit lim; 86 87 (void) write(STDERR_FILENO, msg, sizeof (msg) - 1); 88 89 act.sa_handler = SIG_DFL; 90 act.sa_flags = 0; 91 92 (void) sigemptyset(&act.sa_mask); 93 (void) sigaction(SIGABRT, &act, NULL); 94 95 lim.rlim_cur = RLIM_INFINITY; 96 lim.rlim_max = RLIM_INFINITY; 97 98 (void) setrlimit(RLIMIT_CORE, &lim); 99 abort(); 100 } 101 102 /*ARGSUSED*/ 103 static int 104 dt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 105 { 106 static int enabled = 0; 107 108 if (arg != NULL) 109 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 110 111 if (enabled++ || atexit(dt_coredump) == 0) 112 return (0); 113 114 return (dt_set_errno(dtp, errno)); 115 } 116 117 /*ARGSUSED*/ 118 static int 119 dt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 120 { 121 if (arg != NULL) 122 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 123 124 if (dtp->dt_pcb != NULL) 125 return (dt_set_errno(dtp, EDT_BADOPTCTX)); 126 127 if (dt_cpp_add_arg(dtp, "-H") == NULL) 128 return (dt_set_errno(dtp, EDT_NOMEM)); 129 130 return (0); 131 } 132 133 /*ARGSUSED*/ 134 static int 135 dt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 136 { 137 char *cpp; 138 139 if (arg == NULL) 140 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 141 142 if (dtp->dt_pcb != NULL) 143 return (dt_set_errno(dtp, EDT_BADOPTCTX)); 144 145 if ((cpp = strdup(arg)) == NULL) 146 return (dt_set_errno(dtp, EDT_NOMEM)); 147 148 dtp->dt_cpp_argv[0] = (char *)strbasename(cpp); 149 free(dtp->dt_cpp_path); 150 dtp->dt_cpp_path = cpp; 151 152 return (0); 153 } 154 155 static int 156 dt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 157 { 158 char *buf; 159 size_t len; 160 const char *opt = (const char *)option; 161 162 if (opt == NULL || arg == NULL) 163 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 164 165 if (dtp->dt_pcb != NULL) 166 return (dt_set_errno(dtp, EDT_BADOPTCTX)); 167 168 len = strlen(opt) + strlen(arg) + 1; 169 buf = alloca(len); 170 171 (void) strcpy(buf, opt); 172 (void) strcat(buf, arg); 173 174 if (dt_cpp_add_arg(dtp, buf) == NULL) 175 return (dt_set_errno(dtp, EDT_NOMEM)); 176 177 return (0); 178 } 179 180 /*ARGSUSED*/ 181 static int 182 dt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 183 { 184 int fd; 185 186 if (arg == NULL) 187 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 188 189 if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1) 190 return (dt_set_errno(dtp, errno)); 191 192 (void) close(dtp->dt_cdefs_fd); 193 dtp->dt_cdefs_fd = fd; 194 return (0); 195 } 196 197 /*ARGSUSED*/ 198 static int 199 dt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 200 { 201 dtp->dt_droptags = 1; 202 return (0); 203 } 204 205 /*ARGSUSED*/ 206 static int 207 dt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 208 { 209 int fd; 210 211 if (arg == NULL) 212 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 213 214 if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1) 215 return (dt_set_errno(dtp, errno)); 216 217 (void) close(dtp->dt_ddefs_fd); 218 dtp->dt_ddefs_fd = fd; 219 return (0); 220 } 221 222 /*ARGSUSED*/ 223 static int 224 dt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 225 { 226 if (arg != NULL) 227 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 228 229 _dtrace_debug = 1; 230 return (0); 231 } 232 233 /*ARGSUSED*/ 234 static int 235 dt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 236 { 237 int n; 238 239 if (arg == NULL || (n = atoi(arg)) <= 0) 240 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 241 242 dtp->dt_conf.dtc_difintregs = n; 243 return (0); 244 } 245 246 /*ARGSUSED*/ 247 static int 248 dt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 249 { 250 dtp->dt_lazyload = 1; 251 252 return (0); 253 } 254 255 /*ARGSUSED*/ 256 static int 257 dt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 258 { 259 char *ld; 260 261 if (arg == NULL) 262 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 263 264 if (dtp->dt_pcb != NULL) 265 return (dt_set_errno(dtp, EDT_BADOPTCTX)); 266 267 if ((ld = strdup(arg)) == NULL) 268 return (dt_set_errno(dtp, EDT_NOMEM)); 269 270 free(dtp->dt_ld_path); 271 dtp->dt_ld_path = ld; 272 273 return (0); 274 } 275 276 /*ARGSUSED*/ 277 static int 278 dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 279 { 280 dt_dirpath_t *dp; 281 282 if (arg == NULL) 283 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 284 285 if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL || 286 (dp->dir_path = strdup(arg)) == NULL) { 287 free(dp); 288 return (dt_set_errno(dtp, EDT_NOMEM)); 289 } 290 291 dt_list_append(&dtp->dt_lib_path, dp); 292 return (0); 293 } 294 295 /*ARGSUSED*/ 296 static int 297 dt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 298 { 299 if (arg == NULL) 300 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 301 302 if (strcmp(arg, "kernel") == 0) 303 dtp->dt_linkmode = DT_LINK_KERNEL; 304 else if (strcmp(arg, "primary") == 0) 305 dtp->dt_linkmode = DT_LINK_PRIMARY; 306 else if (strcmp(arg, "dynamic") == 0) 307 dtp->dt_linkmode = DT_LINK_DYNAMIC; 308 else if (strcmp(arg, "static") == 0) 309 dtp->dt_linkmode = DT_LINK_STATIC; 310 else 311 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 312 313 return (0); 314 } 315 316 /*ARGSUSED*/ 317 static int 318 dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 319 { 320 if (arg == NULL) 321 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 322 323 if (strcasecmp(arg, "elf") == 0) 324 dtp->dt_linktype = DT_LTYP_ELF; 325 else if (strcasecmp(arg, "dof") == 0) 326 dtp->dt_linktype = DT_LTYP_DOF; 327 else 328 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 329 330 return (0); 331 } 332 333 /*ARGSUSED*/ 334 static int 335 dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 336 { 337 if (arg == NULL) 338 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 339 340 if (strcmp(arg, "exec") == 0) 341 dtp->dt_prcmode = DT_PROC_STOP_CREATE; 342 else if (strcmp(arg, "preinit") == 0) 343 dtp->dt_prcmode = DT_PROC_STOP_PREINIT; 344 else if (strcmp(arg, "postinit") == 0) 345 dtp->dt_prcmode = DT_PROC_STOP_POSTINIT; 346 else if (strcmp(arg, "main") == 0) 347 dtp->dt_prcmode = DT_PROC_STOP_MAIN; 348 else 349 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 350 351 return (0); 352 } 353 354 /*ARGSUSED*/ 355 static int 356 dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 357 { 358 int n; 359 360 if (arg == NULL || (n = atoi(arg)) < 0) 361 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 362 363 dtp->dt_procs->dph_lrulim = n; 364 return (0); 365 } 366 367 /*ARGSUSED*/ 368 static int 369 dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 370 { 371 if (arg == NULL) 372 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 373 374 if (dtp->dt_pcb != NULL) 375 return (dt_set_errno(dtp, EDT_BADOPTCTX)); 376 377 if (strcmp(arg, "a") == 0) 378 dtp->dt_stdcmode = DT_STDC_XA; 379 else if (strcmp(arg, "c") == 0) 380 dtp->dt_stdcmode = DT_STDC_XC; 381 else if (strcmp(arg, "s") == 0) 382 dtp->dt_stdcmode = DT_STDC_XS; 383 else if (strcmp(arg, "t") == 0) 384 dtp->dt_stdcmode = DT_STDC_XT; 385 else 386 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 387 388 return (0); 389 } 390 391 /*ARGSUSED*/ 392 static int 393 dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 394 { 395 dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path); 396 char *path; 397 398 if (arg == NULL) 399 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 400 401 if ((path = strdup(arg)) == NULL) 402 return (dt_set_errno(dtp, EDT_NOMEM)); 403 404 free(dp->dir_path); 405 dp->dir_path = path; 406 407 return (0); 408 } 409 410 411 /*ARGSUSED*/ 412 static int 413 dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 414 { 415 int m; 416 417 if (arg == NULL || (m = atoi(arg)) <= 0) 418 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 419 420 dtp->dt_treedump = m; 421 return (0); 422 } 423 424 /*ARGSUSED*/ 425 static int 426 dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 427 { 428 int n; 429 430 if (arg == NULL || (n = atoi(arg)) <= 0) 431 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 432 433 dtp->dt_conf.dtc_diftupregs = n; 434 return (0); 435 } 436 437 /*ARGSUSED*/ 438 static int 439 dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 440 { 441 if (arg == NULL) 442 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 443 444 if (strcmp(arg, "dynamic") == 0) 445 dtp->dt_xlatemode = DT_XL_DYNAMIC; 446 else if (strcmp(arg, "static") == 0) 447 dtp->dt_xlatemode = DT_XL_STATIC; 448 else 449 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 450 451 return (0); 452 } 453 454 /*ARGSUSED*/ 455 static int 456 dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 457 { 458 if (arg != NULL) 459 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 460 461 if (dtp->dt_pcb != NULL) 462 dtp->dt_pcb->pcb_cflags |= option; 463 else 464 dtp->dt_cflags |= option; 465 466 return (0); 467 } 468 469 static int 470 dt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 471 { 472 if (arg != NULL) 473 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 474 475 dtp->dt_dflags |= option; 476 return (0); 477 } 478 479 static int 480 dt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 481 { 482 if (arg != NULL) 483 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 484 485 if (dtp->dt_pcb != NULL) 486 dtp->dt_pcb->pcb_cflags &= ~option; 487 else 488 dtp->dt_cflags &= ~option; 489 490 return (0); 491 } 492 493 /*ARGSUSED*/ 494 static int 495 dt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 496 { 497 dt_version_t v; 498 499 if (arg == NULL) 500 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 501 502 if (dt_version_str2num(arg, &v) == -1) 503 return (dt_set_errno(dtp, EDT_VERSINVAL)); 504 505 if (!dt_version_defined(v)) 506 return (dt_set_errno(dtp, EDT_VERSUNDEF)); 507 508 return (dt_reduce(dtp, v)); 509 } 510 511 static int 512 dt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 513 { 514 char *end; 515 dtrace_optval_t val = 0; 516 int i; 517 518 const struct { 519 char *positive; 520 char *negative; 521 } couples[] = { 522 { "yes", "no" }, 523 { "enable", "disable" }, 524 { "enabled", "disabled" }, 525 { "true", "false" }, 526 { "on", "off" }, 527 { "set", "unset" }, 528 { NULL } 529 }; 530 531 if (arg != NULL) { 532 if (arg[0] == '\0') { 533 val = DTRACEOPT_UNSET; 534 goto out; 535 } 536 537 for (i = 0; couples[i].positive != NULL; i++) { 538 if (strcasecmp(couples[i].positive, arg) == 0) { 539 val = 1; 540 goto out; 541 } 542 543 if (strcasecmp(couples[i].negative, arg) == 0) { 544 val = DTRACEOPT_UNSET; 545 goto out; 546 } 547 } 548 549 errno = 0; 550 val = strtoull(arg, &end, 0); 551 552 if (*end != '\0' || errno != 0 || val < 0) 553 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 554 } 555 556 out: 557 dtp->dt_options[option] = val; 558 return (0); 559 } 560 561 static int 562 dt_optval_parse(const char *arg, dtrace_optval_t *rval) 563 { 564 dtrace_optval_t mul = 1; 565 size_t len; 566 char *end; 567 568 len = strlen(arg); 569 errno = 0; 570 571 switch (arg[len - 1]) { 572 case 't': 573 case 'T': 574 mul *= 1024; 575 /*FALLTHRU*/ 576 case 'g': 577 case 'G': 578 mul *= 1024; 579 /*FALLTHRU*/ 580 case 'm': 581 case 'M': 582 mul *= 1024; 583 /*FALLTHRU*/ 584 case 'k': 585 case 'K': 586 mul *= 1024; 587 /*FALLTHRU*/ 588 default: 589 break; 590 } 591 592 errno = 0; 593 *rval = strtoull(arg, &end, 0) * mul; 594 595 if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') || 596 *rval < 0 || errno != 0) 597 return (-1); 598 599 return (0); 600 } 601 602 static int 603 dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 604 { 605 dtrace_optval_t val = 0; 606 607 if (arg != NULL && dt_optval_parse(arg, &val) != 0) 608 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 609 610 dtp->dt_options[option] = val; 611 return (0); 612 } 613 614 static int 615 dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 616 { 617 char *end; 618 int i; 619 dtrace_optval_t mul = 1, val = 0; 620 621 const struct { 622 char *name; 623 hrtime_t mul; 624 } suffix[] = { 625 { "ns", NANOSEC / NANOSEC }, 626 { "nsec", NANOSEC / NANOSEC }, 627 { "us", NANOSEC / MICROSEC }, 628 { "usec", NANOSEC / MICROSEC }, 629 { "ms", NANOSEC / MILLISEC }, 630 { "msec", NANOSEC / MILLISEC }, 631 { "s", NANOSEC / SEC }, 632 { "sec", NANOSEC / SEC }, 633 { "m", NANOSEC * (hrtime_t)60 }, 634 { "min", NANOSEC * (hrtime_t)60 }, 635 { "h", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 636 { "hour", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 637 { "d", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 638 { "day", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 639 { "hz", 0 }, 640 { NULL } 641 }; 642 643 if (arg != NULL) { 644 errno = 0; 645 val = strtoull(arg, &end, 0); 646 647 for (i = 0; suffix[i].name != NULL; i++) { 648 if (strcasecmp(suffix[i].name, end) == 0) { 649 mul = suffix[i].mul; 650 break; 651 } 652 } 653 654 if (suffix[i].name == NULL && *end != '\0' || val < 0) 655 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 656 657 if (mul == 0) { 658 /* 659 * The rate has been specified in frequency-per-second. 660 */ 661 if (val != 0) 662 val = NANOSEC / val; 663 } else { 664 val *= mul; 665 } 666 } 667 668 dtp->dt_options[option] = val; 669 return (0); 670 } 671 672 /* 673 * When setting the strsize option, set the option in the dt_options array 674 * using dt_opt_size() as usual, and then update the definition of the CTF 675 * type for the D intrinsic "string" to be an array of the corresponding size. 676 * If any errors occur, reset dt_options[option] to its previous value. 677 */ 678 static int 679 dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 680 { 681 dtrace_optval_t val = dtp->dt_options[option]; 682 ctf_file_t *fp = DT_STR_CTFP(dtp); 683 ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp)); 684 ctf_arinfo_t r; 685 686 if (dt_opt_size(dtp, arg, option) != 0) 687 return (-1); /* dt_errno is set for us */ 688 689 if (dtp->dt_options[option] > UINT_MAX) { 690 dtp->dt_options[option] = val; 691 return (dt_set_errno(dtp, EOVERFLOW)); 692 } 693 694 if (ctf_array_info(fp, type, &r) == CTF_ERR) { 695 dtp->dt_options[option] = val; 696 dtp->dt_ctferr = ctf_errno(fp); 697 return (dt_set_errno(dtp, EDT_CTF)); 698 } 699 700 r.ctr_nelems = (uint_t)dtp->dt_options[option]; 701 702 if (ctf_set_array(fp, type, &r) == CTF_ERR || 703 ctf_update(fp) == CTF_ERR) { 704 dtp->dt_options[option] = val; 705 dtp->dt_ctferr = ctf_errno(fp); 706 return (dt_set_errno(dtp, EDT_CTF)); 707 } 708 709 return (0); 710 } 711 712 static const struct { 713 const char *dtbp_name; 714 int dtbp_policy; 715 } _dtrace_bufpolicies[] = { 716 { "ring", DTRACEOPT_BUFPOLICY_RING }, 717 { "fill", DTRACEOPT_BUFPOLICY_FILL }, 718 { "switch", DTRACEOPT_BUFPOLICY_SWITCH }, 719 { NULL, 0 } 720 }; 721 722 /*ARGSUSED*/ 723 static int 724 dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 725 { 726 dtrace_optval_t policy = DTRACEOPT_UNSET; 727 int i; 728 729 if (arg == NULL) 730 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 731 732 for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) { 733 if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) { 734 policy = _dtrace_bufpolicies[i].dtbp_policy; 735 break; 736 } 737 } 738 739 if (policy == DTRACEOPT_UNSET) 740 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 741 742 dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy; 743 744 return (0); 745 } 746 747 static const struct { 748 const char *dtbr_name; 749 int dtbr_policy; 750 } _dtrace_bufresize[] = { 751 { "auto", DTRACEOPT_BUFRESIZE_AUTO }, 752 { "manual", DTRACEOPT_BUFRESIZE_MANUAL }, 753 { NULL, 0 } 754 }; 755 756 /*ARGSUSED*/ 757 static int 758 dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 759 { 760 dtrace_optval_t policy = DTRACEOPT_UNSET; 761 int i; 762 763 if (arg == NULL) 764 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 765 766 for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) { 767 if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) { 768 policy = _dtrace_bufresize[i].dtbr_policy; 769 break; 770 } 771 } 772 773 if (policy == DTRACEOPT_UNSET) 774 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 775 776 dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy; 777 778 return (0); 779 } 780 781 int 782 dt_options_load(dtrace_hdl_t *dtp) 783 { 784 dof_hdr_t hdr, *dof; 785 dof_sec_t *sec; 786 size_t offs; 787 int i; 788 789 /* 790 * To load the option values, we need to ask the kernel to provide its 791 * DOF, which we'll sift through to look for OPTDESC sections. 792 */ 793 bzero(&hdr, sizeof (dof_hdr_t)); 794 hdr.dofh_loadsz = sizeof (dof_hdr_t); 795 796 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1) 797 return (dt_set_errno(dtp, errno)); 798 799 if (hdr.dofh_loadsz < sizeof (dof_hdr_t)) 800 return (dt_set_errno(dtp, EINVAL)); 801 802 dof = alloca(hdr.dofh_loadsz); 803 bzero(dof, sizeof (dof_hdr_t)); 804 dof->dofh_loadsz = hdr.dofh_loadsz; 805 806 for (i = 0; i < DTRACEOPT_MAX; i++) 807 dtp->dt_options[i] = DTRACEOPT_UNSET; 808 809 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1) 810 return (dt_set_errno(dtp, errno)); 811 812 for (i = 0; i < dof->dofh_secnum; i++) { 813 sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof + 814 dof->dofh_secoff + i * dof->dofh_secsize); 815 816 if (sec->dofs_type != DOF_SECT_OPTDESC) 817 continue; 818 819 break; 820 } 821 822 for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) { 823 dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t) 824 ((uintptr_t)dof + sec->dofs_offset + offs); 825 826 if (opt->dofo_strtab != DOF_SECIDX_NONE) 827 continue; 828 829 if (opt->dofo_option >= DTRACEOPT_MAX) 830 continue; 831 832 dtp->dt_options[opt->dofo_option] = opt->dofo_value; 833 } 834 835 return (0); 836 } 837 838 typedef struct dt_option { 839 const char *o_name; 840 int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t); 841 uintptr_t o_option; 842 } dt_option_t; 843 844 /* 845 * Compile-time options. 846 */ 847 static const dt_option_t _dtrace_ctoptions[] = { 848 { "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU }, 849 { "amin", dt_opt_amin }, 850 { "argref", dt_opt_cflags, DTRACE_C_ARGREF }, 851 { "core", dt_opt_core }, 852 { "cpp", dt_opt_cflags, DTRACE_C_CPP }, 853 { "cpphdrs", dt_opt_cpp_hdrs }, 854 { "cpppath", dt_opt_cpp_path }, 855 { "ctypes", dt_opt_ctypes }, 856 { "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG }, 857 { "dtypes", dt_opt_dtypes }, 858 { "debug", dt_opt_debug }, 859 { "define", dt_opt_cpp_opts, (uintptr_t)"-D" }, 860 { "droptags", dt_opt_droptags }, 861 { "empty", dt_opt_cflags, DTRACE_C_EMPTY }, 862 { "errtags", dt_opt_cflags, DTRACE_C_ETAGS }, 863 { "evaltime", dt_opt_evaltime }, 864 { "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" }, 865 { "iregs", dt_opt_iregs }, 866 { "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF }, 867 { "knodefs", dt_opt_cflags, DTRACE_C_KNODEF }, 868 { "late", dt_opt_xlate }, 869 { "lazyload", dt_opt_lazyload }, 870 { "ldpath", dt_opt_ld_path }, 871 { "libdir", dt_opt_libdir }, 872 { "linkmode", dt_opt_linkmode }, 873 { "linktype", dt_opt_linktype }, 874 { "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS }, 875 { "pgmax", dt_opt_pgmax }, 876 { "pspec", dt_opt_cflags, DTRACE_C_PSPEC }, 877 { "stdc", dt_opt_stdc }, 878 { "strip", dt_opt_dflags, DTRACE_D_STRIP }, 879 { "syslibdir", dt_opt_syslibdir }, 880 { "tree", dt_opt_tree }, 881 { "tregs", dt_opt_tregs }, 882 { "udefs", dt_opt_invcflags, DTRACE_C_UNODEF }, 883 { "undef", dt_opt_cpp_opts, (uintptr_t)"-U" }, 884 { "unodefs", dt_opt_cflags, DTRACE_C_UNODEF }, 885 { "verbose", dt_opt_cflags, DTRACE_C_DIFV }, 886 { "version", dt_opt_version }, 887 { "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS }, 888 { NULL } 889 }; 890 891 /* 892 * Run-time options. 893 */ 894 static const dt_option_t _dtrace_rtoptions[] = { 895 { "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE }, 896 { "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE }, 897 { "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY }, 898 { "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE }, 899 { "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE }, 900 { "cpu", dt_opt_runtime, DTRACEOPT_CPU }, 901 { "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE }, 902 { "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE }, 903 { "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON }, 904 { "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES }, 905 { "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE }, 906 { "nspec", dt_opt_runtime, DTRACEOPT_NSPEC }, 907 { "specsize", dt_opt_size, DTRACEOPT_SPECSIZE }, 908 { "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES }, 909 { "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE }, 910 { "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE }, 911 { "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES }, 912 { NULL } 913 }; 914 915 /* 916 * Dynamic run-time options. 917 */ 918 static const dt_option_t _dtrace_drtoptions[] = { 919 { "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE }, 920 { "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY }, 921 { "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS }, 922 { "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS }, 923 { "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV }, 924 { "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT }, 925 { "quiet", dt_opt_runtime, DTRACEOPT_QUIET }, 926 { "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES }, 927 { "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT }, 928 { "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE }, 929 { NULL } 930 }; 931 932 int 933 dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val) 934 { 935 const dt_option_t *op; 936 937 if (opt == NULL) 938 return (dt_set_errno(dtp, EINVAL)); 939 940 /* 941 * We only need to search the run-time options -- it's not legal 942 * to get the values of compile-time options. 943 */ 944 for (op = _dtrace_rtoptions; op->o_name != NULL; op++) { 945 if (strcmp(op->o_name, opt) == 0) { 946 *val = dtp->dt_options[op->o_option]; 947 return (0); 948 } 949 } 950 951 for (op = _dtrace_drtoptions; op->o_name != NULL; op++) { 952 if (strcmp(op->o_name, opt) == 0) { 953 *val = dtp->dt_options[op->o_option]; 954 return (0); 955 } 956 } 957 958 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 959 } 960 961 int 962 dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val) 963 { 964 const dt_option_t *op; 965 966 if (opt == NULL) 967 return (dt_set_errno(dtp, EINVAL)); 968 969 for (op = _dtrace_ctoptions; op->o_name != NULL; op++) { 970 if (strcmp(op->o_name, opt) == 0) 971 return (op->o_func(dtp, val, op->o_option)); 972 } 973 974 for (op = _dtrace_drtoptions; op->o_name != NULL; op++) { 975 if (strcmp(op->o_name, opt) == 0) 976 return (op->o_func(dtp, val, op->o_option)); 977 } 978 979 for (op = _dtrace_rtoptions; op->o_name != NULL; op++) { 980 if (strcmp(op->o_name, opt) == 0) { 981 /* 982 * Only dynamic run-time options may be set while 983 * tracing is active. 984 */ 985 if (dtp->dt_active) 986 return (dt_set_errno(dtp, EDT_ACTIVE)); 987 988 return (op->o_func(dtp, val, op->o_option)); 989 } 990 } 991 992 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 993 } 994