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