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