dt_options.c revision 178529
1234353Sdim/* 2193323Sed * CDDL HEADER START 3193323Sed * 4193323Sed * The contents of this file are subject to the terms of the 5193323Sed * Common Development and Distribution License (the "License"). 6193323Sed * You may not use this file except in compliance with the License. 7193323Sed * 8193323Sed * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9193323Sed * or http://www.opensolaris.org/os/licensing. 10193323Sed * See the License for the specific language governing permissions 11193323Sed * and limitations under the License. 12193323Sed * 13193323Sed * When distributing Covered Code, include this CDDL HEADER in each 14193323Sed * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15193323Sed * If applicable, add the following below this CDDL HEADER, with the 16193323Sed * fields enclosed by brackets "[]" replaced with your own identifying 17195340Sed * information: Portions Copyright [yyyy] [name of copyright owner] 18234353Sdim * 19193323Sed * CDDL HEADER END 20193323Sed */ 21193323Sed 22193323Sed/* 23263508Sdim * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24263508Sdim * Use is subject to license terms. 25195340Sed */ 26234353Sdim 27195340Sed#pragma ident "%Z%%M% %I% %E% SMI" 28263508Sdim 29193323Sed#include <sys/resource.h> 30193323Sed#include <sys/mman.h> 31193323Sed#include <sys/types.h> 32193323Sed 33193323Sed#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 45static int 46dt_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*/ 58static int 59dt_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 81static void 82dt_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*/ 105static int 106dt_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*/ 120static int 121dt_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*/ 136static int 137dt_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 157static int 158dt_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*/ 183static int 184dt_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*/ 200static int 201dt_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*/ 208static int 209dt_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*/ 225static int 226dt_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*/ 236static int 237dt_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*/ 249static int 250dt_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*/ 258static int 259dt_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*/ 279static int 280dt_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*/ 298static int 299dt_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*/ 319static int 320dt_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*/ 336static int 337dt_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*/ 357static int 358dt_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*/ 370static int 371dt_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*/ 394static int 395dt_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*/ 414static int 415dt_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*/ 427static int 428dt_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*/ 440static int 441dt_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*/ 457static int 458dt_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 471static int 472dt_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 481static int 482dt_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*/ 496static int 497dt_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 513static int 514dt_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 558out: 559 dtp->dt_options[option] = val; 560 return (0); 561} 562 563static int 564dt_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 604static int 605dt_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 616static int 617dt_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 */ 680static int 681dt_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 714static 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*/ 725static int 726dt_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 749static 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*/ 759static int 760dt_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 783int 784dt_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*/ 841static int 842dt_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 864typedef 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 */ 873static 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 */ 921static 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 */ 945static 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 959int 960dtrace_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 988int 989dtrace_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