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