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