158582Skris/* 265674Skris * CDDL HEADER START 365674Skris * 465674Skris * The contents of this file are subject to the terms of the 565674Skris * Common Development and Distribution License (the "License"). 665674Skris * You may not use this file except in compliance with the License. 765674Skris * 865674Skris * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 965674Skris * or http://www.opensolaris.org/os/licensing. 1065674Skris * See the License for the specific language governing permissions 1165674Skris * and limitations under the License. 1292559Sdes * 1358582Skris * When distributing Covered Code, include this CDDL HEADER in each 1458582Skris * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1558582Skris * If applicable, add the following below this CDDL HEADER, with the 1658582Skris * fields enclosed by brackets "[]" replaced with your own identifying 1758582Skris * information: Portions Copyright [yyyy] [name of copyright owner] 1858582Skris * 1958582Skris * CDDL HEADER END 2058582Skris */ 2158582Skris 2258582Skris/* 2358582Skris * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2458582Skris * Use is subject to license terms. 2558582Skris */ 2658582Skris 2758582Skris/* 2858582Skris * Copyright (c) 2013, Joyent, Inc. All rights reserved. 2958582Skris * Copyright (c) 2012 by Delphix. All rights reserved. 3058582Skris */ 3158582Skris 3258582Skris#include <sys/resource.h> 3358582Skris#include <sys/mman.h> 3476262Sgreen#include <sys/types.h> 35137019Sdes 3658582Skris#include <strings.h> 3758592Skris#include <signal.h> 3876262Sgreen#include <stdlib.h> 3958582Skris#include <unistd.h> 4058582Skris#include <limits.h> 4176262Sgreen#ifdef illumos 4260576Skris#include <alloca.h> 4376262Sgreen#endif 4476262Sgreen#include <errno.h> 4576262Sgreen#include <fcntl.h> 4658582Skris 4758582Skris#include <dt_impl.h> 4858582Skris#include <dt_string.h> 4958582Skris 5058582Skrisstatic int 5158582Skrisdt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 5258582Skris{ 5358582Skris dt_aggregate_t *agp = &dtp->dt_aggregate; 5458582Skris 5592559Sdes if (arg != NULL) 5660576Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 5760576Skris 5858582Skris agp->dtat_flags |= option; 5976262Sgreen return (0); 6058582Skris} 6192559Sdes 6292559Sdes/*ARGSUSED*/ 6392559Sdesstatic int 6492559Sdesdt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 6592559Sdes{ 6692559Sdes char str[DTRACE_ATTR2STR_MAX]; 6758582Skris dtrace_attribute_t attr; 6858582Skris 6958582Skris if (arg == NULL || dtrace_str2attr(arg, &attr) == -1) 7092559Sdes return (dt_set_errno(dtp, EDT_BADOPTVAL)); 7192559Sdes 7292559Sdes dt_dprintf("set compiler attribute minimum to %s\n", 7392559Sdes dtrace_attr2str(attr, str, sizeof (str))); 7492559Sdes 7592559Sdes if (dtp->dt_pcb != NULL) { 7692559Sdes dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR; 7792559Sdes dtp->dt_pcb->pcb_amin = attr; 7892559Sdes } else { 7992559Sdes dtp->dt_cflags |= DTRACE_C_EATTR; 8058582Skris dtp->dt_amin = attr; 8158582Skris } 8276262Sgreen 8358582Skris return (0); 8458582Skris} 8558582Skris 8658582Skrisstatic void 8758582Skrisdt_coredump(void) 8858582Skris{ 8958582Skris const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n"; 9099063Sdes 9176262Sgreen struct sigaction act; 9276262Sgreen struct rlimit lim; 9376262Sgreen 9476262Sgreen (void) write(STDERR_FILENO, msg, sizeof (msg) - 1); 9576262Sgreen 9676262Sgreen act.sa_handler = SIG_DFL; 9776262Sgreen act.sa_flags = 0; 9892559Sdes 9992559Sdes (void) sigemptyset(&act.sa_mask); 10092559Sdes (void) sigaction(SIGABRT, &act, NULL); 10192559Sdes 10292559Sdes lim.rlim_cur = RLIM_INFINITY; 10392559Sdes lim.rlim_max = RLIM_INFINITY; 10492559Sdes 10592559Sdes (void) setrlimit(RLIMIT_CORE, &lim); 10692559Sdes abort(); 10792559Sdes} 10892559Sdes 10992559Sdes/*ARGSUSED*/ 11076262Sgreenstatic int 11176262Sgreendt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 11292559Sdes{ 11392559Sdes static int enabled = 0; 11476262Sgreen 11576262Sgreen if (arg != NULL) 11676262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 11776262Sgreen 11876262Sgreen if (enabled++ || atexit(dt_coredump) == 0) 11976262Sgreen return (0); 12076262Sgreen 12176262Sgreen return (dt_set_errno(dtp, errno)); 12299063Sdes} 12358582Skris 12458582Skris/*ARGSUSED*/ 12558582Skrisstatic int 12658582Skrisdt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 12776262Sgreen{ 12858582Skris if (arg != NULL) 12958582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 13058582Skris 13158582Skris if (dtp->dt_pcb != NULL) 13258582Skris return (dt_set_errno(dtp, EDT_BADOPTCTX)); 13358582Skris 13458582Skris if (dt_cpp_add_arg(dtp, "-H") == NULL) 13558582Skris return (dt_set_errno(dtp, EDT_NOMEM)); 13658582Skris 13758582Skris return (0); 13876262Sgreen} 13976262Sgreen 14058582Skris/*ARGSUSED*/ 14158582Skrisstatic int 14258582Skrisdt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 14358582Skris{ 14458582Skris char *cpp; 14558582Skris 146126277Sdes if (arg == NULL) 14758582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 148126277Sdes 14958582Skris if (dtp->dt_pcb != NULL) 15058582Skris return (dt_set_errno(dtp, EDT_BADOPTCTX)); 15158582Skris 15258582Skris if ((cpp = strdup(arg)) == NULL) 15376262Sgreen return (dt_set_errno(dtp, EDT_NOMEM)); 15458582Skris 15558582Skris dtp->dt_cpp_argv[0] = (char *)strbasename(cpp); 15658582Skris free(dtp->dt_cpp_path); 15758582Skris dtp->dt_cpp_path = cpp; 15858582Skris 15958582Skris return (0); 16058582Skris} 16158582Skris 16258582Skrisstatic int 16358582Skrisdt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 16458582Skris{ 16558582Skris char *buf; 16658582Skris size_t len; 16760576Skris const char *opt = (const char *)option; 16858582Skris 16958582Skris if (opt == NULL || arg == NULL) 17058582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 17158582Skris 17258582Skris if (dtp->dt_pcb != NULL) 173124211Sdes return (dt_set_errno(dtp, EDT_BADOPTCTX)); 174126277Sdes 175126277Sdes len = strlen(opt) + strlen(arg) + 1; 17658582Skris buf = alloca(len); 17792559Sdes 17876262Sgreen (void) strcpy(buf, opt); 17976262Sgreen (void) strcat(buf, arg); 18076262Sgreen 18192559Sdes if (dt_cpp_add_arg(dtp, buf) == NULL) 18260576Skris return (dt_set_errno(dtp, EDT_NOMEM)); 18358582Skris 18476262Sgreen return (0); 18576262Sgreen} 18676262Sgreen 18776262Sgreen/*ARGSUSED*/ 18876262Sgreenstatic int 18976262Sgreendt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 19076262Sgreen{ 19176262Sgreen int fd; 19276262Sgreen 19376262Sgreen if (arg == NULL) 19476262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 19576262Sgreen 19676262Sgreen if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1) 19758582Skris return (dt_set_errno(dtp, errno)); 19876262Sgreen 19958582Skris (void) close(dtp->dt_cdefs_fd); 20058582Skris dtp->dt_cdefs_fd = fd; 20158582Skris return (0); 20260576Skris} 20360576Skris 20460576Skris/*ARGSUSED*/ 20558582Skrisstatic int 20658582Skrisdt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 20776262Sgreen{ 20876262Sgreen dtp->dt_droptags = 1; 20958582Skris return (0); 21076262Sgreen} 21176262Sgreen 21276262Sgreen/*ARGSUSED*/ 21358582Skrisstatic int 21476262Sgreendt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 21558582Skris{ 21658582Skris int fd; 21760576Skris 21876262Sgreen if (arg == NULL) 21965674Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 22065674Skris 22192559Sdes if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1) 22260576Skris return (dt_set_errno(dtp, errno)); 22360576Skris 22476262Sgreen (void) close(dtp->dt_ddefs_fd); 22576262Sgreen dtp->dt_ddefs_fd = fd; 22658582Skris return (0); 22758582Skris} 22858582Skris 22958582Skris/*ARGSUSED*/ 230106130Sdesstatic int 231106130Sdesdt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 23276262Sgreen{ 23376262Sgreen if (arg != NULL) 23476262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 23576262Sgreen 23676262Sgreen _dtrace_debug = 1; 23776262Sgreen return (0); 23892559Sdes} 23976262Sgreen 24076262Sgreen/*ARGSUSED*/ 241124211Sdesstatic int 24276262Sgreendt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 243124211Sdes{ 244124211Sdes int n; 24576262Sgreen 24676262Sgreen if (arg == NULL || (n = atoi(arg)) <= 0) 24776262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 24876262Sgreen 249106130Sdes dtp->dt_conf.dtc_difintregs = n; 250106130Sdes return (0); 25176262Sgreen} 25276262Sgreen 25376262Sgreen/*ARGSUSED*/ 25476262Sgreenstatic int 25576262Sgreendt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 25676262Sgreen{ 25776262Sgreen dtp->dt_lazyload = 1; 25876262Sgreen 25976262Sgreen return (0); 26076262Sgreen} 26176262Sgreen 26276262Sgreen/*ARGSUSED*/ 26376262Sgreenstatic int 26476262Sgreendt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 26576262Sgreen{ 26676262Sgreen char *ld; 26776262Sgreen 26876262Sgreen if (arg == NULL) 26976262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 27076262Sgreen 27176262Sgreen if (dtp->dt_pcb != NULL) 27276262Sgreen return (dt_set_errno(dtp, EDT_BADOPTCTX)); 27376262Sgreen 27476262Sgreen if ((ld = strdup(arg)) == NULL) 27576262Sgreen return (dt_set_errno(dtp, EDT_NOMEM)); 27676262Sgreen 27776262Sgreen free(dtp->dt_ld_path); 27876262Sgreen dtp->dt_ld_path = ld; 27976262Sgreen 28076262Sgreen return (0); 28176262Sgreen} 28276262Sgreen 28376262Sgreen/*ARGSUSED*/ 28476262Sgreenstatic int 28576262Sgreendt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 28676262Sgreen{ 28776262Sgreen dt_dirpath_t *dp; 28876262Sgreen 28976262Sgreen if (arg == NULL) 29076262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 29176262Sgreen 29276262Sgreen if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL || 29376262Sgreen (dp->dir_path = strdup(arg)) == NULL) { 29476262Sgreen free(dp); 29576262Sgreen return (dt_set_errno(dtp, EDT_NOMEM)); 296106130Sdes } 297126277Sdes 29876262Sgreen dt_list_append(&dtp->dt_lib_path, dp); 29976262Sgreen return (0); 30076262Sgreen} 30192559Sdes 30292559Sdes/*ARGSUSED*/ 30376262Sgreenstatic int 30476262Sgreendt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 30576262Sgreen{ 30692559Sdes if (arg == NULL) 30776262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 30876262Sgreen 30976262Sgreen if (strcmp(arg, "kernel") == 0) 31076262Sgreen dtp->dt_linkmode = DT_LINK_KERNEL; 31176262Sgreen else if (strcmp(arg, "primary") == 0) 31276262Sgreen dtp->dt_linkmode = DT_LINK_PRIMARY; 31376262Sgreen else if (strcmp(arg, "dynamic") == 0) 31476262Sgreen dtp->dt_linkmode = DT_LINK_DYNAMIC; 31576262Sgreen else if (strcmp(arg, "static") == 0) 31676262Sgreen dtp->dt_linkmode = DT_LINK_STATIC; 31776262Sgreen else 31876262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 31976262Sgreen 32076262Sgreen return (0); 32176262Sgreen} 32276262Sgreen 32358582Skris/*ARGSUSED*/ 32458582Skrisstatic int 32558582Skrisdt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 32658582Skris{ 32758582Skris if (arg == NULL) 32858582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 32958582Skris 33092559Sdes if (strcasecmp(arg, "elf") == 0) 33158582Skris dtp->dt_linktype = DT_LTYP_ELF; 33258582Skris else if (strcasecmp(arg, "dof") == 0) 33358582Skris dtp->dt_linktype = DT_LTYP_DOF; 33458582Skris else 33558582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 33658582Skris 33758582Skris return (0); 33858582Skris} 33958582Skris 34058582Skris/*ARGSUSED*/ 34158582Skrisstatic int 34258582Skrisdt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 34358582Skris{ 34458582Skris if (arg == NULL) 34558582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 34658582Skris 34758582Skris if (strcmp(arg, "ascii") == 0) 34858582Skris dtp->dt_encoding = DT_ENCODING_ASCII; 34958582Skris else if (strcmp(arg, "utf8") == 0) 35058582Skris dtp->dt_encoding = DT_ENCODING_UTF8; 35158582Skris else 35258582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 35358582Skris 35458582Skris return (0); 35558582Skris} 35658582Skris 35758582Skris/*ARGSUSED*/ 35858582Skrisstatic int 35958582Skrisdt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 36058582Skris{ 36158582Skris if (arg == NULL) 36258582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 36358582Skris 36458582Skris if (strcmp(arg, "exec") == 0) 36558582Skris dtp->dt_prcmode = DT_PROC_STOP_CREATE; 36699063Sdes else if (strcmp(arg, "preinit") == 0) 36792559Sdes dtp->dt_prcmode = DT_PROC_STOP_PREINIT; 36858582Skris else if (strcmp(arg, "postinit") == 0) 36958582Skris dtp->dt_prcmode = DT_PROC_STOP_POSTINIT; 37058582Skris else if (strcmp(arg, "main") == 0) 37158582Skris dtp->dt_prcmode = DT_PROC_STOP_MAIN; 37258582Skris else 37358582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 37458582Skris 37558582Skris return (0); 37692559Sdes} 37758582Skris 37858582Skris/*ARGSUSED*/ 37976262Sgreenstatic int 38092559Sdesdt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 38176262Sgreen{ 38260576Skris int n; 38358582Skris 38460576Skris if (arg == NULL || (n = atoi(arg)) < 0) 38576262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 38676262Sgreen 38776262Sgreen dtp->dt_procs->dph_lrulim = n; 38876262Sgreen return (0); 38976262Sgreen} 39060576Skris 39160576Skrisstatic int 39260576Skrisdt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 39392559Sdes{ 39476262Sgreen char **p; 39560576Skris char *var; 39660576Skris int i; 39776262Sgreen 39860576Skris /* 39960576Skris * We can't effectively set environment variables from #pragma lines 40058582Skris * since the processes have already been spawned. 40176262Sgreen */ 40260576Skris if (dtp->dt_pcb != NULL) 40358582Skris return (dt_set_errno(dtp, EDT_BADOPTCTX)); 40458582Skris 40576262Sgreen if (arg == NULL) 40658582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 40776262Sgreen 40876262Sgreen if (!option && strchr(arg, '=') != NULL) 40958582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 41076262Sgreen 41176262Sgreen for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++) 41258582Skris continue; 41376262Sgreen 41476262Sgreen for (p = dtp->dt_proc_env; *p != NULL; p++) { 415113911Sdes var = strchr(*p, '='); 41676262Sgreen if (var == NULL) 41776262Sgreen var = *p + strlen(*p); 41876262Sgreen if (strncmp(*p, arg, var - *p) == 0) { 41976262Sgreen dt_free(dtp, *p); 42076262Sgreen *p = dtp->dt_proc_env[i - 1]; 42176262Sgreen dtp->dt_proc_env[i - 1] = NULL; 422113911Sdes i--; 42376262Sgreen } 42476262Sgreen } 42576262Sgreen 42676262Sgreen if (option) { 42776262Sgreen if ((var = strdup(arg)) == NULL) 42876262Sgreen return (dt_set_errno(dtp, EDT_NOMEM)); 42976262Sgreen 43076262Sgreen if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) { 43176262Sgreen dt_free(dtp, var); 43276262Sgreen return (dt_set_errno(dtp, EDT_NOMEM)); 43376262Sgreen } 43476262Sgreen 43592559Sdes bcopy(dtp->dt_proc_env, p, sizeof (char *) * i); 43676262Sgreen dt_free(dtp, dtp->dt_proc_env); 43760576Skris dtp->dt_proc_env = p; 43860576Skris 43960576Skris dtp->dt_proc_env[i - 1] = var; 44060576Skris dtp->dt_proc_env[i] = NULL; 44161203Skris } 44292559Sdes 44376262Sgreen return (0); 44460576Skris} 445124211Sdes 44692559Sdes/*ARGSUSED*/ 44761203Skrisstatic int 44876262Sgreendt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 44976262Sgreen{ 45061203Skris if (arg == NULL) 45176262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 45276262Sgreen 45376262Sgreen if (dtp->dt_pcb != NULL) 45476262Sgreen return (dt_set_errno(dtp, EDT_BADOPTCTX)); 45576262Sgreen 45676262Sgreen if (strcmp(arg, "a") == 0) 45776262Sgreen dtp->dt_stdcmode = DT_STDC_XA; 45876262Sgreen else if (strcmp(arg, "c") == 0) 45976262Sgreen dtp->dt_stdcmode = DT_STDC_XC; 46076262Sgreen else if (strcmp(arg, "s") == 0) 46176262Sgreen dtp->dt_stdcmode = DT_STDC_XS; 46276262Sgreen else if (strcmp(arg, "t") == 0) 46376262Sgreen dtp->dt_stdcmode = DT_STDC_XT; 46476262Sgreen else 46576262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 46676262Sgreen 46776262Sgreen return (0); 46876262Sgreen} 46976262Sgreen 47076262Sgreen/*ARGSUSED*/ 47176262Sgreenstatic int 47276262Sgreendt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 47376262Sgreen{ 47476262Sgreen dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path); 47576262Sgreen char *path; 47676262Sgreen 47792559Sdes if (arg == NULL) 47876262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 47976262Sgreen 48061203Skris if ((path = strdup(arg)) == NULL) 48161203Skris return (dt_set_errno(dtp, EDT_NOMEM)); 48261203Skris 48361203Skris free(dp->dir_path); 48461203Skris dp->dir_path = path; 48561203Skris 48658582Skris return (0); 48758582Skris} 48860576Skris 48958582Skris/*ARGSUSED*/ 49058582Skrisstatic int 49176262Sgreendt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 49258582Skris{ 49399063Sdes int m; 49458582Skris 495126277Sdes if (arg == NULL || (m = atoi(arg)) <= 0) 49658582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 49792559Sdes 49892559Sdes dtp->dt_treedump = m; 499106130Sdes return (0); 500106130Sdes} 50158582Skris 50276262Sgreen/*ARGSUSED*/ 50358582Skrisstatic int 50458582Skrisdt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 50558582Skris{ 50658582Skris int n; 50758582Skris 50858582Skris if (arg == NULL || (n = atoi(arg)) <= 0) 50958582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 51058582Skris 51158582Skris dtp->dt_conf.dtc_diftupregs = n; 51276262Sgreen return (0); 51376262Sgreen} 51476262Sgreen 51560576Skris/*ARGSUSED*/ 51660576Skrisstatic int 51760576Skrisdt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 51876262Sgreen{ 51958582Skris if (arg == NULL) 52058582Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 52160576Skris 52260576Skris if (strcmp(arg, "dynamic") == 0) 52358582Skris dtp->dt_xlatemode = DT_XL_DYNAMIC; 52458582Skris else if (strcmp(arg, "static") == 0) 52558582Skris dtp->dt_xlatemode = DT_XL_STATIC; 52699063Sdes else 527126277Sdes return (dt_set_errno(dtp, EDT_BADOPTVAL)); 528126277Sdes 52960576Skris return (0); 53060576Skris} 53176262Sgreen 53276262Sgreen/*ARGSUSED*/ 53376262Sgreenstatic int 53460576Skrisdt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 53560576Skris{ 53660576Skris if (arg != NULL) 53760576Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 53860576Skris 53960576Skris if (dtp->dt_pcb != NULL) 54060576Skris dtp->dt_pcb->pcb_cflags |= option; 54160576Skris else 54260576Skris dtp->dt_cflags |= option; 54399063Sdes 544126277Sdes return (0); 545126277Sdes} 54676262Sgreen 54776262Sgreenstatic int 54876262Sgreendt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 54976262Sgreen{ 55076262Sgreen if (arg != NULL) 55176262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 55276262Sgreen 55376262Sgreen dtp->dt_dflags |= option; 55476262Sgreen return (0); 55576262Sgreen} 55676262Sgreen 55799063Sdesstatic int 55876262Sgreendt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 559126277Sdes{ 56092559Sdes if (arg != NULL) 56165674Skris return (dt_set_errno(dtp, EDT_BADOPTVAL)); 56276262Sgreen 56365674Skris if (dtp->dt_pcb != NULL) 56465674Skris dtp->dt_pcb->pcb_cflags &= ~option; 56565674Skris else 56665674Skris dtp->dt_cflags &= ~option; 56765674Skris 56865674Skris return (0); 56965674Skris} 57065674Skris 57165674Skris/*ARGSUSED*/ 57276262Sgreenstatic int 57392559Sdesdt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 57476262Sgreen{ 57576262Sgreen dt_version_t v; 57676262Sgreen 57776262Sgreen if (arg == NULL) 57876262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 57976262Sgreen 58076262Sgreen if (dt_version_str2num(arg, &v) == -1) 58176262Sgreen return (dt_set_errno(dtp, EDT_VERSINVAL)); 58276262Sgreen 58392559Sdes if (!dt_version_defined(v)) 58476262Sgreen return (dt_set_errno(dtp, EDT_VERSUNDEF)); 58576262Sgreen 58676262Sgreen return (dt_reduce(dtp, v)); 58776262Sgreen} 58876262Sgreen 58976262Sgreenstatic int 59076262Sgreendt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 59176262Sgreen{ 59276262Sgreen char *end; 59376262Sgreen dtrace_optval_t val = 0; 59476262Sgreen int i; 59576262Sgreen 59676262Sgreen const struct { 59776262Sgreen char *positive; 59876262Sgreen char *negative; 59976262Sgreen } couples[] = { 60076262Sgreen { "yes", "no" }, 60176262Sgreen { "enable", "disable" }, 60276262Sgreen { "enabled", "disabled" }, 60376262Sgreen { "true", "false" }, 60476262Sgreen { "on", "off" }, 60576262Sgreen { "set", "unset" }, 60676262Sgreen { NULL } 60776262Sgreen }; 60876262Sgreen 60976262Sgreen if (arg != NULL) { 61076262Sgreen if (arg[0] == '\0') { 61176262Sgreen val = DTRACEOPT_UNSET; 61276262Sgreen goto out; 61376262Sgreen } 61476262Sgreen 61576262Sgreen for (i = 0; couples[i].positive != NULL; i++) { 616126277Sdes if (strcasecmp(couples[i].positive, arg) == 0) { 61776262Sgreen val = 1; 61876262Sgreen goto out; 61976262Sgreen } 62076262Sgreen 62176262Sgreen if (strcasecmp(couples[i].negative, arg) == 0) { 62276262Sgreen val = DTRACEOPT_UNSET; 62376262Sgreen goto out; 62476262Sgreen } 62576262Sgreen } 62676262Sgreen 62776262Sgreen errno = 0; 62876262Sgreen val = strtoull(arg, &end, 0); 62976262Sgreen 63076262Sgreen if (*end != '\0' || errno != 0 || val < 0) 63176262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 63276262Sgreen } 63376262Sgreen 63476262Sgreenout: 63576262Sgreen dtp->dt_options[option] = val; 63676262Sgreen return (0); 63776262Sgreen} 63876262Sgreen 63976262Sgreenstatic int 64076262Sgreendt_optval_parse(const char *arg, dtrace_optval_t *rval) 64176262Sgreen{ 64276262Sgreen dtrace_optval_t mul = 1; 64392559Sdes size_t len; 64476262Sgreen char *end; 64592559Sdes 64676262Sgreen len = strlen(arg); 64792559Sdes errno = 0; 64876262Sgreen 64992559Sdes switch (arg[len - 1]) { 65076262Sgreen case 't': 65192559Sdes case 'T': 65276262Sgreen mul *= 1024; 65376262Sgreen /*FALLTHRU*/ 65476262Sgreen case 'g': 65576262Sgreen case 'G': 65676262Sgreen mul *= 1024; 65776262Sgreen /*FALLTHRU*/ 65876262Sgreen case 'm': 65976262Sgreen case 'M': 66076262Sgreen mul *= 1024; 66176262Sgreen /*FALLTHRU*/ 66276262Sgreen case 'k': 66376262Sgreen case 'K': 66476262Sgreen mul *= 1024; 66576262Sgreen /*FALLTHRU*/ 66676262Sgreen default: 66792559Sdes break; 66876262Sgreen } 66976262Sgreen 67076262Sgreen errno = 0; 67176262Sgreen *rval = strtoull(arg, &end, 0) * mul; 67276262Sgreen 67376262Sgreen if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') || 67476262Sgreen *rval < 0 || errno != 0) 67576262Sgreen return (-1); 67676262Sgreen 67776262Sgreen return (0); 67876262Sgreen} 67976262Sgreen 68076262Sgreenstatic int 681126277Sdesdt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 68276262Sgreen{ 68376262Sgreen dtrace_optval_t val = 0; 68476262Sgreen 68576262Sgreen if (arg != NULL && dt_optval_parse(arg, &val) != 0) 68676262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 68776262Sgreen 68876262Sgreen dtp->dt_options[option] = val; 68976262Sgreen return (0); 69076262Sgreen} 69176262Sgreen 69276262Sgreenstatic int 69376262Sgreendt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 69476262Sgreen{ 69576262Sgreen char *end; 69692559Sdes int i; 69776262Sgreen dtrace_optval_t mul = 1, val = 0; 69876262Sgreen 69976262Sgreen const struct { 70076262Sgreen char *name; 70176262Sgreen hrtime_t mul; 70276262Sgreen } suffix[] = { 70376262Sgreen { "ns", NANOSEC / NANOSEC }, 70476262Sgreen { "nsec", NANOSEC / NANOSEC }, 70576262Sgreen { "us", NANOSEC / MICROSEC }, 70676262Sgreen { "usec", NANOSEC / MICROSEC }, 70776262Sgreen { "ms", NANOSEC / MILLISEC }, 70876262Sgreen { "msec", NANOSEC / MILLISEC }, 70976262Sgreen { "s", NANOSEC / SEC }, 71076262Sgreen { "sec", NANOSEC / SEC }, 71176262Sgreen { "m", NANOSEC * (hrtime_t)60 }, 71276262Sgreen { "min", NANOSEC * (hrtime_t)60 }, 71376262Sgreen { "h", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 71476262Sgreen { "hour", NANOSEC * (hrtime_t)60 * (hrtime_t)60 }, 71576262Sgreen { "d", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 71676262Sgreen { "day", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 71776262Sgreen { "hz", 0 }, 71876262Sgreen { NULL } 71976262Sgreen }; 72076262Sgreen 72176262Sgreen if (arg != NULL) { 72276262Sgreen errno = 0; 72376262Sgreen val = strtoull(arg, &end, 0); 72476262Sgreen 72576262Sgreen for (i = 0; suffix[i].name != NULL; i++) { 72676262Sgreen if (strcasecmp(suffix[i].name, end) == 0) { 72776262Sgreen mul = suffix[i].mul; 72876262Sgreen break; 72976262Sgreen } 73076262Sgreen } 731126277Sdes 73276262Sgreen if (suffix[i].name == NULL && *end != '\0' || val < 0) 73376262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 73476262Sgreen 73576262Sgreen if (mul == 0) { 73676262Sgreen /* 73776262Sgreen * The rate has been specified in frequency-per-second. 73876262Sgreen */ 73976262Sgreen if (val != 0) 74076262Sgreen val = NANOSEC / val; 74192559Sdes } else { 74276262Sgreen val *= mul; 74376262Sgreen } 74476262Sgreen } 74576262Sgreen 74676262Sgreen dtp->dt_options[option] = val; 74776262Sgreen return (0); 74876262Sgreen} 74976262Sgreen 75076262Sgreen/* 75176262Sgreen * When setting the strsize option, set the option in the dt_options array 75276262Sgreen * using dt_opt_size() as usual, and then update the definition of the CTF 75376262Sgreen * type for the D intrinsic "string" to be an array of the corresponding size. 75476262Sgreen * If any errors occur, reset dt_options[option] to its previous value. 75592559Sdes */ 75692559Sdesstatic int 75792559Sdesdt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 75876262Sgreen{ 75976262Sgreen dtrace_optval_t val = dtp->dt_options[option]; 760106130Sdes ctf_file_t *fp = DT_STR_CTFP(dtp); 761106130Sdes ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp)); 762106130Sdes ctf_arinfo_t r; 763106130Sdes 764106130Sdes if (dt_opt_size(dtp, arg, option) != 0) 765106130Sdes return (-1); /* dt_errno is set for us */ 76676262Sgreen 76776262Sgreen if (dtp->dt_options[option] > UINT_MAX) { 76876262Sgreen dtp->dt_options[option] = val; 76976262Sgreen return (dt_set_errno(dtp, EOVERFLOW)); 77076262Sgreen } 77176262Sgreen 77276262Sgreen if (ctf_array_info(fp, type, &r) == CTF_ERR) { 773126277Sdes dtp->dt_options[option] = val; 77492559Sdes dtp->dt_ctferr = ctf_errno(fp); 775126277Sdes return (dt_set_errno(dtp, EDT_CTF)); 77676262Sgreen } 77792559Sdes 77876262Sgreen r.ctr_nelems = (uint_t)dtp->dt_options[option]; 77976262Sgreen 78076262Sgreen if (ctf_set_array(fp, type, &r) == CTF_ERR || 78176262Sgreen ctf_update(fp) == CTF_ERR) { 78276262Sgreen dtp->dt_options[option] = val; 78376262Sgreen dtp->dt_ctferr = ctf_errno(fp); 78476262Sgreen return (dt_set_errno(dtp, EDT_CTF)); 785137019Sdes } 78676262Sgreen 78776262Sgreen return (0); 78876262Sgreen} 78976262Sgreen 79076262Sgreenstatic const struct { 79198684Sdes const char *dtbp_name; 79298684Sdes int dtbp_policy; 79398684Sdes} _dtrace_bufpolicies[] = { 79498684Sdes { "ring", DTRACEOPT_BUFPOLICY_RING }, 79576262Sgreen { "fill", DTRACEOPT_BUFPOLICY_FILL }, 79676262Sgreen { "switch", DTRACEOPT_BUFPOLICY_SWITCH }, 797126277Sdes { NULL, 0 } 798126277Sdes}; 799126277Sdes 80076262Sgreen/*ARGSUSED*/ 80192559Sdesstatic int 80292559Sdesdt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 80392559Sdes{ 80492559Sdes dtrace_optval_t policy = DTRACEOPT_UNSET; 80576262Sgreen int i; 80676262Sgreen 80776262Sgreen if (arg == NULL) 80876262Sgreen return (dt_set_errno(dtp, EDT_BADOPTVAL)); 80976262Sgreen 81076262Sgreen for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) { 81176262Sgreen if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) { 812137019Sdes policy = _dtrace_bufpolicies[i].dtbp_policy; 81376262Sgreen break; 81476262Sgreen } 81576262Sgreen } 81676262Sgreen 81798684Sdes if (policy == DTRACEOPT_UNSET) 81898684Sdes return (dt_set_errno(dtp, EDT_BADOPTVAL)); 81998684Sdes 820126277Sdes dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy; 82198684Sdes 82298684Sdes return (0); 82398684Sdes} 82498684Sdes 82598684Sdesstatic const struct { 82698684Sdes const char *dtbr_name; 82798684Sdes int dtbr_policy; 82898684Sdes} _dtrace_bufresize[] = { 82998684Sdes { "auto", DTRACEOPT_BUFRESIZE_AUTO }, 83098684Sdes { "manual", DTRACEOPT_BUFRESIZE_MANUAL }, 83198684Sdes { NULL, 0 } 83298684Sdes}; 83398684Sdes 83498684Sdes/*ARGSUSED*/ 83598684Sdesstatic int 83698684Sdesdt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) 83798684Sdes{ 83898684Sdes dtrace_optval_t policy = DTRACEOPT_UNSET; 83998684Sdes int i; 84098684Sdes 84198684Sdes if (arg == NULL) 84298684Sdes return (dt_set_errno(dtp, EDT_BADOPTVAL)); 84398684Sdes 84498684Sdes for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) { 84598684Sdes if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) { 84698684Sdes policy = _dtrace_bufresize[i].dtbr_policy; 84798684Sdes break; 84898684Sdes } 84998684Sdes } 85098684Sdes 85198684Sdes if (policy == DTRACEOPT_UNSET) 85298684Sdes return (dt_set_errno(dtp, EDT_BADOPTVAL)); 85398684Sdes 85498684Sdes dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy; 85598684Sdes 85698684Sdes return (0); 85798684Sdes} 85898684Sdes 859int 860dt_options_load(dtrace_hdl_t *dtp) 861{ 862 dof_hdr_t hdr, *dof; 863 dof_sec_t *sec; 864 size_t offs; 865 int i; 866 867 /* 868 * To load the option values, we need to ask the kernel to provide its 869 * DOF, which we'll sift through to look for OPTDESC sections. 870 */ 871 bzero(&hdr, sizeof (dof_hdr_t)); 872 hdr.dofh_loadsz = sizeof (dof_hdr_t); 873 874#ifdef illumos 875 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1) 876#else 877 dof = &hdr; 878 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1) 879#endif 880 return (dt_set_errno(dtp, errno)); 881 882 if (hdr.dofh_loadsz < sizeof (dof_hdr_t)) 883 return (dt_set_errno(dtp, EINVAL)); 884 885 dof = alloca(hdr.dofh_loadsz); 886 bzero(dof, sizeof (dof_hdr_t)); 887 dof->dofh_loadsz = hdr.dofh_loadsz; 888 889 for (i = 0; i < DTRACEOPT_MAX; i++) 890 dtp->dt_options[i] = DTRACEOPT_UNSET; 891 892#ifdef illumos 893 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1) 894#else 895 if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1) 896#endif 897 return (dt_set_errno(dtp, errno)); 898 899 for (i = 0; i < dof->dofh_secnum; i++) { 900 sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof + 901 dof->dofh_secoff + i * dof->dofh_secsize); 902 903 if (sec->dofs_type != DOF_SECT_OPTDESC) 904 continue; 905 906 break; 907 } 908 909 for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) { 910 dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t) 911 ((uintptr_t)dof + sec->dofs_offset + offs); 912 913 if (opt->dofo_strtab != DOF_SECIDX_NONE) 914 continue; 915 916 if (opt->dofo_option >= DTRACEOPT_MAX) 917 continue; 918 919 dtp->dt_options[opt->dofo_option] = opt->dofo_value; 920 } 921 922 return (0); 923} 924 925typedef struct dt_option { 926 const char *o_name; 927 int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t); 928 uintptr_t o_option; 929} dt_option_t; 930 931/* 932 * Compile-time options. 933 */ 934static const dt_option_t _dtrace_ctoptions[] = { 935 { "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU }, 936 { "amin", dt_opt_amin }, 937 { "argref", dt_opt_cflags, DTRACE_C_ARGREF }, 938 { "core", dt_opt_core }, 939 { "cpp", dt_opt_cflags, DTRACE_C_CPP }, 940 { "cpphdrs", dt_opt_cpp_hdrs }, 941 { "cpppath", dt_opt_cpp_path }, 942 { "ctypes", dt_opt_ctypes }, 943 { "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG }, 944 { "dtypes", dt_opt_dtypes }, 945 { "debug", dt_opt_debug }, 946 { "define", dt_opt_cpp_opts, (uintptr_t)"-D" }, 947 { "droptags", dt_opt_droptags }, 948 { "empty", dt_opt_cflags, DTRACE_C_EMPTY }, 949 { "encoding", dt_opt_encoding }, 950 { "errtags", dt_opt_cflags, DTRACE_C_ETAGS }, 951 { "evaltime", dt_opt_evaltime }, 952 { "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" }, 953 { "iregs", dt_opt_iregs }, 954 { "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF }, 955 { "knodefs", dt_opt_cflags, DTRACE_C_KNODEF }, 956 { "late", dt_opt_xlate }, 957 { "lazyload", dt_opt_lazyload }, 958 { "ldpath", dt_opt_ld_path }, 959 { "libdir", dt_opt_libdir }, 960 { "linkmode", dt_opt_linkmode }, 961 { "linktype", dt_opt_linktype }, 962 { "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS }, 963 { "pgmax", dt_opt_pgmax }, 964 { "pspec", dt_opt_cflags, DTRACE_C_PSPEC }, 965 { "setenv", dt_opt_setenv, 1 }, 966 { "stdc", dt_opt_stdc }, 967 { "strip", dt_opt_dflags, DTRACE_D_STRIP }, 968 { "syslibdir", dt_opt_syslibdir }, 969 { "tree", dt_opt_tree }, 970 { "tregs", dt_opt_tregs }, 971 { "udefs", dt_opt_invcflags, DTRACE_C_UNODEF }, 972 { "undef", dt_opt_cpp_opts, (uintptr_t)"-U" }, 973 { "unodefs", dt_opt_cflags, DTRACE_C_UNODEF }, 974 { "unsetenv", dt_opt_setenv, 0 }, 975 { "verbose", dt_opt_cflags, DTRACE_C_DIFV }, 976 { "version", dt_opt_version }, 977 { "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS }, 978 { NULL, NULL, 0 } 979}; 980 981/* 982 * Run-time options. 983 */ 984static const dt_option_t _dtrace_rtoptions[] = { 985 { "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE }, 986 { "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE }, 987 { "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY }, 988 { "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE }, 989 { "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE }, 990 { "cpu", dt_opt_runtime, DTRACEOPT_CPU }, 991 { "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE }, 992 { "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE }, 993 { "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON }, 994 { "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES }, 995 { "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE }, 996 { "nspec", dt_opt_runtime, DTRACEOPT_NSPEC }, 997 { "specsize", dt_opt_size, DTRACEOPT_SPECSIZE }, 998 { "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES }, 999 { "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE }, 1000 { "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE }, 1001 { "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES }, 1002 { "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL }, 1003 { NULL, NULL, 0 } 1004}; 1005 1006/* 1007 * Dynamic run-time options. 1008 */ 1009static const dt_option_t _dtrace_drtoptions[] = { 1010 { "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST }, 1011 { "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK }, 1012 { "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE }, 1013 { "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY }, 1014 { "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS }, 1015 { "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS }, 1016 { "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV }, 1017 { "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM }, 1018 { "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT }, 1019 { "quiet", dt_opt_runtime, DTRACEOPT_QUIET }, 1020 { "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES }, 1021 { "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT }, 1022 { "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE }, 1023 { NULL, NULL, 0 } 1024}; 1025 1026int 1027dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val) 1028{ 1029 const dt_option_t *op; 1030 1031 if (opt == NULL) 1032 return (dt_set_errno(dtp, EINVAL)); 1033 1034 /* 1035 * We only need to search the run-time options -- it's not legal 1036 * to get the values of compile-time options. 1037 */ 1038 for (op = _dtrace_rtoptions; op->o_name != NULL; op++) { 1039 if (strcmp(op->o_name, opt) == 0) { 1040 *val = dtp->dt_options[op->o_option]; 1041 return (0); 1042 } 1043 } 1044 1045 for (op = _dtrace_drtoptions; op->o_name != NULL; op++) { 1046 if (strcmp(op->o_name, opt) == 0) { 1047 *val = dtp->dt_options[op->o_option]; 1048 return (0); 1049 } 1050 } 1051 1052 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 1053} 1054 1055int 1056dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val) 1057{ 1058 const dt_option_t *op; 1059 1060 if (opt == NULL) 1061 return (dt_set_errno(dtp, EINVAL)); 1062 1063 for (op = _dtrace_ctoptions; op->o_name != NULL; op++) { 1064 if (strcmp(op->o_name, opt) == 0) 1065 return (op->o_func(dtp, val, op->o_option)); 1066 } 1067 1068 for (op = _dtrace_drtoptions; 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_rtoptions; op->o_name != NULL; op++) { 1074 if (strcmp(op->o_name, opt) == 0) { 1075 /* 1076 * Only dynamic run-time options may be set while 1077 * tracing is active. 1078 */ 1079 if (dtp->dt_active) 1080 return (dt_set_errno(dtp, EDT_ACTIVE)); 1081 1082 return (op->o_func(dtp, val, op->o_option)); 1083 } 1084 } 1085 1086 return (dt_set_errno(dtp, EDT_BADOPTNAME)); 1087} 1088