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