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 <alloca.h> 42 #include <errno.h> 43 #include <fcntl.h> 44 #include <zone.h> 45 #include <libzonecfg.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 /*ARGSUSED*/ 284 static int 285 dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 286 { 287 dt_dirpath_t *dp; 288 289 if (arg == NULL) 290 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 291 292 if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL || 293 (dp->dir_path = strdup(arg)) == NULL) { 294 free(dp); 295 return (dt_set_errno(dtp, EDT_NOMEM)); 296 } 297 298 dt_list_append(&dtp->dt_lib_path, dp); 299 return (0); 300 } 301 302 /*ARGSUSED*/ 303 static int 304 dt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 305 { 306 if (arg == NULL) 307 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 308 309 if (strcmp(arg, "kernel") == 0) 310 dtp->dt_linkmode = DT_LINK_KERNEL; 311 else if (strcmp(arg, "primary") == 0) 312 dtp->dt_linkmode = DT_LINK_PRIMARY; 313 else if (strcmp(arg, "dynamic") == 0) 314 dtp->dt_linkmode = DT_LINK_DYNAMIC; 315 else if (strcmp(arg, "static") == 0) 316 dtp->dt_linkmode = DT_LINK_STATIC; 317 else 318 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 319 320 return (0); 321 } 322 323 /*ARGSUSED*/ 324 static int 325 dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 326 { 327 if (arg == NULL) 328 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 329 330 if (strcasecmp(arg, "elf") == 0) 331 dtp->dt_linktype = DT_LTYP_ELF; 332 else if (strcasecmp(arg, "dof") == 0) 333 dtp->dt_linktype = DT_LTYP_DOF; 334 else 335 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 336 337 return (0); 338 } 339 340 /*ARGSUSED*/ 341 static int 342 dt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 343 { 344 if (arg == NULL) 345 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 346 347 if (strcmp(arg, "ascii") == 0) 348 dtp->dt_encoding = DT_ENCODING_ASCII; 349 else if (strcmp(arg, "utf8") == 0) 350 dtp->dt_encoding = DT_ENCODING_UTF8; 351 else 352 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 353 354 return (0); 355 } 356 357 /*ARGSUSED*/ 358 static int 359 dt_opt_evaltime(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 (strcmp(arg, "exec") == 0) 365 dtp->dt_prcmode = DT_PROC_STOP_CREATE; 366 else if (strcmp(arg, "preinit") == 0) 367 dtp->dt_prcmode = DT_PROC_STOP_PREINIT; 368 else if (strcmp(arg, "postinit") == 0) 369 dtp->dt_prcmode = DT_PROC_STOP_POSTINIT; 370 else if (strcmp(arg, "main") == 0) 371 dtp->dt_prcmode = DT_PROC_STOP_MAIN; 372 else 373 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 374 375 return (0); 376 } 377 378 /*ARGSUSED*/ 379 static int 380 dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 381 { 382 int n; 383 384 if (arg == NULL || (n = atoi(arg)) < 0) 385 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 386 387 dtp->dt_procs->dph_lrulim = n; 388 return (0); 389 } 390 391 static int 392 dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 393 { 394 char **p; 395 char *var; 396 int i; 397 398 /* 399 * We can't effectively set environment variables from #pragma lines 400 * since the processes have already been spawned. 401 */ 402 if (dtp->dt_pcb != NULL) 403 return (dt_set_errno(dtp, EDT_BADOPTCTX)); 404 405 if (arg == NULL) 406 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 407 408 if (!option && strchr(arg, '=') != NULL) 409 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 410 411 for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++) 412 continue; 413 414 for (p = dtp->dt_proc_env; *p != NULL; p++) { 415 var = strchr(*p, '='); 416 if (var == NULL) 417 var = *p + strlen(*p); 418 if (strncmp(*p, arg, var - *p) == 0) { 419 dt_free(dtp, *p); 420 *p = dtp->dt_proc_env[i - 1]; 421 dtp->dt_proc_env[i - 1] = NULL; 422 i--; 423 } 424 } 425 426 if (option) { 427 if ((var = strdup(arg)) == NULL) 428 return (dt_set_errno(dtp, EDT_NOMEM)); 429 430 if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) { 431 dt_free(dtp, var); 432 return (dt_set_errno(dtp, EDT_NOMEM)); 433 } 434 435 bcopy(dtp->dt_proc_env, p, sizeof (char *) * i); 436 dt_free(dtp, dtp->dt_proc_env); 437 dtp->dt_proc_env = p; 438 439 dtp->dt_proc_env[i - 1] = var; 440 dtp->dt_proc_env[i] = NULL; 441 } 442 443 return (0); 444 } 445 446 /*ARGSUSED*/ 447 static int 448 dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 449 { 450 if (arg == NULL) 451 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 452 453 if (dtp->dt_pcb != NULL) 454 return (dt_set_errno(dtp, EDT_BADOPTCTX)); 455 456 if (strcmp(arg, "a") == 0) 457 dtp->dt_stdcmode = DT_STDC_XA; 458 else if (strcmp(arg, "c") == 0) 459 dtp->dt_stdcmode = DT_STDC_XC; 460 else if (strcmp(arg, "s") == 0) 461 dtp->dt_stdcmode = DT_STDC_XS; 462 else if (strcmp(arg, "t") == 0) 463 dtp->dt_stdcmode = DT_STDC_XT; 464 else 465 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 466 467 return (0); 468 } 469 470 /*ARGSUSED*/ 471 static int 472 dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 473 { 474 dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path); 475 char *path; 476 477 if (arg == NULL) 478 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 479 480 if ((path = strdup(arg)) == NULL) 481 return (dt_set_errno(dtp, EDT_NOMEM)); 482 483 free(dp->dir_path); 484 dp->dir_path = path; 485 486 return (0); 487 } 488 489 /*ARGSUSED*/ 490 static int 491 dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 492 { 493 int m; 494 495 if (arg == NULL || (m = atoi(arg)) <= 0) 496 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 497 498 dtp->dt_treedump = m; 499 return (0); 500 } 501 502 /*ARGSUSED*/ 503 static int 504 dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 505 { 506 int n; 507 508 if (arg == NULL || (n = atoi(arg)) <= 0) 509 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 510 511 dtp->dt_conf.dtc_diftupregs = n; 512 return (0); 513 } 514 515 /*ARGSUSED*/ 516 static int 517 dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 518 { 519 if (arg == NULL) 520 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 521 522 if (strcmp(arg, "dynamic") == 0) 523 dtp->dt_xlatemode = DT_XL_DYNAMIC; 524 else if (strcmp(arg, "static") == 0) 525 dtp->dt_xlatemode = DT_XL_STATIC; 526 else 527 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 528 529 return (0); 530 } 531 532 /*ARGSUSED*/ 533 static int 534 dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 535 { 536 if (arg != NULL) 537 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 538 539 if (dtp->dt_pcb != NULL) 540 dtp->dt_pcb->pcb_cflags |= option; 541 else 542 dtp->dt_cflags |= option; 543 544 return (0); 545 } 546 547 static int 548 dt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 549 { 550 if (arg != NULL) 551 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 552 553 dtp->dt_dflags |= option; 554 return (0); 555 } 556 557 static int 558 dt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 559 { 560 if (arg != NULL) 561 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 562 563 if (dtp->dt_pcb != NULL) 564 dtp->dt_pcb->pcb_cflags &= ~option; 565 else 566 dtp->dt_cflags &= ~option; 567 568 return (0); 569 } 570 571 /*ARGSUSED*/ 572 static int 573 dt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 574 { 575 dt_version_t v; 576 577 if (arg == NULL) 578 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 579 580 if (dt_version_str2num(arg, &v) == -1) 581 return (dt_set_errno(dtp, EDT_VERSINVAL)); 582 583 if (!dt_version_defined(v)) 584 return (dt_set_errno(dtp, EDT_VERSUNDEF)); 585 586 return (dt_reduce(dtp, v)); 587 } 588 589 static int 590 dt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 591 { 592 char *end; 593 dtrace_optval_t val = 0; 594 int i; 595 596 const struct { 597 char *positive; 598 char *negative; 599 } couples[] = { 600 { "yes", "no" }, 601 { "enable", "disable" }, 602 { "enabled", "disabled" }, 603 { "true", "false" }, 604 { "on", "off" }, 605 { "set", "unset" }, 606 { NULL } 607 }; 608 609 if (arg != NULL) { 610 if (arg[0] == '\0') { 611 val = DTRACEOPT_UNSET; 612 goto out; 613 } 614 615 for (i = 0; couples[i].positive != NULL; i++) { 616 if (strcasecmp(couples[i].positive, arg) == 0) { 617 val = 1; 618 goto out; 619 } 620 621 if (strcasecmp(couples[i].negative, arg) == 0) { 622 val = DTRACEOPT_UNSET; 623 goto out; 624 } 625 } 626 627 errno = 0; 628 val = strtoull(arg, &end, 0); 629 630 if (*end != '\0' || errno != 0 || val < 0) 631 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 632 } 633 634 out: 635 dtp->dt_options[option] = val; 636 return (0); 637 } 638 639 static int 640 dt_optval_parse(const char *arg, dtrace_optval_t *rval) 641 { 642 dtrace_optval_t mul = 1; 643 size_t len; 644 char *end; 645 646 len = strlen(arg); 647 errno = 0; 648 649 switch (arg[len - 1]) { 650 case 't': 651 case 'T': 652 mul *= 1024; 653 /*FALLTHRU*/ 654 case 'g': 655 case 'G': 656 mul *= 1024; 657 /*FALLTHRU*/ 658 case 'm': 659 case 'M': 660 mul *= 1024; 661 /*FALLTHRU*/ 662 case 'k': 663 case 'K': 664 mul *= 1024; 665 /*FALLTHRU*/ 666 default: 667 break; 668 } 669 670 errno = 0; 671 *rval = strtoull(arg, &end, 0) * mul; 672 673 if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') || 674 *rval < 0 || errno != 0) 675 return (-1); 676 677 return (0); 678 } 679 680 static int 681 dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 682 { 683 dtrace_optval_t val = 0; 684 685 if (arg != NULL && dt_optval_parse(arg, &val) != 0) 686 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 687 688 dtp->dt_options[option] = val; 689 return (0); 690 } 691 692 static int 693 dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 694 { 695 char *end; 696 int i; 697 dtrace_optval_t mul = 1, val = 0; 698 699 const struct { 700 char *name; 701 hrtime_t mul; 702 } suffix[] = { 703 { "ns", NANOSEC / NANOSEC }, 704 { "nsec", NANOSEC / NANOSEC }, 705 { "us", NANOSEC / MICROSEC }, 706 { "usec", NANOSEC / MICROSEC }, 707 { "ms", NANOSEC / MILLISEC }, 708 { "msec", NANOSEC / MILLISEC }, 709 { "s", NANOSEC / SEC }, 710 { "sec", NANOSEC / SEC }, 711 { "m", NANOSEC * (hrtime_t)60 }, 712 { "min", NANOSEC * (hrtime_t)60 }, 713 { "h", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 714 { "hour", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 715 { "d", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 716 { "day", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 717 { "hz", 0 }, 718 { NULL } 719 }; 720 721 if (arg != NULL) { 722 errno = 0; 723 val = strtoull(arg, &end, 0); 724 725 for (i = 0; suffix[i].name != NULL; i++) { 726 if (strcasecmp(suffix[i].name, end) == 0) { 727 mul = suffix[i].mul; 728 break; 729 } 730 } 731 732 if (suffix[i].name == NULL && *end != '\0' || val < 0) 733 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 734 735 if (mul == 0) { 736 /* 737 * The rate has been specified in frequency-per-second. 738 */ 739 if (val != 0) 740 val = NANOSEC / val; 741 } else { 742 val *= mul; 743 } 744 } 745 746 dtp->dt_options[option] = val; 747 return (0); 748 } 749 750 /* 751 * When setting the strsize option, set the option in the dt_options array 752 * using dt_opt_size() as usual, and then update the definition of the CTF 753 * type for the D intrinsic "string" to be an array of the corresponding size. 754 * If any errors occur, reset dt_options[option] to its previous value. 755 */ 756 static int 757 dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 758 { 759 dtrace_optval_t val = dtp->dt_options[option]; 760 ctf_file_t *fp = DT_STR_CTFP(dtp); 761 ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp)); 762 ctf_arinfo_t r; 763 764 if (dt_opt_size(dtp, arg, option) != 0) 765 return (-1); /* dt_errno is set for us */ 766 767 if (dtp->dt_options[option] > UINT_MAX) { 768 dtp->dt_options[option] = val; 769 return (dt_set_errno(dtp, EOVERFLOW)); 770 } 771 772 if (ctf_array_info(fp, type, &r) == CTF_ERR) { 773 dtp->dt_options[option] = val; 774 dtp->dt_ctferr = ctf_errno(fp); 775 return (dt_set_errno(dtp, EDT_CTF)); 776 } 777 778 r.ctr_nelems = (uint_t)dtp->dt_options[option]; 779 780 if (ctf_set_array(fp, type, &r) == CTF_ERR || 781 ctf_update(fp) == CTF_ERR) { 782 dtp->dt_options[option] = val; 783 dtp->dt_ctferr = ctf_errno(fp); 784 return (dt_set_errno(dtp, EDT_CTF)); 785 } 786 787 return (0); 788 } 789 790 static const struct { 791 const char *dtbp_name; 792 int dtbp_policy; 793 } _dtrace_bufpolicies[] = { 794 { "ring", DTRACEOPT_BUFPOLICY_RING }, 795 { "fill", DTRACEOPT_BUFPOLICY_FILL }, 796 { "switch", DTRACEOPT_BUFPOLICY_SWITCH }, 797 { NULL, 0 } 798 }; 799 800 /*ARGSUSED*/ 801 static int 802 dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 803 { 804 dtrace_optval_t policy = DTRACEOPT_UNSET; 805 int i; 806 807 if (arg == NULL) 808 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 809 810 for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) { 811 if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) { 812 policy = _dtrace_bufpolicies[i].dtbp_policy; 813 break; 814 } 815 } 816 817 if (policy == DTRACEOPT_UNSET) 818 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 819 820 dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy; 821 822 return (0); 823 } 824 825 static const struct { 826 const char *dtbr_name; 827 int dtbr_policy; 828 } _dtrace_bufresize[] = { 829 { "auto", DTRACEOPT_BUFRESIZE_AUTO }, 830 { "manual", DTRACEOPT_BUFRESIZE_MANUAL }, 831 { NULL, 0 } 832 }; 833 834 /*ARGSUSED*/ 835 static int 836 dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 837 { 838 dtrace_optval_t policy = DTRACEOPT_UNSET; 839 int i; 840 841 if (arg == NULL) 842 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 843 844 for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) { 845 if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) { 846 policy = _dtrace_bufresize[i].dtbr_policy; 847 break; 848 } 849 } 850 851 if (policy == DTRACEOPT_UNSET) 852 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 853 854 dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy; 855 856 return (0); 857 } 858 859 /*ARGSUSED*/ 860 static int 861 dt_opt_zone(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 862 { 863 zoneid_t z, did; 864 865 if (arg == NULL) 866 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 867 868 /* 869 * If the specified zone is currently running, we'll query the kernel 870 * for its debugger ID. If it doesn't appear to be running, we'll look 871 * for it for among all installed zones (thereby allowing a zdefs 872 * enabling against a halted zone). 873 */ 874 if ((z = getzoneidbyname(arg)) != -1) { 875 if (zone_getattr(z, ZONE_ATTR_DID, &did, sizeof (did)) < 0) 876 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 877 } else { 878 zone_dochandle_t handle; 879 880 if ((handle = zonecfg_init_handle()) == NULL) 881 return (dt_set_errno(dtp, errno)); 882 883 if (zonecfg_get_handle(arg, handle) != Z_OK) { 884 zonecfg_fini_handle(handle); 885 return (dt_set_errno(dtp, EDT_BADOPTVAL)); 886 } 887 888 did = zonecfg_get_did(handle); 889 zonecfg_fini_handle(handle); 890 } 891 892 dtp->dt_options[DTRACEOPT_ZONE] = did; 893 894 return (0); 895 } 896 897 int 898 dt_options_load(dtrace_hdl_t *dtp) 899 { 900 dof_hdr_t hdr, *dof; 901 dof_sec_t *sec; 902 size_t offs; 903 int i; 904 905 /* 906 * To load the option values, we need to ask the kernel to provide its 907 * DOF, which we'll sift through to look for OPTDESC sections. 908 */ 909 bzero(&hdr, sizeof (dof_hdr_t)); 910 hdr.dofh_loadsz = sizeof (dof_hdr_t); 911 912 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1) 913 return (dt_set_errno(dtp, errno)); 914 915 if (hdr.dofh_loadsz < sizeof (dof_hdr_t)) 916 return (dt_set_errno(dtp, EINVAL)); 917 918 dof = calloc(1, hdr.dofh_loadsz); 919 if (dof == NULL) 920 return (dt_set_errno(dtp, errno)); 921 922 dof->dofh_loadsz = hdr.dofh_loadsz; 923 924 for (i = 0; i < DTRACEOPT_MAX; i++) 925 dtp->dt_options[i] = DTRACEOPT_UNSET; 926 927 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1) { 928 free(dof); 929 return (dt_set_errno(dtp, errno)); 930 } 931 932 for (i = 0; i < dof->dofh_secnum; i++) { 933 sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof + 934 dof->dofh_secoff + i * dof->dofh_secsize); 935 936 if (sec->dofs_type != DOF_SECT_OPTDESC) 937 continue; 938 939 break; 940 } 941 942 for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) { 943 dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t) 944 ((uintptr_t)dof + sec->dofs_offset + offs); 945 946 if (opt->dofo_strtab != DOF_SECIDX_NONE) 947 continue; 948 949 if (opt->dofo_option >= DTRACEOPT_MAX) 950 continue; 951 952 dtp->dt_options[opt->dofo_option] = opt->dofo_value; 953 } 954 955 free(dof); 956 return (0); 957 } 958 959 typedef struct dt_option { 960 const char *o_name; 961 int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t); 962 uintptr_t o_option; 963 } dt_option_t; 964 965 /* 966 * Compile-time options. 967 */ 968 static const dt_option_t _dtrace_ctoptions[] = { 969 { "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU }, 970 { "amin", dt_opt_amin }, 971 { "argref", dt_opt_cflags, DTRACE_C_ARGREF }, 972 { "core", dt_opt_core }, 973 { "cpp", dt_opt_cflags, DTRACE_C_CPP }, 974 { "cpphdrs", dt_opt_cpp_hdrs }, 975 { "cpppath", dt_opt_cpp_path }, 976 { "ctypes", dt_opt_ctypes }, 977 { "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG }, 978 { "dtypes", dt_opt_dtypes }, 979 { "debug", dt_opt_debug }, 980 { "define", dt_opt_cpp_opts, (uintptr_t)"-D" }, 981 { "droptags", dt_opt_droptags }, 982 { "empty", dt_opt_cflags, DTRACE_C_EMPTY }, 983 { "encoding", dt_opt_encoding }, 984 { "errtags", dt_opt_cflags, DTRACE_C_ETAGS }, 985 { "evaltime", dt_opt_evaltime }, 986 { "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" }, 987 { "iregs", dt_opt_iregs }, 988 { "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF }, 989 { "knodefs", dt_opt_cflags, DTRACE_C_KNODEF }, 990 { "late", dt_opt_xlate }, 991 { "lazyload", dt_opt_lazyload }, 992 { "ldpath", dt_opt_ld_path }, 993 { "libdir", dt_opt_libdir }, 994 { "linkmode", dt_opt_linkmode }, 995 { "linktype", dt_opt_linktype }, 996 { "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS }, 997 { "pgmax", dt_opt_pgmax }, 998 { "pspec", dt_opt_cflags, DTRACE_C_PSPEC }, 999 { "setenv", dt_opt_setenv, 1 }, 1000 { "stdc", dt_opt_stdc }, 1001 { "strip", dt_opt_dflags, DTRACE_D_STRIP }, 1002 { "syslibdir", dt_opt_syslibdir }, 1003 { "tree", dt_opt_tree }, 1004 { "tregs", dt_opt_tregs }, 1005 { "udefs", dt_opt_invcflags, DTRACE_C_UNODEF }, 1006 { "undef", dt_opt_cpp_opts, (uintptr_t)"-U" }, 1007 { "unodefs", dt_opt_cflags, DTRACE_C_UNODEF }, 1008 { "unsetenv", dt_opt_setenv, 0 }, 1009 { "verbose", dt_opt_cflags, DTRACE_C_DIFV }, 1010 { "version", dt_opt_version }, 1011 { "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS }, 1012 { NULL } 1013 }; 1014 1015 /* 1016 * Run-time options. 1017 */ 1018 static const dt_option_t _dtrace_rtoptions[] = { 1019 { "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE }, 1020 { "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE }, 1021 { "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY }, 1022 { "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE }, 1023 { "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE }, 1024 { "cpu", dt_opt_runtime, DTRACEOPT_CPU }, 1025 { "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE }, 1026 { "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE }, 1027 { "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON }, 1028 { "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES }, 1029 { "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE }, 1030 { "nspec", dt_opt_runtime, DTRACEOPT_NSPEC }, 1031 { "specsize", dt_opt_size, DTRACEOPT_SPECSIZE }, 1032 { "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES }, 1033 { "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE }, 1034 { "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE }, 1035 { "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES }, 1036 { "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL }, 1037 { "zone", dt_opt_zone, DTRACEOPT_ZONE }, 1038 { NULL } 1039 }; 1040 1041 /* 1042 * Dynamic run-time options. 1043 */ 1044 static const dt_option_t _dtrace_drtoptions[] = { 1045 { "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST }, 1046 { "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK }, 1047 { "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE }, 1048 { "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY }, 1049 { "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS }, 1050 { "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS }, 1051 { "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV }, 1052 { "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM }, 1053 { "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT }, 1054 { "quiet", dt_opt_runtime, DTRACEOPT_QUIET }, 1055 { "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES }, 1056 { "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT }, 1057 { "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE }, 1058 { NULL } 1059 }; 1060 1061 int 1062 dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val) 1063 { 1064 const dt_option_t *op; 1065 1066 if (opt == NULL) 1067 return (dt_set_errno(dtp, EINVAL)); 1068 1069 /* 1070 * We only need to search the run-time options -- it's not legal 1071 * to get the values of compile-time options. 1072 */ 1073 for (op = _dtrace_rtoptions; op->o_name != NULL; op++) { 1074 if (strcmp(op->o_name, opt) == 0) { 1075 *val = dtp->dt_options[op->o_option]; 1076 return (0); 1077 } 1078 } 1079 1080 for (op = _dtrace_drtoptions; op->o_name != NULL; op++) { 1081 if (strcmp(op->o_name, opt) == 0) { 1082 *val = dtp->dt_options[op->o_option]; 1083 return (0); 1084 } 1085 } 1086 1087 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 1088 } 1089 1090 int 1091 dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val) 1092 { 1093 const dt_option_t *op; 1094 1095 if (opt == NULL) 1096 return (dt_set_errno(dtp, EINVAL)); 1097 1098 for (op = _dtrace_ctoptions; op->o_name != NULL; op++) { 1099 if (strcmp(op->o_name, opt) == 0) 1100 return (op->o_func(dtp, val, op->o_option)); 1101 } 1102 1103 for (op = _dtrace_drtoptions; op->o_name != NULL; op++) { 1104 if (strcmp(op->o_name, opt) == 0) 1105 return (op->o_func(dtp, val, op->o_option)); 1106 } 1107 1108 for (op = _dtrace_rtoptions; op->o_name != NULL; op++) { 1109 if (strcmp(op->o_name, opt) == 0) { 1110 /* 1111 * Only dynamic run-time options may be set while 1112 * tracing is active. 1113 */ 1114 if (dtp->dt_active) 1115 return (dt_set_errno(dtp, EDT_ACTIVE)); 1116 1117 return (op->o_func(dtp, val, op->o_option)); 1118 } 1119 } 1120 1121 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 1122 }