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 /*ARGSUSED*/ 431 static int 432 dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 433 { 434 if (arg == NULL) 435 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 436 437 if (strcmp(arg, "dynamic") == 0) 438 dtp->dt_xlatemode = DT_XL_DYNAMIC; 439 else if (strcmp(arg, "static") == 0) 440 dtp->dt_xlatemode = DT_XL_STATIC; 441 else 442 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 443 444 return (0); 445 } 446 447 /*ARGSUSED*/ 448 449 static int 450 dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 451 { 452 if (arg != NULL) 453 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 454 455 if (dtp->dt_pcb != NULL) 456 dtp->dt_pcb->pcb_cflags |= option; 457 else 458 dtp->dt_cflags |= option; 459 460 return (0); 461 } 462 463 static int 464 dt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 465 { 466 if (arg != NULL) 467 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 468 469 dtp->dt_dflags |= option; 470 return (0); 471 } 472 473 static int 474 dt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 475 { 476 if (arg != NULL) 477 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 478 479 if (dtp->dt_pcb != NULL) 480 dtp->dt_pcb->pcb_cflags &= ~option; 481 else 482 dtp->dt_cflags &= ~option; 483 484 return (0); 485 } 486 487 /*ARGSUSED*/ 488 static int 489 dt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 490 { 491 dt_version_t v; 492 493 if (arg == NULL) 494 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 495 496 if (dt_version_str2num(arg, &v) == -1) 497 return (dt_set_errno(dtp, EDT_VERSINVAL)); 498 499 if (!dt_version_defined(v)) 500 return (dt_set_errno(dtp, EDT_VERSUNDEF)); 501 502 return (dt_reduce(dtp, v)); 503 } 504 505 static int 506 dt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 507 { 508 char *end; 509 dtrace_optval_t val = 0; 510 511 if (arg != NULL) { 512 errno = 0; 513 val = strtoull(arg, &end, 0); 514 515 if (*end != '\0' || errno != 0 || val < 0) 516 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 517 } 518 519 dtp->dt_options[option] = val; 520 return (0); 521 } 522 523 static int 524 dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 525 { 526 char *end; 527 int len; 528 dtrace_optval_t mul = 1, val = 0; 529 530 if (arg != NULL) { 531 len = strlen(arg); 532 errno = 0; 533 534 switch (arg[len - 1]) { 535 case 't': 536 case 'T': 537 mul *= 1024; 538 /*FALLTHRU*/ 539 case 'g': 540 case 'G': 541 mul *= 1024; 542 /*FALLTHRU*/ 543 case 'm': 544 case 'M': 545 mul *= 1024; 546 /*FALLTHRU*/ 547 case 'k': 548 case 'K': 549 mul *= 1024; 550 /*FALLTHRU*/ 551 default: 552 break; 553 } 554 555 val = strtoull(arg, &end, 0) * mul; 556 557 if ((mul > 1 && end != &arg[len - 1]) || 558 (mul == 1 && *end != '\0') || val < 0 || 559 errno != 0 || val == DTRACEOPT_UNSET) 560 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 561 } 562 563 dtp->dt_options[option] = val; 564 return (0); 565 } 566 567 static int 568 dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 569 { 570 char *end; 571 int i; 572 dtrace_optval_t mul = 1, val = 0; 573 574 const struct { 575 char *name; 576 hrtime_t mul; 577 } suffix[] = { 578 { "ns", NANOSEC / NANOSEC }, 579 { "nsec", NANOSEC / NANOSEC }, 580 { "us", NANOSEC / MICROSEC }, 581 { "usec", NANOSEC / MICROSEC }, 582 { "ms", NANOSEC / MILLISEC }, 583 { "msec", NANOSEC / MILLISEC }, 584 { "s", NANOSEC / SEC }, 585 { "sec", NANOSEC / SEC }, 586 { "m", NANOSEC * (hrtime_t)60 }, 587 { "min", NANOSEC * (hrtime_t)60 }, 588 { "h", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 589 { "hour", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 590 { "d", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 591 { "day", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 592 { "hz", 0 }, 593 { NULL } 594 }; 595 596 if (arg != NULL) { 597 errno = 0; 598 val = strtoull(arg, &end, 0); 599 600 for (i = 0; suffix[i].name != NULL; i++) { 601 if (strcasecmp(suffix[i].name, end) == 0) { 602 mul = suffix[i].mul; 603 break; 604 } 605 } 606 607 if (suffix[i].name == NULL && *end != '\0' || val < 0) 608 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 609 610 if (mul == 0) { 611 /* 612 * The rate has been specified in frequency-per-second. 613 */ 614 if (val != 0) 615 val = NANOSEC / val; 616 } else { 617 val *= mul; 618 } 619 } 620 621 dtp->dt_options[option] = val; 622 return (0); 623 } 624 625 /* 626 * When setting the strsize option, set the option in the dt_options array 627 * using dt_opt_size() as usual, and then update the definition of the CTF 628 * type for the D intrinsic "string" to be an array of the corresponding size. 629 * If any errors occur, reset dt_options[option] to its previous value. 630 */ 631 static int 632 dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 633 { 634 dtrace_optval_t val = dtp->dt_options[option]; 635 ctf_file_t *fp = DT_STR_CTFP(dtp); 636 ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp)); 637 ctf_arinfo_t r; 638 639 if (dt_opt_size(dtp, arg, option) != 0) 640 return (-1); /* dt_errno is set for us */ 641 642 if (dtp->dt_options[option] > UINT_MAX) { 643 dtp->dt_options[option] = val; 644 return (dt_set_errno(dtp, EOVERFLOW)); 645 } 646 647 if (ctf_array_info(fp, type, &r) == CTF_ERR) { 648 dtp->dt_options[option] = val; 649 dtp->dt_ctferr = ctf_errno(fp); 650 return (dt_set_errno(dtp, EDT_CTF)); 651 } 652 653 r.ctr_nelems = (uint_t)dtp->dt_options[option]; 654 655 if (ctf_set_array(fp, type, &r) == CTF_ERR || 656 ctf_update(fp) == CTF_ERR) { 657 dtp->dt_options[option] = val; 658 dtp->dt_ctferr = ctf_errno(fp); 659 return (dt_set_errno(dtp, EDT_CTF)); 660 } 661 662 return (0); 663 } 664 665 static const struct { 666 const char *dtbp_name; 667 int dtbp_policy; 668 } _dtrace_bufpolicies[] = { 669 { "ring", DTRACEOPT_BUFPOLICY_RING }, 670 { "fill", DTRACEOPT_BUFPOLICY_FILL }, 671 { "switch", DTRACEOPT_BUFPOLICY_SWITCH }, 672 { NULL, 0 } 673 }; 674 675 /*ARGSUSED*/ 676 static int 677 dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 678 { 679 dtrace_optval_t policy = DTRACEOPT_UNSET; 680 int i; 681 682 if (arg == NULL) 683 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 684 685 for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) { 686 if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) { 687 policy = _dtrace_bufpolicies[i].dtbp_policy; 688 break; 689 } 690 } 691 692 if (policy == DTRACEOPT_UNSET) 693 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 694 695 dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy; 696 697 return (0); 698 } 699 700 static const struct { 701 const char *dtbr_name; 702 int dtbr_policy; 703 } _dtrace_bufresize[] = { 704 { "auto", DTRACEOPT_BUFRESIZE_AUTO }, 705 { "manual", DTRACEOPT_BUFRESIZE_MANUAL }, 706 { NULL, 0 } 707 }; 708 709 /*ARGSUSED*/ 710 static int 711 dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 712 { 713 dtrace_optval_t policy = DTRACEOPT_UNSET; 714 int i; 715 716 if (arg == NULL) 717 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 718 719 for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) { 720 if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) { 721 policy = _dtrace_bufresize[i].dtbr_policy; 722 break; 723 } 724 } 725 726 if (policy == DTRACEOPT_UNSET) 727 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 728 729 dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy; 730 731 return (0); 732 } 733 734 int 735 dt_options_load(dtrace_hdl_t *dtp) 736 { 737 dof_hdr_t hdr, *dof; 738 dof_sec_t *sec; 739 size_t offs; 740 int i; 741 742 /* 743 * To load the option values, we need to ask the kernel to provide its 744 * DOF, which we'll sift through to look for OPTDESC sections. 745 */ 746 bzero(&hdr, sizeof (dof_hdr_t)); 747 hdr.dofh_loadsz = sizeof (dof_hdr_t); 748 749 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1) 750 return (dt_set_errno(dtp, errno)); 751 752 if (hdr.dofh_loadsz < sizeof (dof_hdr_t)) 753 return (dt_set_errno(dtp, EINVAL)); 754 755 dof = alloca(hdr.dofh_loadsz); 756 bzero(dof, sizeof (dof_hdr_t)); 757 dof->dofh_loadsz = hdr.dofh_loadsz; 758 759 for (i = 0; i < DTRACEOPT_MAX; i++) 760 dtp->dt_options[i] = DTRACEOPT_UNSET; 761 762 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1) 763 return (dt_set_errno(dtp, errno)); 764 765 for (i = 0; i < dof->dofh_secnum; i++) { 766 sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof + 767 dof->dofh_secoff + i * dof->dofh_secsize); 768 769 if (sec->dofs_type != DOF_SECT_OPTDESC) 770 continue; 771 772 break; 773 } 774 775 for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) { 776 dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t) 777 ((uintptr_t)dof + sec->dofs_offset + offs); 778 779 if (opt->dofo_strtab != DOF_SECIDX_NONE) 780 continue; 781 782 if (opt->dofo_option >= DTRACEOPT_MAX) 783 continue; 784 785 dtp->dt_options[opt->dofo_option] = opt->dofo_value; 786 } 787 788 return (0); 789 } 790 791 typedef struct dt_option { 792 const char *o_name; 793 int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t); 794 uintptr_t o_option; 795 } dt_option_t; 796 797 /* 798 * Compile-time options. 799 */ 800 static const dt_option_t _dtrace_ctoptions[] = { 801 { "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU }, 802 { "amin", dt_opt_amin }, 803 { "argref", dt_opt_cflags, DTRACE_C_ARGREF }, 804 { "core", dt_opt_core }, 805 { "cpp", dt_opt_cflags, DTRACE_C_CPP }, 806 { "cpphdrs", dt_opt_cpp_hdrs }, 807 { "cpppath", dt_opt_cpp_path }, 808 { "ctypes", dt_opt_ctypes }, 809 { "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG }, 810 { "dtypes", dt_opt_dtypes }, 811 { "debug", dt_opt_debug }, 812 { "define", dt_opt_cpp_opts, (uintptr_t)"-D" }, 813 { "empty", dt_opt_cflags, DTRACE_C_EMPTY }, 814 { "errtags", dt_opt_cflags, DTRACE_C_ETAGS }, 815 { "evaltime", dt_opt_evaltime }, 816 { "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" }, 817 { "iregs", dt_opt_iregs }, 818 { "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF }, 819 { "knodefs", dt_opt_cflags, DTRACE_C_KNODEF }, 820 { "late", dt_opt_xlate }, 821 { "lazyload", dt_opt_lazyload }, 822 { "ldpath", dt_opt_ld_path }, 823 { "libdir", dt_opt_libdir }, 824 { "linkmode", dt_opt_linkmode }, 825 { "linktype", dt_opt_linktype }, 826 { "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS }, 827 { "pgmax", dt_opt_pgmax }, 828 { "pspec", dt_opt_cflags, DTRACE_C_PSPEC }, 829 { "stdc", dt_opt_stdc }, 830 { "strip", dt_opt_dflags, DTRACE_D_STRIP }, 831 { "syslibdir", dt_opt_syslibdir }, 832 { "tree", dt_opt_tree }, 833 { "tregs", dt_opt_tregs }, 834 { "udefs", dt_opt_invcflags, DTRACE_C_UNODEF }, 835 { "undef", dt_opt_cpp_opts, (uintptr_t)"-U" }, 836 { "unodefs", dt_opt_cflags, DTRACE_C_UNODEF }, 837 { "verbose", dt_opt_cflags, DTRACE_C_DIFV }, 838 { "version", dt_opt_version }, 839 { "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS }, 840 { NULL } 841 }; 842 843 /* 844 * Run-time options. 845 */ 846 static const dt_option_t _dtrace_rtoptions[] = { 847 { "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE }, 848 { "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE }, 849 { "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE }, 850 { "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY }, 851 { "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE }, 852 { "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE }, 853 { "cpu", dt_opt_runtime, DTRACEOPT_CPU }, 854 { "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE }, 855 { "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE }, 856 { "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT }, 857 { "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON }, 858 { "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES }, 859 { "jstackstrsize", dt_opt_runtime, DTRACEOPT_JSTACKSTRSIZE }, 860 { "nspec", dt_opt_runtime, DTRACEOPT_NSPEC }, 861 { "quiet", dt_opt_runtime, DTRACEOPT_QUIET }, 862 { "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES }, 863 { "specsize", dt_opt_size, DTRACEOPT_SPECSIZE }, 864 { "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES }, 865 { "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT }, 866 { "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE }, 867 { "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE }, 868 { "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE }, 869 { "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES }, 870 { NULL } 871 }; 872 873 int 874 dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val) 875 { 876 const dt_option_t *op; 877 878 if (opt == NULL) 879 return (dt_set_errno(dtp, EINVAL)); 880 881 /* 882 * We only need to search the run-time options -- it's not legal 883 * to get the values of compile-time options. 884 */ 885 for (op = _dtrace_rtoptions; op->o_name != NULL; op++) { 886 if (strcmp(op->o_name, opt) == 0) { 887 *val = dtp->dt_options[op->o_option]; 888 return (0); 889 } 890 } 891 892 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 893 } 894 895 int 896 dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val) 897 { 898 const dt_option_t *op; 899 900 if (opt == NULL) 901 return (dt_set_errno(dtp, EINVAL)); 902 903 for (op = _dtrace_ctoptions; op->o_name != NULL; op++) { 904 if (strcmp(op->o_name, opt) == 0) 905 return (op->o_func(dtp, val, op->o_option)); 906 } 907 908 for (op = _dtrace_rtoptions; op->o_name != NULL; op++) { 909 if (strcmp(op->o_name, opt) == 0) { 910 /* 911 * Currently, no run-time option may be set while 912 * tracing is active. 913 */ 914 if (dtp->dt_active) 915 return (dt_set_errno(dtp, EDT_ACTIVE)); 916 917 return (op->o_func(dtp, val, op->o_option)); 918 } 919 } 920 921 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 922 } 923