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