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