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 47static int 48dt_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*/ 60static int 61dt_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 83static void 84dt_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*/ 107static int 108dt_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*/ 122static int 123dt_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*/ 138static int 139dt_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 159static int 160dt_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*/ 185static int 186dt_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*/ 202static int 203dt_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*/ 210static int 211dt_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*/ 227static int 228dt_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*/ 238static int 239dt_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*/ 251static int 252dt_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*/ 260static int 261dt_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*/ 281static int 282dt_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*/ 300static int 301dt_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*/ 321static int 322dt_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*/ 338static int 339dt_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*/ 359static int 360dt_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*/ 372static int 373dt_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*/ 396static int 397dt_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*/ 416static int 417dt_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*/ 429static int 430dt_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*/ 442static int 443dt_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*/ 459static int 460dt_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 473static int 474dt_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 483static int 484dt_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*/ 498static int 499dt_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 515static int 516dt_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 560out: 561 dtp->dt_options[option] = val; 562 return (0); 563} 564 565static int 566dt_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 606static int 607dt_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 618static int 619dt_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 */ 682static int 683dt_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 716static 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*/ 727static int 728dt_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 751static 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*/ 761static int 762dt_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 785int 786dt_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*/ 852static int 853dt_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 875typedef 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 */ 884static 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 */ 932static 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 */ 956static 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 970int 971dtrace_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 999int 1000dtrace_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