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_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 201 { 202 int fd; 203 204 if (arg == NULL) 205 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 206 207 if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1) 208 return (dt_set_errno(dtp, errno)); 209 210 (void) close(dtp->dt_ddefs_fd); 211 dtp->dt_ddefs_fd = fd; 212 return (0); 213 } 214 215 /*ARGSUSED*/ 216 static int 217 dt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 218 { 219 if (arg != NULL) 220 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 221 222 _dtrace_debug = 1; 223 return (0); 224 } 225 226 /*ARGSUSED*/ 227 static int 228 dt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 229 { 230 int n; 231 232 if (arg == NULL || (n = atoi(arg)) <= 0) 233 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 234 235 dtp->dt_conf.dtc_difintregs = n; 236 return (0); 237 } 238 239 /*ARGSUSED*/ 240 static int 241 dt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 242 { 243 dtp->dt_lazyload = 1; 244 245 return (0); 246 } 247 248 /*ARGSUSED*/ 249 static int 250 dt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 251 { 252 char *ld; 253 254 if (arg == NULL) 255 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 256 257 if (dtp->dt_pcb != NULL) 258 return (dt_set_errno(dtp, EDT_BADOPTCTX)); 259 260 if ((ld = strdup(arg)) == NULL) 261 return (dt_set_errno(dtp, EDT_NOMEM)); 262 263 free(dtp->dt_ld_path); 264 dtp->dt_ld_path = ld; 265 266 return (0); 267 } 268 269 /*ARGSUSED*/ 270 static int 271 dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 272 { 273 dt_dirpath_t *dp; 274 275 if (arg == NULL) 276 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 277 278 if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL || 279 (dp->dir_path = strdup(arg)) == NULL) { 280 free(dp); 281 return (dt_set_errno(dtp, EDT_NOMEM)); 282 } 283 284 dt_list_append(&dtp->dt_lib_path, dp); 285 return (0); 286 } 287 288 /*ARGSUSED*/ 289 static int 290 dt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 291 { 292 if (arg == NULL) 293 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 294 295 if (strcmp(arg, "kernel") == 0) 296 dtp->dt_linkmode = DT_LINK_KERNEL; 297 else if (strcmp(arg, "primary") == 0) 298 dtp->dt_linkmode = DT_LINK_PRIMARY; 299 else if (strcmp(arg, "dynamic") == 0) 300 dtp->dt_linkmode = DT_LINK_DYNAMIC; 301 else if (strcmp(arg, "static") == 0) 302 dtp->dt_linkmode = DT_LINK_STATIC; 303 else 304 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 305 306 return (0); 307 } 308 309 /*ARGSUSED*/ 310 static int 311 dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 312 { 313 if (arg == NULL) 314 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 315 316 if (strcasecmp(arg, "elf") == 0) 317 dtp->dt_linktype = DT_LTYP_ELF; 318 else if (strcasecmp(arg, "dof") == 0) 319 dtp->dt_linktype = DT_LTYP_DOF; 320 else 321 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 322 323 return (0); 324 } 325 326 /*ARGSUSED*/ 327 static int 328 dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 329 { 330 if (arg == NULL) 331 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 332 333 if (strcmp(arg, "exec") == 0) 334 dtp->dt_prcmode = DT_PROC_STOP_CREATE; 335 else if (strcmp(arg, "preinit") == 0) 336 dtp->dt_prcmode = DT_PROC_STOP_PREINIT; 337 else if (strcmp(arg, "postinit") == 0) 338 dtp->dt_prcmode = DT_PROC_STOP_POSTINIT; 339 else if (strcmp(arg, "main") == 0) 340 dtp->dt_prcmode = DT_PROC_STOP_MAIN; 341 else 342 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 343 344 return (0); 345 } 346 347 /*ARGSUSED*/ 348 static int 349 dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 350 { 351 int n; 352 353 if (arg == NULL || (n = atoi(arg)) < 0) 354 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 355 356 dtp->dt_procs->dph_lrulim = n; 357 return (0); 358 } 359 360 /*ARGSUSED*/ 361 static int 362 dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 363 { 364 if (arg == NULL) 365 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 366 367 if (dtp->dt_pcb != NULL) 368 return (dt_set_errno(dtp, EDT_BADOPTCTX)); 369 370 if (strcmp(arg, "a") == 0) 371 dtp->dt_stdcmode = DT_STDC_XA; 372 else if (strcmp(arg, "c") == 0) 373 dtp->dt_stdcmode = DT_STDC_XC; 374 else if (strcmp(arg, "s") == 0) 375 dtp->dt_stdcmode = DT_STDC_XS; 376 else if (strcmp(arg, "t") == 0) 377 dtp->dt_stdcmode = DT_STDC_XT; 378 else 379 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 380 381 return (0); 382 } 383 384 /*ARGSUSED*/ 385 static int 386 dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 387 { 388 dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path); 389 char *path; 390 391 if (arg == NULL) 392 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 393 394 if ((path = strdup(arg)) == NULL) 395 return (dt_set_errno(dtp, EDT_NOMEM)); 396 397 free(dp->dir_path); 398 dp->dir_path = path; 399 400 return (0); 401 } 402 403 404 /*ARGSUSED*/ 405 static int 406 dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 407 { 408 int m; 409 410 if (arg == NULL || (m = atoi(arg)) <= 0) 411 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 412 413 dtp->dt_treedump = m; 414 return (0); 415 } 416 417 /*ARGSUSED*/ 418 static int 419 dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 420 { 421 int n; 422 423 if (arg == NULL || (n = atoi(arg)) <= 0) 424 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 425 426 dtp->dt_conf.dtc_diftupregs = n; 427 return (0); 428 } 429 430 static int 431 dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 432 { 433 if (arg != NULL) 434 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 435 436 if (dtp->dt_pcb != NULL) 437 dtp->dt_pcb->pcb_cflags |= option; 438 else 439 dtp->dt_cflags |= option; 440 441 return (0); 442 } 443 444 static int 445 dt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 446 { 447 if (arg != NULL) 448 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 449 450 dtp->dt_dflags |= option; 451 return (0); 452 } 453 454 static int 455 dt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 456 { 457 if (arg != NULL) 458 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 459 460 if (dtp->dt_pcb != NULL) 461 dtp->dt_pcb->pcb_cflags &= ~option; 462 else 463 dtp->dt_cflags &= ~option; 464 465 return (0); 466 } 467 468 /*ARGSUSED*/ 469 static int 470 dt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 471 { 472 dt_version_t v; 473 474 if (arg == NULL) 475 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 476 477 if (dt_version_str2num(arg, &v) == -1) 478 return (dt_set_errno(dtp, EDT_VERSINVAL)); 479 480 if (!dt_version_defined(v)) 481 return (dt_set_errno(dtp, EDT_VERSUNDEF)); 482 483 return (dt_reduce(dtp, v)); 484 } 485 486 static int 487 dt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 488 { 489 char *end; 490 dtrace_optval_t val = 0; 491 492 if (arg != NULL) { 493 errno = 0; 494 val = strtoull(arg, &end, 0); 495 496 if (*end != '\0' || errno != 0 || val < 0) 497 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 498 } 499 500 dtp->dt_options[option] = val; 501 return (0); 502 } 503 504 static int 505 dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 506 { 507 char *end; 508 int len; 509 dtrace_optval_t mul = 1, val = 0; 510 511 if (arg != NULL) { 512 len = strlen(arg); 513 errno = 0; 514 515 switch (arg[len - 1]) { 516 case 't': 517 case 'T': 518 mul *= 1024; 519 /*FALLTHRU*/ 520 case 'g': 521 case 'G': 522 mul *= 1024; 523 /*FALLTHRU*/ 524 case 'm': 525 case 'M': 526 mul *= 1024; 527 /*FALLTHRU*/ 528 case 'k': 529 case 'K': 530 mul *= 1024; 531 /*FALLTHRU*/ 532 default: 533 break; 534 } 535 536 val = strtoull(arg, &end, 0) * mul; 537 538 if ((mul > 1 && end != &arg[len - 1]) || 539 (mul == 1 && *end != '\0') || val < 0 || 540 errno != 0 || val == DTRACEOPT_UNSET) 541 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 542 } 543 544 dtp->dt_options[option] = val; 545 return (0); 546 } 547 548 static int 549 dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 550 { 551 char *end; 552 int i; 553 dtrace_optval_t mul = 1, val = 0; 554 555 const struct { 556 char *name; 557 hrtime_t mul; 558 } suffix[] = { 559 { "ns", NANOSEC / NANOSEC }, 560 { "nsec", NANOSEC / NANOSEC }, 561 { "us", NANOSEC / MICROSEC }, 562 { "usec", NANOSEC / MICROSEC }, 563 { "ms", NANOSEC / MILLISEC }, 564 { "msec", NANOSEC / MILLISEC }, 565 { "s", NANOSEC / SEC }, 566 { "sec", NANOSEC / SEC }, 567 { "m", NANOSEC * (hrtime_t)60 }, 568 { "min", NANOSEC * (hrtime_t)60 }, 569 { "h", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 570 { "hour", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 571 { "d", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 572 { "day", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 573 { "hz", 0 }, 574 { NULL } 575 }; 576 577 if (arg != NULL) { 578 errno = 0; 579 val = strtoull(arg, &end, 0); 580 581 for (i = 0; suffix[i].name != NULL; i++) { 582 if (strcasecmp(suffix[i].name, end) == 0) { 583 mul = suffix[i].mul; 584 break; 585 } 586 } 587 588 if (suffix[i].name == NULL && *end != '\0' || val < 0) 589 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 590 591 if (mul == 0) { 592 /* 593 * The rate has been specified in frequency-per-second. 594 */ 595 if (val != 0) 596 val = NANOSEC / val; 597 } else { 598 val *= mul; 599 } 600 } 601 602 dtp->dt_options[option] = val; 603 return (0); 604 } 605 606 /* 607 * When setting the strsize option, set the option in the dt_options array 608 * using dt_opt_size() as usual, and then update the definition of the CTF 609 * type for the D intrinsic "string" to be an array of the corresponding size. 610 * If any errors occur, reset dt_options[option] to its previous value. 611 */ 612 static int 613 dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 614 { 615 dtrace_optval_t val = dtp->dt_options[option]; 616 ctf_file_t *fp = DT_STR_CTFP(dtp); 617 ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp)); 618 ctf_arinfo_t r; 619 620 if (dt_opt_size(dtp, arg, option) != 0) 621 return (-1); /* dt_errno is set for us */ 622 623 if (dtp->dt_options[option] > UINT_MAX) { 624 dtp->dt_options[option] = val; 625 return (dt_set_errno(dtp, EOVERFLOW)); 626 } 627 628 if (ctf_array_info(fp, type, &r) == CTF_ERR) { 629 dtp->dt_options[option] = val; 630 dtp->dt_ctferr = ctf_errno(fp); 631 return (dt_set_errno(dtp, EDT_CTF)); 632 } 633 634 r.ctr_nelems = (uint_t)dtp->dt_options[option]; 635 636 if (ctf_set_array(fp, type, &r) == CTF_ERR || 637 ctf_update(fp) == CTF_ERR) { 638 dtp->dt_options[option] = val; 639 dtp->dt_ctferr = ctf_errno(fp); 640 return (dt_set_errno(dtp, EDT_CTF)); 641 } 642 643 return (0); 644 } 645 646 static const struct { 647 const char *dtbp_name; 648 int dtbp_policy; 649 } _dtrace_bufpolicies[] = { 650 { "ring", DTRACEOPT_BUFPOLICY_RING }, 651 { "fill", DTRACEOPT_BUFPOLICY_FILL }, 652 { "switch", DTRACEOPT_BUFPOLICY_SWITCH }, 653 { NULL, 0 } 654 }; 655 656 /*ARGSUSED*/ 657 static int 658 dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 659 { 660 dtrace_optval_t policy = DTRACEOPT_UNSET; 661 int i; 662 663 if (arg == NULL) 664 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 665 666 for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) { 667 if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) { 668 policy = _dtrace_bufpolicies[i].dtbp_policy; 669 break; 670 } 671 } 672 673 if (policy == DTRACEOPT_UNSET) 674 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 675 676 dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy; 677 678 return (0); 679 } 680 681 static const struct { 682 const char *dtbr_name; 683 int dtbr_policy; 684 } _dtrace_bufresize[] = { 685 { "auto", DTRACEOPT_BUFRESIZE_AUTO }, 686 { "manual", DTRACEOPT_BUFRESIZE_MANUAL }, 687 { NULL, 0 } 688 }; 689 690 /*ARGSUSED*/ 691 static int 692 dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 693 { 694 dtrace_optval_t policy = DTRACEOPT_UNSET; 695 int i; 696 697 if (arg == NULL) 698 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 699 700 for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) { 701 if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) { 702 policy = _dtrace_bufresize[i].dtbr_policy; 703 break; 704 } 705 } 706 707 if (policy == DTRACEOPT_UNSET) 708 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 709 710 dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy; 711 712 return (0); 713 } 714 715 int 716 dt_options_load(dtrace_hdl_t *dtp) 717 { 718 dof_hdr_t hdr, *dof; 719 dof_sec_t *sec; 720 size_t offs; 721 int i; 722 723 /* 724 * To load the option values, we need to ask the kernel to provide its 725 * DOF, which we'll sift through to look for OPTDESC sections. 726 */ 727 bzero(&hdr, sizeof (dof_hdr_t)); 728 hdr.dofh_loadsz = sizeof (dof_hdr_t); 729 730 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1) 731 return (dt_set_errno(dtp, errno)); 732 733 if (hdr.dofh_loadsz < sizeof (dof_hdr_t)) 734 return (dt_set_errno(dtp, EINVAL)); 735 736 dof = alloca(hdr.dofh_loadsz); 737 bzero(dof, sizeof (dof_hdr_t)); 738 dof->dofh_loadsz = hdr.dofh_loadsz; 739 740 for (i = 0; i < DTRACEOPT_MAX; i++) 741 dtp->dt_options[i] = DTRACEOPT_UNSET; 742 743 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1) 744 return (dt_set_errno(dtp, errno)); 745 746 for (i = 0; i < dof->dofh_secnum; i++) { 747 sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof + 748 dof->dofh_secoff + i * dof->dofh_secsize); 749 750 if (sec->dofs_type != DOF_SECT_OPTDESC) 751 continue; 752 753 break; 754 } 755 756 for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) { 757 dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t) 758 ((uintptr_t)dof + sec->dofs_offset + offs); 759 760 if (opt->dofo_strtab != DOF_SECIDX_NONE) 761 continue; 762 763 if (opt->dofo_option >= DTRACEOPT_MAX) 764 continue; 765 766 dtp->dt_options[opt->dofo_option] = opt->dofo_value; 767 } 768 769 return (0); 770 } 771 772 typedef struct dt_option { 773 const char *o_name; 774 int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t); 775 uintptr_t o_option; 776 } dt_option_t; 777 778 /* 779 * Compile-time options. 780 */ 781 static const dt_option_t _dtrace_ctoptions[] = { 782 { "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU }, 783 { "amin", dt_opt_amin }, 784 { "argref", dt_opt_cflags, DTRACE_C_ARGREF }, 785 { "core", dt_opt_core }, 786 { "cpp", dt_opt_cflags, DTRACE_C_CPP }, 787 { "cpphdrs", dt_opt_cpp_hdrs }, 788 { "cpppath", dt_opt_cpp_path }, 789 { "ctypes", dt_opt_ctypes }, 790 { "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG }, 791 { "dtypes", dt_opt_dtypes }, 792 { "debug", dt_opt_debug }, 793 { "define", dt_opt_cpp_opts, (uintptr_t)"-D" }, 794 { "empty", dt_opt_cflags, DTRACE_C_EMPTY }, 795 { "errtags", dt_opt_cflags, DTRACE_C_ETAGS }, 796 { "evaltime", dt_opt_evaltime }, 797 { "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" }, 798 { "iregs", dt_opt_iregs }, 799 { "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF }, 800 { "knodefs", dt_opt_cflags, DTRACE_C_KNODEF }, 801 { "lazyload", dt_opt_lazyload }, 802 { "ldpath", dt_opt_ld_path }, 803 { "libdir", dt_opt_libdir }, 804 { "linkmode", dt_opt_linkmode }, 805 { "linktype", dt_opt_linktype }, 806 { "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS }, 807 { "pgmax", dt_opt_pgmax }, 808 { "pspec", dt_opt_cflags, DTRACE_C_PSPEC }, 809 { "stdc", dt_opt_stdc }, 810 { "strip", dt_opt_dflags, DTRACE_D_STRIP }, 811 { "syslibdir", dt_opt_syslibdir }, 812 { "tree", dt_opt_tree }, 813 { "tregs", dt_opt_tregs }, 814 { "udefs", dt_opt_invcflags, DTRACE_C_UNODEF }, 815 { "undef", dt_opt_cpp_opts, (uintptr_t)"-U" }, 816 { "unodefs", dt_opt_cflags, DTRACE_C_UNODEF }, 817 { "verbose", dt_opt_cflags, DTRACE_C_DIFV }, 818 { "version", dt_opt_version }, 819 { "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS }, 820 { NULL } 821 }; 822 823 /* 824 * Run-time options. 825 */ 826 static const dt_option_t _dtrace_rtoptions[] = { 827 { "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE }, 828 { "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE }, 829 { "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE }, 830 { "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY }, 831 { "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE }, 832 { "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE }, 833 { "cpu", dt_opt_runtime, DTRACEOPT_CPU }, 834 { "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE }, 835 { "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE }, 836 { "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT }, 837 { "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON }, 838 { "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES }, 839 { "jstackstrsize", dt_opt_runtime, DTRACEOPT_JSTACKSTRSIZE }, 840 { "nspec", dt_opt_runtime, DTRACEOPT_NSPEC }, 841 { "quiet", dt_opt_runtime, DTRACEOPT_QUIET }, 842 { "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES }, 843 { "specsize", dt_opt_size, DTRACEOPT_SPECSIZE }, 844 { "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES }, 845 { "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT }, 846 { "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE }, 847 { "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE }, 848 { "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE }, 849 { "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES }, 850 { NULL } 851 }; 852 853 int 854 dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val) 855 { 856 const dt_option_t *op; 857 858 if (opt == NULL) 859 return (dt_set_errno(dtp, EINVAL)); 860 861 /* 862 * We only need to search the run-time options -- it's not legal 863 * to get the values of compile-time options. 864 */ 865 for (op = _dtrace_rtoptions; op->o_name != NULL; op++) { 866 if (strcmp(op->o_name, opt) == 0) { 867 *val = dtp->dt_options[op->o_option]; 868 return (0); 869 } 870 } 871 872 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 873 } 874 875 int 876 dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val) 877 { 878 const dt_option_t *op; 879 880 if (opt == NULL) 881 return (dt_set_errno(dtp, EINVAL)); 882 883 for (op = _dtrace_ctoptions; op->o_name != NULL; op++) { 884 if (strcmp(op->o_name, opt) == 0) 885 return (op->o_func(dtp, val, op->o_option)); 886 } 887 888 for (op = _dtrace_rtoptions; op->o_name != NULL; op++) { 889 if (strcmp(op->o_name, opt) == 0) { 890 /* 891 * Currently, no run-time option may be set while 892 * tracing is active. 893 */ 894 if (dtp->dt_active) 895 return (dt_set_errno(dtp, EDT_ACTIVE)); 896 897 return (op->o_func(dtp, val, op->o_option)); 898 } 899 } 900 901 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 902 } 903