Path: blob/main/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
39562 views
/*1* CDDL HEADER START2*3* The contents of this file are subject to the terms of the4* Common Development and Distribution License (the "License").5* You may not use this file except in compliance with the License.6*7* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE8* or http://www.opensolaris.org/os/licensing.9* See the License for the specific language governing permissions10* and limitations under the License.11*12* When distributing Covered Code, include this CDDL HEADER in each13* file and include the License file at usr/src/OPENSOLARIS.LICENSE.14* If applicable, add the following below this CDDL HEADER, with the15* fields enclosed by brackets "[]" replaced with your own identifying16* information: Portions Copyright [yyyy] [name of copyright owner]17*18* CDDL HEADER END19*/2021/*22* Copyright 2007 Sun Microsystems, Inc. All rights reserved.23* Use is subject to license terms.24*/2526/*27* Copyright (c) 2013, Joyent, Inc. All rights reserved.28* Copyright (c) 2012 by Delphix. All rights reserved.29*/3031#include <sys/resource.h>32#include <sys/mman.h>33#include <sys/types.h>3435#include <strings.h>36#include <signal.h>37#include <stdlib.h>38#include <unistd.h>39#include <limits.h>40#include <errno.h>41#include <fcntl.h>4243#include <dt_impl.h>44#include <dt_string.h>45#include <dt_oformat.h>4647static int48dt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)49{50dt_aggregate_t *agp = &dtp->dt_aggregate;5152if (arg != NULL)53return (dt_set_errno(dtp, EDT_BADOPTVAL));5455agp->dtat_flags |= option;56return (0);57}5859/*ARGSUSED*/60static int61dt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)62{63char str[DTRACE_ATTR2STR_MAX];64dtrace_attribute_t attr;6566if (arg == NULL || dtrace_str2attr(arg, &attr) == -1)67return (dt_set_errno(dtp, EDT_BADOPTVAL));6869dt_dprintf("set compiler attribute minimum to %s\n",70dtrace_attr2str(attr, str, sizeof (str)));7172if (dtp->dt_pcb != NULL) {73dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR;74dtp->dt_pcb->pcb_amin = attr;75} else {76dtp->dt_cflags |= DTRACE_C_EATTR;77dtp->dt_amin = attr;78}7980return (0);81}8283static void84dt_coredump(void)85{86const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n";8788struct sigaction act;89struct rlimit lim;9091(void) write(STDERR_FILENO, msg, sizeof (msg) - 1);9293act.sa_handler = SIG_DFL;94act.sa_flags = 0;9596(void) sigemptyset(&act.sa_mask);97(void) sigaction(SIGABRT, &act, NULL);9899lim.rlim_cur = RLIM_INFINITY;100lim.rlim_max = RLIM_INFINITY;101102(void) setrlimit(RLIMIT_CORE, &lim);103abort();104}105106/*ARGSUSED*/107static int108dt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)109{110static int enabled = 0;111112if (arg != NULL)113return (dt_set_errno(dtp, EDT_BADOPTVAL));114115if (enabled++ || atexit(dt_coredump) == 0)116return (0);117118return (dt_set_errno(dtp, errno));119}120121/*ARGSUSED*/122static int123dt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)124{125if (arg != NULL)126return (dt_set_errno(dtp, EDT_BADOPTVAL));127128if (dtp->dt_pcb != NULL)129return (dt_set_errno(dtp, EDT_BADOPTCTX));130131if (dt_cpp_add_arg(dtp, "-H") == NULL)132return (dt_set_errno(dtp, EDT_NOMEM));133134return (0);135}136137/*ARGSUSED*/138static int139dt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)140{141char *cpp;142143if (arg == NULL)144return (dt_set_errno(dtp, EDT_BADOPTVAL));145146if (dtp->dt_pcb != NULL)147return (dt_set_errno(dtp, EDT_BADOPTCTX));148149if ((cpp = strdup(arg)) == NULL)150return (dt_set_errno(dtp, EDT_NOMEM));151152dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);153free(dtp->dt_cpp_path);154dtp->dt_cpp_path = cpp;155156return (0);157}158159static int160dt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)161{162char *buf = NULL;163size_t len;164const char *opt = (const char *)option;165int ret;166167if (opt == NULL || arg == NULL) {168ret = dt_set_errno(dtp, EDT_BADOPTVAL);169goto out;170}171172if (dtp->dt_pcb != NULL) {173ret = dt_set_errno(dtp, EDT_BADOPTCTX);174goto out;175}176177len = strlen(opt) + strlen(arg) + 1;178if ((buf = dt_alloc(dtp, len)) == NULL) {179ret = dt_set_errno(dtp, EDT_NOMEM);180goto out;181}182183(void) strcpy(buf, opt);184(void) strcat(buf, arg);185186if (dt_cpp_add_arg(dtp, buf) == NULL) {187ret = dt_set_errno(dtp, EDT_NOMEM);188goto out;189}190191ret = 0;192out:193if (buf != NULL)194dt_free(dtp, buf);195return (ret);196}197198/*ARGSUSED*/199static int200dt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)201{202int fd;203204if (arg == NULL)205return (dt_set_errno(dtp, EDT_BADOPTVAL));206207if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)208return (dt_set_errno(dtp, errno));209210(void) close(dtp->dt_cdefs_fd);211dtp->dt_cdefs_fd = fd;212return (0);213}214215/*ARGSUSED*/216static int217dt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)218{219dtp->dt_droptags = 1;220return (0);221}222223/*ARGSUSED*/224static int225dt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)226{227int fd;228229if (arg == NULL)230return (dt_set_errno(dtp, EDT_BADOPTVAL));231232if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)233return (dt_set_errno(dtp, errno));234235(void) close(dtp->dt_ddefs_fd);236dtp->dt_ddefs_fd = fd;237return (0);238}239240/*ARGSUSED*/241static int242dt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)243{244if (arg != NULL)245return (dt_set_errno(dtp, EDT_BADOPTVAL));246247_dtrace_debug = 1;248return (0);249}250251/*ARGSUSED*/252static int253dt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)254{255int n;256257if (arg == NULL || (n = atoi(arg)) <= 0)258return (dt_set_errno(dtp, EDT_BADOPTVAL));259260dtp->dt_conf.dtc_difintregs = n;261return (0);262}263264/*ARGSUSED*/265static int266dt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)267{268dtp->dt_lazyload = 1;269270return (0);271}272273/*ARGSUSED*/274static int275dt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)276{277char *ld;278279if (arg == NULL)280return (dt_set_errno(dtp, EDT_BADOPTVAL));281282if (dtp->dt_pcb != NULL)283return (dt_set_errno(dtp, EDT_BADOPTCTX));284285if ((ld = strdup(arg)) == NULL)286return (dt_set_errno(dtp, EDT_NOMEM));287288free(dtp->dt_ld_path);289dtp->dt_ld_path = ld;290291return (0);292}293294#ifdef __FreeBSD__295static int296dt_opt_objcopy_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)297{298char *objcopy;299300if (arg == NULL)301return (dt_set_errno(dtp, EDT_BADOPTVAL));302303if (dtp->dt_pcb != NULL)304return (dt_set_errno(dtp, EDT_BADOPTCTX));305306if ((objcopy = strdup(arg)) == NULL)307return (dt_set_errno(dtp, EDT_NOMEM));308309free(dtp->dt_objcopy_path);310dtp->dt_objcopy_path = objcopy;311312return (0);313}314#endif315316/*ARGSUSED*/317static int318dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)319{320dt_dirpath_t *dp;321322if (arg == NULL)323return (dt_set_errno(dtp, EDT_BADOPTVAL));324325if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL ||326(dp->dir_path = strdup(arg)) == NULL) {327free(dp);328return (dt_set_errno(dtp, EDT_NOMEM));329}330331dt_list_append(&dtp->dt_lib_path, dp);332return (0);333}334335/*ARGSUSED*/336static int337dt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)338{339if (arg == NULL)340return (dt_set_errno(dtp, EDT_BADOPTVAL));341342if (strcmp(arg, "kernel") == 0)343dtp->dt_linkmode = DT_LINK_KERNEL;344else if (strcmp(arg, "primary") == 0)345dtp->dt_linkmode = DT_LINK_PRIMARY;346else if (strcmp(arg, "dynamic") == 0)347dtp->dt_linkmode = DT_LINK_DYNAMIC;348else if (strcmp(arg, "static") == 0)349dtp->dt_linkmode = DT_LINK_STATIC;350else351return (dt_set_errno(dtp, EDT_BADOPTVAL));352353return (0);354}355356/*ARGSUSED*/357static int358dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)359{360if (arg == NULL)361return (dt_set_errno(dtp, EDT_BADOPTVAL));362363if (strcasecmp(arg, "elf") == 0)364dtp->dt_linktype = DT_LTYP_ELF;365else if (strcasecmp(arg, "dof") == 0)366dtp->dt_linktype = DT_LTYP_DOF;367else368return (dt_set_errno(dtp, EDT_BADOPTVAL));369370return (0);371}372373/*ARGSUSED*/374static int375dt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)376{377if (arg == NULL)378return (dt_set_errno(dtp, EDT_BADOPTVAL));379380if (strcmp(arg, "ascii") == 0)381dtp->dt_encoding = DT_ENCODING_ASCII;382else if (strcmp(arg, "utf8") == 0)383dtp->dt_encoding = DT_ENCODING_UTF8;384else385return (dt_set_errno(dtp, EDT_BADOPTVAL));386387return (0);388}389390/*ARGSUSED*/391static int392dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)393{394if (arg == NULL)395return (dt_set_errno(dtp, EDT_BADOPTVAL));396397if (strcmp(arg, "exec") == 0)398dtp->dt_prcmode = DT_PROC_STOP_CREATE;399else if (strcmp(arg, "preinit") == 0)400dtp->dt_prcmode = DT_PROC_STOP_PREINIT;401else if (strcmp(arg, "postinit") == 0)402dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;403else if (strcmp(arg, "main") == 0)404dtp->dt_prcmode = DT_PROC_STOP_MAIN;405else406return (dt_set_errno(dtp, EDT_BADOPTVAL));407408return (0);409}410411/*ARGSUSED*/412static int413dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)414{415int n;416417if (arg == NULL || (n = atoi(arg)) < 0)418return (dt_set_errno(dtp, EDT_BADOPTVAL));419420dtp->dt_procs->dph_lrulim = n;421return (0);422}423424static int425dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)426{427char **p;428char *var;429int nvars;430431/*432* We can't effectively set environment variables from #pragma lines433* since the processes have already been spawned.434*/435if (dtp->dt_pcb != NULL)436return (dt_set_errno(dtp, EDT_BADOPTCTX));437438if (arg == NULL)439return (dt_set_errno(dtp, EDT_BADOPTVAL));440441if (!option && strchr(arg, '=') != NULL)442return (dt_set_errno(dtp, EDT_BADOPTVAL));443444for (nvars = 0, p = dtp->dt_proc_env; *p != NULL; nvars++, p++)445continue;446447for (p = dtp->dt_proc_env; *p != NULL; p++) {448var = strchr(*p, '=');449if (var == NULL)450var = *p + strlen(*p);451if (strncmp(*p, arg, var - *p) == 0) {452dt_free(dtp, *p);453*p = dtp->dt_proc_env[nvars - 1];454dtp->dt_proc_env[nvars - 1] = NULL;455nvars--;456}457}458459if (option) {460if ((var = strdup(arg)) == NULL)461return (dt_set_errno(dtp, EDT_NOMEM));462463nvars++;464if ((p = dt_alloc(dtp, sizeof(char *) * (nvars + 1))) == NULL) {465dt_free(dtp, var);466return (dt_set_errno(dtp, EDT_NOMEM));467}468469bcopy(dtp->dt_proc_env, p, sizeof(char *) * nvars);470dt_free(dtp, dtp->dt_proc_env);471dtp->dt_proc_env = p;472473dtp->dt_proc_env[nvars - 1] = var;474dtp->dt_proc_env[nvars] = NULL;475}476477return (0);478}479480/*ARGSUSED*/481static int482dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)483{484if (arg == NULL)485return (dt_set_errno(dtp, EDT_BADOPTVAL));486487if (dtp->dt_pcb != NULL)488return (dt_set_errno(dtp, EDT_BADOPTCTX));489490if (strcmp(arg, "a") == 0)491dtp->dt_stdcmode = DT_STDC_XA;492else if (strcmp(arg, "c") == 0)493dtp->dt_stdcmode = DT_STDC_XC;494else if (strcmp(arg, "s") == 0)495dtp->dt_stdcmode = DT_STDC_XS;496else if (strcmp(arg, "t") == 0)497dtp->dt_stdcmode = DT_STDC_XT;498else499return (dt_set_errno(dtp, EDT_BADOPTVAL));500501return (0);502}503504/*ARGSUSED*/505static int506dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)507{508dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);509char *path;510511if (arg == NULL)512return (dt_set_errno(dtp, EDT_BADOPTVAL));513514if ((path = strdup(arg)) == NULL)515return (dt_set_errno(dtp, EDT_NOMEM));516517free(dp->dir_path);518dp->dir_path = path;519520return (0);521}522523/*ARGSUSED*/524static int525dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)526{527int m;528529if (arg == NULL || (m = atoi(arg)) <= 0)530return (dt_set_errno(dtp, EDT_BADOPTVAL));531532dtp->dt_treedump = m;533return (0);534}535536/*ARGSUSED*/537static int538dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)539{540int n;541542if (arg == NULL || (n = atoi(arg)) <= 0)543return (dt_set_errno(dtp, EDT_BADOPTVAL));544545dtp->dt_conf.dtc_diftupregs = n;546return (0);547}548549/*ARGSUSED*/550static int551dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)552{553if (arg == NULL)554return (dt_set_errno(dtp, EDT_BADOPTVAL));555556if (strcmp(arg, "dynamic") == 0)557dtp->dt_xlatemode = DT_XL_DYNAMIC;558else if (strcmp(arg, "static") == 0)559dtp->dt_xlatemode = DT_XL_STATIC;560else561return (dt_set_errno(dtp, EDT_BADOPTVAL));562563return (0);564}565566/*ARGSUSED*/567static int568dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)569{570if (arg != NULL)571return (dt_set_errno(dtp, EDT_BADOPTVAL));572573if (dtp->dt_pcb != NULL)574dtp->dt_pcb->pcb_cflags |= option;575else576dtp->dt_cflags |= option;577578return (0);579}580581static int582dt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)583{584if (arg != NULL)585return (dt_set_errno(dtp, EDT_BADOPTVAL));586587dtp->dt_dflags |= option;588return (0);589}590591static int592dt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)593{594if (arg != NULL)595return (dt_set_errno(dtp, EDT_BADOPTVAL));596597if (dtp->dt_pcb != NULL)598dtp->dt_pcb->pcb_cflags &= ~option;599else600dtp->dt_cflags &= ~option;601602return (0);603}604605/*ARGSUSED*/606static int607dt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)608{609dt_version_t v;610611if (arg == NULL)612return (dt_set_errno(dtp, EDT_BADOPTVAL));613614if (dt_version_str2num(arg, &v) == -1)615return (dt_set_errno(dtp, EDT_VERSINVAL));616617if (!dt_version_defined(v))618return (dt_set_errno(dtp, EDT_VERSUNDEF));619620return (dt_reduce(dtp, v));621}622623static int624dt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)625{626char *end;627dtrace_optval_t val = 0;628int i;629630const struct {631char *positive;632char *negative;633} couples[] = {634{ "yes", "no" },635{ "enable", "disable" },636{ "enabled", "disabled" },637{ "true", "false" },638{ "on", "off" },639{ "set", "unset" },640{ NULL }641};642643if (arg != NULL) {644if (arg[0] == '\0') {645val = DTRACEOPT_UNSET;646goto out;647}648649for (i = 0; couples[i].positive != NULL; i++) {650if (strcasecmp(couples[i].positive, arg) == 0) {651val = 1;652goto out;653}654655if (strcasecmp(couples[i].negative, arg) == 0) {656val = DTRACEOPT_UNSET;657goto out;658}659}660661errno = 0;662val = strtoull(arg, &end, 0);663664if (*end != '\0' || errno != 0 || val < 0)665return (dt_set_errno(dtp, EDT_BADOPTVAL));666}667668out:669dtp->dt_options[option] = val;670return (0);671}672673static int674dt_optval_parse(const char *arg, dtrace_optval_t *rval)675{676dtrace_optval_t mul = 1;677size_t len;678char *end;679680len = strlen(arg);681errno = 0;682683switch (arg[len - 1]) {684case 't':685case 'T':686mul *= 1024;687/*FALLTHRU*/688case 'g':689case 'G':690mul *= 1024;691/*FALLTHRU*/692case 'm':693case 'M':694mul *= 1024;695/*FALLTHRU*/696case 'k':697case 'K':698mul *= 1024;699/*FALLTHRU*/700default:701break;702}703704errno = 0;705*rval = strtoull(arg, &end, 0) * mul;706707if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') ||708*rval < 0 || errno != 0)709return (-1);710711return (0);712}713714static int715dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)716{717dtrace_optval_t val = 0;718719if (arg != NULL && dt_optval_parse(arg, &val) != 0)720return (dt_set_errno(dtp, EDT_BADOPTVAL));721722dtp->dt_options[option] = val;723return (0);724}725726static int727dt_opt_oformat(dtrace_hdl_t *dtp, const char *arg, uintptr_t option __unused)728{729if (arg == NULL)730return (dt_set_errno(dtp, EDT_BADOPTVAL));731732if (xo_set_options(NULL, arg) < 0)733return (dt_set_errno(dtp, EDT_BADOPTVAL));734735return (dtrace_oformat_configure(dtp));736}737738static int739dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)740{741char *end;742int i;743dtrace_optval_t mul = 1, val = 0;744745const struct {746char *name;747hrtime_t mul;748} suffix[] = {749{ "ns", NANOSEC / NANOSEC },750{ "nsec", NANOSEC / NANOSEC },751{ "us", NANOSEC / MICROSEC },752{ "usec", NANOSEC / MICROSEC },753{ "ms", NANOSEC / MILLISEC },754{ "msec", NANOSEC / MILLISEC },755{ "s", NANOSEC / SEC },756{ "sec", NANOSEC / SEC },757{ "m", NANOSEC * (hrtime_t)60 },758{ "min", NANOSEC * (hrtime_t)60 },759{ "h", NANOSEC * (hrtime_t)60 * (hrtime_t)60 },760{ "hour", NANOSEC * (hrtime_t)60 * (hrtime_t)60 },761{ "d", NANOSEC * (hrtime_t)(24 * 60 * 60) },762{ "day", NANOSEC * (hrtime_t)(24 * 60 * 60) },763{ "hz", 0 },764{ NULL }765};766767if (arg != NULL) {768errno = 0;769val = strtoull(arg, &end, 0);770771for (i = 0; suffix[i].name != NULL; i++) {772if (strcasecmp(suffix[i].name, end) == 0) {773mul = suffix[i].mul;774break;775}776}777778if (suffix[i].name == NULL && *end != '\0' || val < 0)779return (dt_set_errno(dtp, EDT_BADOPTVAL));780781if (mul == 0) {782/*783* The rate has been specified in frequency-per-second.784*/785if (val != 0)786val = NANOSEC / val;787} else {788val *= mul;789}790}791792dtp->dt_options[option] = val;793return (0);794}795796/*797* When setting the strsize option, set the option in the dt_options array798* using dt_opt_size() as usual, and then update the definition of the CTF799* type for the D intrinsic "string" to be an array of the corresponding size.800* If any errors occur, reset dt_options[option] to its previous value.801*/802static int803dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)804{805dtrace_optval_t val = dtp->dt_options[option];806ctf_file_t *fp = DT_STR_CTFP(dtp);807ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp));808ctf_arinfo_t r;809810if (dt_opt_size(dtp, arg, option) != 0)811return (-1); /* dt_errno is set for us */812813if (dtp->dt_options[option] > UINT_MAX) {814dtp->dt_options[option] = val;815return (dt_set_errno(dtp, EOVERFLOW));816}817818if (ctf_array_info(fp, type, &r) == CTF_ERR) {819dtp->dt_options[option] = val;820dtp->dt_ctferr = ctf_errno(fp);821return (dt_set_errno(dtp, EDT_CTF));822}823824r.ctr_nelems = (uint_t)dtp->dt_options[option];825826if (ctf_set_array(fp, type, &r) == CTF_ERR ||827ctf_update(fp) == CTF_ERR) {828dtp->dt_options[option] = val;829dtp->dt_ctferr = ctf_errno(fp);830return (dt_set_errno(dtp, EDT_CTF));831}832833return (0);834}835836static const struct {837const char *dtbp_name;838int dtbp_policy;839} _dtrace_bufpolicies[] = {840{ "ring", DTRACEOPT_BUFPOLICY_RING },841{ "fill", DTRACEOPT_BUFPOLICY_FILL },842{ "switch", DTRACEOPT_BUFPOLICY_SWITCH },843{ NULL, 0 }844};845846/*ARGSUSED*/847static int848dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)849{850dtrace_optval_t policy = DTRACEOPT_UNSET;851int i;852853if (arg == NULL)854return (dt_set_errno(dtp, EDT_BADOPTVAL));855856for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) {857if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) {858policy = _dtrace_bufpolicies[i].dtbp_policy;859break;860}861}862863if (policy == DTRACEOPT_UNSET)864return (dt_set_errno(dtp, EDT_BADOPTVAL));865866dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy;867868return (0);869}870871static const struct {872const char *dtbr_name;873int dtbr_policy;874} _dtrace_bufresize[] = {875{ "auto", DTRACEOPT_BUFRESIZE_AUTO },876{ "manual", DTRACEOPT_BUFRESIZE_MANUAL },877{ NULL, 0 }878};879880/*ARGSUSED*/881static int882dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)883{884dtrace_optval_t policy = DTRACEOPT_UNSET;885int i;886887if (arg == NULL)888return (dt_set_errno(dtp, EDT_BADOPTVAL));889890for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) {891if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) {892policy = _dtrace_bufresize[i].dtbr_policy;893break;894}895}896897if (policy == DTRACEOPT_UNSET)898return (dt_set_errno(dtp, EDT_BADOPTVAL));899900dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy;901902return (0);903}904905int906dt_options_load(dtrace_hdl_t *dtp)907{908dof_hdr_t hdr, *dof;909dof_sec_t *sec;910size_t offs;911int i, ret;912913/*914* To load the option values, we need to ask the kernel to provide its915* DOF, which we'll sift through to look for OPTDESC sections.916*/917dof = &hdr;918bzero(&hdr, sizeof (dof_hdr_t));919hdr.dofh_loadsz = sizeof (dof_hdr_t);920921#ifdef illumos922if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1)923#else924if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)925#endif926{927ret = dt_set_errno(dtp, errno);928goto out;929}930931if (hdr.dofh_loadsz < sizeof (dof_hdr_t)) {932ret = dt_set_errno(dtp, EINVAL);933goto out;934}935936if ((dof = dt_alloc(dtp, hdr.dofh_loadsz)) == NULL) {937ret = dt_set_errno(dtp, EDT_NOMEM);938goto out;939}940bzero(dof, sizeof (dof_hdr_t));941dof->dofh_loadsz = hdr.dofh_loadsz;942943for (i = 0; i < DTRACEOPT_MAX; i++)944dtp->dt_options[i] = DTRACEOPT_UNSET;945946#ifdef illumos947if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1)948#else949if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)950#endif951{952ret = dt_set_errno(dtp, errno);953goto out;954}955956for (i = 0; i < dof->dofh_secnum; i++) {957sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof +958dof->dofh_secoff + i * dof->dofh_secsize);959960if (sec->dofs_type != DOF_SECT_OPTDESC)961continue;962963break;964}965966for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {967dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t)968((uintptr_t)dof + sec->dofs_offset + offs);969970if (opt->dofo_strtab != DOF_SECIDX_NONE)971continue;972973if (opt->dofo_option >= DTRACEOPT_MAX)974continue;975976dtp->dt_options[opt->dofo_option] = opt->dofo_value;977}978979ret = 0;980out:981if (dof != NULL && dof != &hdr)982dt_free(dtp, dof);983return (ret);984}985986typedef struct dt_option {987const char *o_name;988int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);989uintptr_t o_option;990} dt_option_t;991992/*993* Compile-time options.994*/995static const dt_option_t _dtrace_ctoptions[] = {996{ "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU },997{ "amin", dt_opt_amin },998{ "argref", dt_opt_cflags, DTRACE_C_ARGREF },999{ "core", dt_opt_core },1000{ "cpp", dt_opt_cflags, DTRACE_C_CPP },1001{ "cpphdrs", dt_opt_cpp_hdrs },1002{ "cpppath", dt_opt_cpp_path },1003{ "ctypes", dt_opt_ctypes },1004{ "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG },1005{ "dtypes", dt_opt_dtypes },1006{ "debug", dt_opt_debug },1007{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },1008{ "droptags", dt_opt_droptags },1009{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },1010{ "encoding", dt_opt_encoding },1011{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },1012{ "evaltime", dt_opt_evaltime },1013{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },1014{ "iregs", dt_opt_iregs },1015{ "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF },1016{ "knodefs", dt_opt_cflags, DTRACE_C_KNODEF },1017{ "late", dt_opt_xlate },1018{ "lazyload", dt_opt_lazyload },1019{ "ldpath", dt_opt_ld_path },1020{ "libdir", dt_opt_libdir },1021{ "linkmode", dt_opt_linkmode },1022{ "linktype", dt_opt_linktype },1023{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },1024#ifdef __FreeBSD__1025{ "objcopypath", dt_opt_objcopy_path },1026#endif1027{ "pgmax", dt_opt_pgmax },1028{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },1029{ "setenv", dt_opt_setenv, 1 },1030{ "stdc", dt_opt_stdc },1031{ "strip", dt_opt_dflags, DTRACE_D_STRIP },1032{ "syslibdir", dt_opt_syslibdir },1033{ "tree", dt_opt_tree },1034{ "tregs", dt_opt_tregs },1035{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },1036{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },1037{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },1038{ "unsetenv", dt_opt_setenv, 0 },1039{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },1040{ "version", dt_opt_version },1041{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },1042{ NULL, NULL, 0 }1043};10441045/*1046* Run-time options.1047*/1048static const dt_option_t _dtrace_rtoptions[] = {1049{ "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE },1050{ "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE },1051{ "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY },1052{ "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE },1053{ "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE },1054{ "cpu", dt_opt_runtime, DTRACEOPT_CPU },1055{ "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE },1056{ "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE },1057{ "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON },1058{ "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES },1059{ "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE },1060{ "nspec", dt_opt_runtime, DTRACEOPT_NSPEC },1061{ "oformat", dt_opt_oformat, 0 },1062{ "specsize", dt_opt_size, DTRACEOPT_SPECSIZE },1063{ "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES },1064{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },1065{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },1066{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },1067{ "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },1068{ NULL, NULL, 0 }1069};10701071/*1072* Dynamic run-time options.1073*/1074static const dt_option_t _dtrace_drtoptions[] = {1075{ "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST },1076{ "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK },1077{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },1078{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },1079{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },1080{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },1081{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },1082{ "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM },1083{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },1084{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },1085{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },1086{ "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT },1087{ "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE },1088{ NULL, NULL, 0 }1089};10901091int1092dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val)1093{1094const dt_option_t *op;10951096if (opt == NULL)1097return (dt_set_errno(dtp, EINVAL));10981099/*1100* We only need to search the run-time options -- it's not legal1101* to get the values of compile-time options.1102*/1103for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {1104if (strcmp(op->o_name, opt) == 0) {1105*val = dtp->dt_options[op->o_option];1106return (0);1107}1108}11091110for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {1111if (strcmp(op->o_name, opt) == 0) {1112*val = dtp->dt_options[op->o_option];1113return (0);1114}1115}11161117return (dt_set_errno(dtp, EDT_BADOPTNAME));1118}11191120int1121dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val)1122{1123const dt_option_t *op;11241125if (opt == NULL)1126return (dt_set_errno(dtp, EINVAL));11271128for (op = _dtrace_ctoptions; op->o_name != NULL; op++) {1129if (strcmp(op->o_name, opt) == 0)1130return (op->o_func(dtp, val, op->o_option));1131}11321133for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {1134if (strcmp(op->o_name, opt) == 0)1135return (op->o_func(dtp, val, op->o_option));1136}11371138for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {1139if (strcmp(op->o_name, opt) == 0) {1140/*1141* Only dynamic run-time options may be set while1142* tracing is active.1143*/1144if (dtp->dt_active)1145return (dt_set_errno(dtp, EDT_ACTIVE));11461147return (op->o_func(dtp, val, op->o_option));1148}1149}11501151return (dt_set_errno(dtp, EDT_BADOPTNAME));1152}115311541155