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