xref: /onnv-gate/usr/src/lib/libdtrace/common/dt_options.c (revision 457:d8f2995c64aa)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <sys/resource.h>
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <strings.h>
330Sstevel@tonic-gate #include <signal.h>
340Sstevel@tonic-gate #include <stdlib.h>
350Sstevel@tonic-gate #include <unistd.h>
360Sstevel@tonic-gate #include <limits.h>
370Sstevel@tonic-gate #include <alloca.h>
380Sstevel@tonic-gate #include <errno.h>
390Sstevel@tonic-gate #include <fcntl.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #include <dt_impl.h>
420Sstevel@tonic-gate #include <dt_string.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate static int
450Sstevel@tonic-gate dt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate 	dt_aggregate_t *agp = &dtp->dt_aggregate;
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	if (arg != NULL)
500Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
510Sstevel@tonic-gate 
520Sstevel@tonic-gate 	agp->dtat_flags |= option;
530Sstevel@tonic-gate 	return (0);
540Sstevel@tonic-gate }
550Sstevel@tonic-gate 
560Sstevel@tonic-gate /*ARGSUSED*/
570Sstevel@tonic-gate static int
580Sstevel@tonic-gate dt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
590Sstevel@tonic-gate {
600Sstevel@tonic-gate 	char str[DTRACE_ATTR2STR_MAX];
610Sstevel@tonic-gate 	dtrace_attribute_t attr;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	if (arg == NULL || dtrace_str2attr(arg, &attr) == -1)
640Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	dt_dprintf("set compiler attribute minimum to %s\n",
670Sstevel@tonic-gate 	    dtrace_attr2str(attr, str, sizeof (str)));
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL) {
700Sstevel@tonic-gate 		dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR;
710Sstevel@tonic-gate 		dtp->dt_pcb->pcb_amin = attr;
720Sstevel@tonic-gate 	} else {
730Sstevel@tonic-gate 		dtp->dt_cflags |= DTRACE_C_EATTR;
740Sstevel@tonic-gate 		dtp->dt_amin = attr;
750Sstevel@tonic-gate 	}
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	return (0);
780Sstevel@tonic-gate }
790Sstevel@tonic-gate 
800Sstevel@tonic-gate static void
810Sstevel@tonic-gate dt_coredump(void)
820Sstevel@tonic-gate {
830Sstevel@tonic-gate 	const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n";
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	struct sigaction act;
860Sstevel@tonic-gate 	struct rlimit lim;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 	(void) write(STDERR_FILENO, msg, sizeof (msg) - 1);
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	act.sa_handler = SIG_DFL;
910Sstevel@tonic-gate 	act.sa_flags = 0;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
940Sstevel@tonic-gate 	(void) sigaction(SIGABRT, &act, NULL);
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	lim.rlim_cur = RLIM_INFINITY;
970Sstevel@tonic-gate 	lim.rlim_max = RLIM_INFINITY;
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	(void) setrlimit(RLIMIT_CORE, &lim);
1000Sstevel@tonic-gate 	abort();
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate /*ARGSUSED*/
1040Sstevel@tonic-gate static int
1050Sstevel@tonic-gate dt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate 	static int enabled = 0;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	if (arg != NULL)
1100Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	if (enabled++ || atexit(dt_coredump) == 0)
1130Sstevel@tonic-gate 		return (0);
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	return (dt_set_errno(dtp, errno));
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate /*ARGSUSED*/
1190Sstevel@tonic-gate static int
1200Sstevel@tonic-gate dt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate 	if (arg != NULL)
1230Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
1260Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	if (dt_cpp_add_arg(dtp, "-H") == NULL)
1290Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	return (0);
1320Sstevel@tonic-gate }
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate /*ARGSUSED*/
1350Sstevel@tonic-gate static int
1360Sstevel@tonic-gate dt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1370Sstevel@tonic-gate {
1380Sstevel@tonic-gate 	char *cpp;
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	if (arg == NULL)
1410Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
1440Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	if ((cpp = strdup(arg)) == NULL)
1470Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);
1500Sstevel@tonic-gate 	free(dtp->dt_cpp_path);
1510Sstevel@tonic-gate 	dtp->dt_cpp_path = cpp;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	return (0);
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate static int
1570Sstevel@tonic-gate dt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1580Sstevel@tonic-gate {
1590Sstevel@tonic-gate 	char *buf;
1600Sstevel@tonic-gate 	size_t len;
1610Sstevel@tonic-gate 	const char *opt = (const char *)option;
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	if (opt == NULL || arg == NULL)
1640Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
1670Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	len = strlen(opt) + strlen(arg) + 1;
1700Sstevel@tonic-gate 	buf = alloca(len);
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	(void) strcpy(buf, opt);
1730Sstevel@tonic-gate 	(void) strcat(buf, arg);
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	if (dt_cpp_add_arg(dtp, buf) == NULL)
1760Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	return (0);
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate /*ARGSUSED*/
1820Sstevel@tonic-gate static int
1830Sstevel@tonic-gate dt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1840Sstevel@tonic-gate {
1850Sstevel@tonic-gate 	int fd;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	if (arg == NULL)
1880Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
1910Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	(void) close(dtp->dt_cdefs_fd);
1940Sstevel@tonic-gate 	dtp->dt_cdefs_fd = fd;
1950Sstevel@tonic-gate 	return (0);
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate /*ARGSUSED*/
1990Sstevel@tonic-gate static int
200*457Sbmc dt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
201*457Sbmc {
202*457Sbmc 	dtp->dt_droptags = 1;
203*457Sbmc 	return (0);
204*457Sbmc }
205*457Sbmc 
206*457Sbmc /*ARGSUSED*/
207*457Sbmc static int
2080Sstevel@tonic-gate dt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2090Sstevel@tonic-gate {
2100Sstevel@tonic-gate 	int fd;
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	if (arg == NULL)
2130Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
2160Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	(void) close(dtp->dt_ddefs_fd);
2190Sstevel@tonic-gate 	dtp->dt_ddefs_fd = fd;
2200Sstevel@tonic-gate 	return (0);
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate /*ARGSUSED*/
2240Sstevel@tonic-gate static int
2250Sstevel@tonic-gate dt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2260Sstevel@tonic-gate {
2270Sstevel@tonic-gate 	if (arg != NULL)
2280Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	_dtrace_debug = 1;
2310Sstevel@tonic-gate 	return (0);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate /*ARGSUSED*/
2350Sstevel@tonic-gate static int
2360Sstevel@tonic-gate dt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate 	int n;
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	if (arg == NULL || (n = atoi(arg)) <= 0)
2410Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	dtp->dt_conf.dtc_difintregs = n;
2440Sstevel@tonic-gate 	return (0);
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate /*ARGSUSED*/
2480Sstevel@tonic-gate static int
2490Sstevel@tonic-gate dt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2500Sstevel@tonic-gate {
2510Sstevel@tonic-gate 	dtp->dt_lazyload = 1;
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	return (0);
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate /*ARGSUSED*/
2570Sstevel@tonic-gate static int
2580Sstevel@tonic-gate dt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2590Sstevel@tonic-gate {
2600Sstevel@tonic-gate 	char *ld;
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	if (arg == NULL)
2630Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
2660Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	if ((ld = strdup(arg)) == NULL)
2690Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	free(dtp->dt_ld_path);
2720Sstevel@tonic-gate 	dtp->dt_ld_path = ld;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	return (0);
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate /*ARGSUSED*/
2780Sstevel@tonic-gate static int
2790Sstevel@tonic-gate dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate 	dt_dirpath_t *dp;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	if (arg == NULL)
2840Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL ||
2870Sstevel@tonic-gate 	    (dp->dir_path = strdup(arg)) == NULL) {
2880Sstevel@tonic-gate 		free(dp);
2890Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
2900Sstevel@tonic-gate 	}
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	dt_list_append(&dtp->dt_lib_path, dp);
2930Sstevel@tonic-gate 	return (0);
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate /*ARGSUSED*/
2970Sstevel@tonic-gate static int
2980Sstevel@tonic-gate dt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2990Sstevel@tonic-gate {
3000Sstevel@tonic-gate 	if (arg == NULL)
3010Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	if (strcmp(arg, "kernel") == 0)
3040Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_KERNEL;
3050Sstevel@tonic-gate 	else if (strcmp(arg, "primary") == 0)
3060Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_PRIMARY;
3070Sstevel@tonic-gate 	else if (strcmp(arg, "dynamic") == 0)
3080Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_DYNAMIC;
3090Sstevel@tonic-gate 	else if (strcmp(arg, "static") == 0)
3100Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_STATIC;
3110Sstevel@tonic-gate 	else
3120Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	return (0);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate /*ARGSUSED*/
3180Sstevel@tonic-gate static int
3190Sstevel@tonic-gate dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3200Sstevel@tonic-gate {
3210Sstevel@tonic-gate 	if (arg == NULL)
3220Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	if (strcasecmp(arg, "elf") == 0)
3250Sstevel@tonic-gate 		dtp->dt_linktype = DT_LTYP_ELF;
3260Sstevel@tonic-gate 	else if (strcasecmp(arg, "dof") == 0)
3270Sstevel@tonic-gate 		dtp->dt_linktype = DT_LTYP_DOF;
3280Sstevel@tonic-gate 	else
3290Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	return (0);
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate /*ARGSUSED*/
3350Sstevel@tonic-gate static int
3360Sstevel@tonic-gate dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3370Sstevel@tonic-gate {
3380Sstevel@tonic-gate 	if (arg == NULL)
3390Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	if (strcmp(arg, "exec") == 0)
3420Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_CREATE;
3430Sstevel@tonic-gate 	else if (strcmp(arg, "preinit") == 0)
3440Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
3450Sstevel@tonic-gate 	else if (strcmp(arg, "postinit") == 0)
3460Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
3470Sstevel@tonic-gate 	else if (strcmp(arg, "main") == 0)
3480Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_MAIN;
3490Sstevel@tonic-gate 	else
3500Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	return (0);
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate /*ARGSUSED*/
3560Sstevel@tonic-gate static int
3570Sstevel@tonic-gate dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3580Sstevel@tonic-gate {
3590Sstevel@tonic-gate 	int n;
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	if (arg == NULL || (n = atoi(arg)) < 0)
3620Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	dtp->dt_procs->dph_lrulim = n;
3650Sstevel@tonic-gate 	return (0);
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate /*ARGSUSED*/
3690Sstevel@tonic-gate static int
3700Sstevel@tonic-gate dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3710Sstevel@tonic-gate {
3720Sstevel@tonic-gate 	if (arg == NULL)
3730Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
3760Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	if (strcmp(arg, "a") == 0)
3790Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XA;
3800Sstevel@tonic-gate 	else if (strcmp(arg, "c") == 0)
3810Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XC;
3820Sstevel@tonic-gate 	else if (strcmp(arg, "s") == 0)
3830Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XS;
3840Sstevel@tonic-gate 	else if (strcmp(arg, "t") == 0)
3850Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XT;
3860Sstevel@tonic-gate 	else
3870Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	return (0);
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate /*ARGSUSED*/
3930Sstevel@tonic-gate static int
3940Sstevel@tonic-gate dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3950Sstevel@tonic-gate {
3960Sstevel@tonic-gate 	dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
3970Sstevel@tonic-gate 	char *path;
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	if (arg == NULL)
4000Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	if ((path = strdup(arg)) == NULL)
4030Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	free(dp->dir_path);
4060Sstevel@tonic-gate 	dp->dir_path = path;
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	return (0);
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate /*ARGSUSED*/
4130Sstevel@tonic-gate static int
4140Sstevel@tonic-gate dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate 	int m;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	if (arg == NULL || (m = atoi(arg)) <= 0)
4190Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	dtp->dt_treedump = m;
4220Sstevel@tonic-gate 	return (0);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate /*ARGSUSED*/
4260Sstevel@tonic-gate static int
4270Sstevel@tonic-gate dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate 	int n;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	if (arg == NULL || (n = atoi(arg)) <= 0)
4320Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 	dtp->dt_conf.dtc_diftupregs = n;
4350Sstevel@tonic-gate 	return (0);
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate 
438265Smws /*ARGSUSED*/
439265Smws static int
440265Smws dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
441265Smws {
442265Smws 	if (arg == NULL)
443265Smws 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
444265Smws 
445265Smws 	if (strcmp(arg, "dynamic") == 0)
446265Smws 		dtp->dt_xlatemode = DT_XL_DYNAMIC;
447265Smws 	else if (strcmp(arg, "static") == 0)
448265Smws 		dtp->dt_xlatemode = DT_XL_STATIC;
449265Smws 	else
450265Smws 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
451265Smws 
452265Smws 	return (0);
453265Smws }
454265Smws 
455265Smws /*ARGSUSED*/
456265Smws 
4570Sstevel@tonic-gate static int
4580Sstevel@tonic-gate dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4590Sstevel@tonic-gate {
4600Sstevel@tonic-gate 	if (arg != NULL)
4610Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
4640Sstevel@tonic-gate 		dtp->dt_pcb->pcb_cflags |= option;
4650Sstevel@tonic-gate 	else
4660Sstevel@tonic-gate 		dtp->dt_cflags |= option;
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	return (0);
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate static int
4720Sstevel@tonic-gate dt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4730Sstevel@tonic-gate {
4740Sstevel@tonic-gate 	if (arg != NULL)
4750Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 	dtp->dt_dflags |= option;
4780Sstevel@tonic-gate 	return (0);
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate static int
4820Sstevel@tonic-gate dt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4830Sstevel@tonic-gate {
4840Sstevel@tonic-gate 	if (arg != NULL)
4850Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
4880Sstevel@tonic-gate 		dtp->dt_pcb->pcb_cflags &= ~option;
4890Sstevel@tonic-gate 	else
4900Sstevel@tonic-gate 		dtp->dt_cflags &= ~option;
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	return (0);
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate /*ARGSUSED*/
4960Sstevel@tonic-gate static int
4970Sstevel@tonic-gate dt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4980Sstevel@tonic-gate {
4990Sstevel@tonic-gate 	dt_version_t v;
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	if (arg == NULL)
5020Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	if (dt_version_str2num(arg, &v) == -1)
5050Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_VERSINVAL));
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	if (!dt_version_defined(v))
5080Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_VERSUNDEF));
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	return (dt_reduce(dtp, v));
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate static int
5140Sstevel@tonic-gate dt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
5150Sstevel@tonic-gate {
5160Sstevel@tonic-gate 	char *end;
5170Sstevel@tonic-gate 	dtrace_optval_t val = 0;
518*457Sbmc 	int i;
519*457Sbmc 
520*457Sbmc 	const struct {
521*457Sbmc 		char *positive;
522*457Sbmc 		char *negative;
523*457Sbmc 	} couples[] = {
524*457Sbmc 		{ "yes",	"no" },
525*457Sbmc 		{ "enable",	"disable" },
526*457Sbmc 		{ "enabled",	"disabled" },
527*457Sbmc 		{ "true",	"false" },
528*457Sbmc 		{ "on",		"off" },
529*457Sbmc 		{ "set",	"unset" },
530*457Sbmc 		{ NULL }
531*457Sbmc 	};
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	if (arg != NULL) {
534*457Sbmc 		if (arg[0] == '\0') {
535*457Sbmc 			val = DTRACEOPT_UNSET;
536*457Sbmc 			goto out;
537*457Sbmc 		}
538*457Sbmc 
539*457Sbmc 		for (i = 0; couples[i].positive != NULL; i++) {
540*457Sbmc 			if (strcasecmp(couples[i].positive, arg) == 0) {
541*457Sbmc 				val = 1;
542*457Sbmc 				goto out;
543*457Sbmc 			}
544*457Sbmc 
545*457Sbmc 			if (strcasecmp(couples[i].negative, arg) == 0) {
546*457Sbmc 				val = DTRACEOPT_UNSET;
547*457Sbmc 				goto out;
548*457Sbmc 			}
549*457Sbmc 		}
550*457Sbmc 
5510Sstevel@tonic-gate 		errno = 0;
5520Sstevel@tonic-gate 		val = strtoull(arg, &end, 0);
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 		if (*end != '\0' || errno != 0 || val < 0)
5550Sstevel@tonic-gate 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
5560Sstevel@tonic-gate 	}
5570Sstevel@tonic-gate 
558*457Sbmc out:
5590Sstevel@tonic-gate 	dtp->dt_options[option] = val;
5600Sstevel@tonic-gate 	return (0);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate static int
5640Sstevel@tonic-gate dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate 	char *end;
5670Sstevel@tonic-gate 	int len;
5680Sstevel@tonic-gate 	dtrace_optval_t mul = 1, val = 0;
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	if (arg != NULL) {
5710Sstevel@tonic-gate 		len = strlen(arg);
5720Sstevel@tonic-gate 		errno = 0;
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 		switch (arg[len - 1]) {
5750Sstevel@tonic-gate 		case 't':
5760Sstevel@tonic-gate 		case 'T':
5770Sstevel@tonic-gate 			mul *= 1024;
5780Sstevel@tonic-gate 			/*FALLTHRU*/
5790Sstevel@tonic-gate 		case 'g':
5800Sstevel@tonic-gate 		case 'G':
5810Sstevel@tonic-gate 			mul *= 1024;
5820Sstevel@tonic-gate 			/*FALLTHRU*/
5830Sstevel@tonic-gate 		case 'm':
5840Sstevel@tonic-gate 		case 'M':
5850Sstevel@tonic-gate 			mul *= 1024;
5860Sstevel@tonic-gate 			/*FALLTHRU*/
5870Sstevel@tonic-gate 		case 'k':
5880Sstevel@tonic-gate 		case 'K':
5890Sstevel@tonic-gate 			mul *= 1024;
5900Sstevel@tonic-gate 			/*FALLTHRU*/
5910Sstevel@tonic-gate 		default:
5920Sstevel@tonic-gate 			break;
5930Sstevel@tonic-gate 		}
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 		val = strtoull(arg, &end, 0) * mul;
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 		if ((mul > 1 && end != &arg[len - 1]) ||
5980Sstevel@tonic-gate 		    (mul == 1 && *end != '\0') || val < 0 ||
5990Sstevel@tonic-gate 		    errno != 0 || val == DTRACEOPT_UNSET)
6000Sstevel@tonic-gate 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
6010Sstevel@tonic-gate 	}
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 	dtp->dt_options[option] = val;
6040Sstevel@tonic-gate 	return (0);
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate static int
6080Sstevel@tonic-gate dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
6090Sstevel@tonic-gate {
6100Sstevel@tonic-gate 	char *end;
6110Sstevel@tonic-gate 	int i;
6120Sstevel@tonic-gate 	dtrace_optval_t mul = 1, val = 0;
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 	const struct {
6150Sstevel@tonic-gate 		char *name;
6160Sstevel@tonic-gate 		hrtime_t mul;
6170Sstevel@tonic-gate 	} suffix[] = {
6180Sstevel@tonic-gate 		{ "ns", 	NANOSEC / NANOSEC },
6190Sstevel@tonic-gate 		{ "nsec",	NANOSEC / NANOSEC },
6200Sstevel@tonic-gate 		{ "us",		NANOSEC / MICROSEC },
6210Sstevel@tonic-gate 		{ "usec",	NANOSEC / MICROSEC },
6220Sstevel@tonic-gate 		{ "ms",		NANOSEC / MILLISEC },
6230Sstevel@tonic-gate 		{ "msec",	NANOSEC / MILLISEC },
6240Sstevel@tonic-gate 		{ "s",		NANOSEC / SEC },
6250Sstevel@tonic-gate 		{ "sec",	NANOSEC / SEC },
6260Sstevel@tonic-gate 		{ "m",		NANOSEC * (hrtime_t)60 },
6270Sstevel@tonic-gate 		{ "min",	NANOSEC * (hrtime_t)60 },
6280Sstevel@tonic-gate 		{ "h",		NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
6290Sstevel@tonic-gate 		{ "hour",	NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
6300Sstevel@tonic-gate 		{ "d",		NANOSEC * (hrtime_t)(24 * 60 * 60) },
6310Sstevel@tonic-gate 		{ "day",	NANOSEC * (hrtime_t)(24 * 60 * 60) },
6320Sstevel@tonic-gate 		{ "hz",		0 },
6330Sstevel@tonic-gate 		{ NULL }
6340Sstevel@tonic-gate 	};
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	if (arg != NULL) {
6370Sstevel@tonic-gate 		errno = 0;
6380Sstevel@tonic-gate 		val = strtoull(arg, &end, 0);
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 		for (i = 0; suffix[i].name != NULL; i++) {
6410Sstevel@tonic-gate 			if (strcasecmp(suffix[i].name, end) == 0) {
6420Sstevel@tonic-gate 				mul = suffix[i].mul;
6430Sstevel@tonic-gate 				break;
6440Sstevel@tonic-gate 			}
6450Sstevel@tonic-gate 		}
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 		if (suffix[i].name == NULL && *end != '\0' || val < 0)
6480Sstevel@tonic-gate 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 		if (mul == 0) {
6510Sstevel@tonic-gate 			/*
6520Sstevel@tonic-gate 			 * The rate has been specified in frequency-per-second.
6530Sstevel@tonic-gate 			 */
6540Sstevel@tonic-gate 			if (val != 0)
6550Sstevel@tonic-gate 				val = NANOSEC / val;
6560Sstevel@tonic-gate 		} else {
6570Sstevel@tonic-gate 			val *= mul;
6580Sstevel@tonic-gate 		}
6590Sstevel@tonic-gate 	}
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	dtp->dt_options[option] = val;
6620Sstevel@tonic-gate 	return (0);
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate /*
6660Sstevel@tonic-gate  * When setting the strsize option, set the option in the dt_options array
6670Sstevel@tonic-gate  * using dt_opt_size() as usual, and then update the definition of the CTF
6680Sstevel@tonic-gate  * type for the D intrinsic "string" to be an array of the corresponding size.
6690Sstevel@tonic-gate  * If any errors occur, reset dt_options[option] to its previous value.
6700Sstevel@tonic-gate  */
6710Sstevel@tonic-gate static int
6720Sstevel@tonic-gate dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
6730Sstevel@tonic-gate {
6740Sstevel@tonic-gate 	dtrace_optval_t val = dtp->dt_options[option];
6750Sstevel@tonic-gate 	ctf_file_t *fp = DT_STR_CTFP(dtp);
6760Sstevel@tonic-gate 	ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp));
6770Sstevel@tonic-gate 	ctf_arinfo_t r;
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	if (dt_opt_size(dtp, arg, option) != 0)
6800Sstevel@tonic-gate 		return (-1); /* dt_errno is set for us */
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	if (dtp->dt_options[option] > UINT_MAX) {
6830Sstevel@tonic-gate 		dtp->dt_options[option] = val;
6840Sstevel@tonic-gate 		return (dt_set_errno(dtp, EOVERFLOW));
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate 	if (ctf_array_info(fp, type, &r) == CTF_ERR) {
6880Sstevel@tonic-gate 		dtp->dt_options[option] = val;
6890Sstevel@tonic-gate 		dtp->dt_ctferr = ctf_errno(fp);
6900Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_CTF));
6910Sstevel@tonic-gate 	}
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	r.ctr_nelems = (uint_t)dtp->dt_options[option];
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 	if (ctf_set_array(fp, type, &r) == CTF_ERR ||
6960Sstevel@tonic-gate 	    ctf_update(fp) == CTF_ERR) {
6970Sstevel@tonic-gate 		dtp->dt_options[option] = val;
6980Sstevel@tonic-gate 		dtp->dt_ctferr = ctf_errno(fp);
6990Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_CTF));
7000Sstevel@tonic-gate 	}
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 	return (0);
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate static const struct {
7060Sstevel@tonic-gate 	const char *dtbp_name;
7070Sstevel@tonic-gate 	int dtbp_policy;
7080Sstevel@tonic-gate } _dtrace_bufpolicies[] = {
7090Sstevel@tonic-gate 	{ "ring", DTRACEOPT_BUFPOLICY_RING },
7100Sstevel@tonic-gate 	{ "fill", DTRACEOPT_BUFPOLICY_FILL },
7110Sstevel@tonic-gate 	{ "switch", DTRACEOPT_BUFPOLICY_SWITCH },
7120Sstevel@tonic-gate 	{ NULL, 0 }
7130Sstevel@tonic-gate };
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate /*ARGSUSED*/
7160Sstevel@tonic-gate static int
7170Sstevel@tonic-gate dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
7180Sstevel@tonic-gate {
7190Sstevel@tonic-gate 	dtrace_optval_t policy = DTRACEOPT_UNSET;
7200Sstevel@tonic-gate 	int i;
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 	if (arg == NULL)
7230Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 	for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) {
7260Sstevel@tonic-gate 		if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) {
7270Sstevel@tonic-gate 			policy = _dtrace_bufpolicies[i].dtbp_policy;
7280Sstevel@tonic-gate 			break;
7290Sstevel@tonic-gate 		}
7300Sstevel@tonic-gate 	}
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	if (policy == DTRACEOPT_UNSET)
7330Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate 	dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy;
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 	return (0);
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate static const struct {
7410Sstevel@tonic-gate 	const char *dtbr_name;
7420Sstevel@tonic-gate 	int dtbr_policy;
7430Sstevel@tonic-gate } _dtrace_bufresize[] = {
7440Sstevel@tonic-gate 	{ "auto", DTRACEOPT_BUFRESIZE_AUTO },
7450Sstevel@tonic-gate 	{ "manual", DTRACEOPT_BUFRESIZE_MANUAL },
7460Sstevel@tonic-gate 	{ NULL, 0 }
7470Sstevel@tonic-gate };
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate /*ARGSUSED*/
7500Sstevel@tonic-gate static int
7510Sstevel@tonic-gate dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
7520Sstevel@tonic-gate {
7530Sstevel@tonic-gate 	dtrace_optval_t policy = DTRACEOPT_UNSET;
7540Sstevel@tonic-gate 	int i;
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 	if (arg == NULL)
7570Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
7580Sstevel@tonic-gate 
7590Sstevel@tonic-gate 	for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) {
7600Sstevel@tonic-gate 		if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) {
7610Sstevel@tonic-gate 			policy = _dtrace_bufresize[i].dtbr_policy;
7620Sstevel@tonic-gate 			break;
7630Sstevel@tonic-gate 		}
7640Sstevel@tonic-gate 	}
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 	if (policy == DTRACEOPT_UNSET)
7670Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 	dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy;
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 	return (0);
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate int
7750Sstevel@tonic-gate dt_options_load(dtrace_hdl_t *dtp)
7760Sstevel@tonic-gate {
7770Sstevel@tonic-gate 	dof_hdr_t hdr, *dof;
7780Sstevel@tonic-gate 	dof_sec_t *sec;
7790Sstevel@tonic-gate 	size_t offs;
7800Sstevel@tonic-gate 	int i;
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 	/*
7830Sstevel@tonic-gate 	 * To load the option values, we need to ask the kernel to provide its
7840Sstevel@tonic-gate 	 * DOF, which we'll sift through to look for OPTDESC sections.
7850Sstevel@tonic-gate 	 */
7860Sstevel@tonic-gate 	bzero(&hdr, sizeof (dof_hdr_t));
7870Sstevel@tonic-gate 	hdr.dofh_loadsz = sizeof (dof_hdr_t);
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1)
7900Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	if (hdr.dofh_loadsz < sizeof (dof_hdr_t))
7930Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	dof = alloca(hdr.dofh_loadsz);
7960Sstevel@tonic-gate 	bzero(dof, sizeof (dof_hdr_t));
7970Sstevel@tonic-gate 	dof->dofh_loadsz = hdr.dofh_loadsz;
7980Sstevel@tonic-gate 
7990Sstevel@tonic-gate 	for (i = 0; i < DTRACEOPT_MAX; i++)
8000Sstevel@tonic-gate 		dtp->dt_options[i] = DTRACEOPT_UNSET;
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1)
8030Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 	for (i = 0; i < dof->dofh_secnum; i++) {
806191Sahl 		sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof +
8070Sstevel@tonic-gate 		    dof->dofh_secoff + i * dof->dofh_secsize);
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 		if (sec->dofs_type != DOF_SECT_OPTDESC)
8100Sstevel@tonic-gate 			continue;
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 		break;
8130Sstevel@tonic-gate 	}
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 	for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {
816191Sahl 		dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t)
817191Sahl 		    ((uintptr_t)dof + sec->dofs_offset + offs);
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate 		if (opt->dofo_strtab != DOF_SECIDX_NONE)
8200Sstevel@tonic-gate 			continue;
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 		if (opt->dofo_option >= DTRACEOPT_MAX)
8230Sstevel@tonic-gate 			continue;
8240Sstevel@tonic-gate 
8250Sstevel@tonic-gate 		dtp->dt_options[opt->dofo_option] = opt->dofo_value;
8260Sstevel@tonic-gate 	}
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 	return (0);
8290Sstevel@tonic-gate }
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate typedef struct dt_option {
8320Sstevel@tonic-gate 	const char *o_name;
8330Sstevel@tonic-gate 	int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
8340Sstevel@tonic-gate 	uintptr_t o_option;
8350Sstevel@tonic-gate } dt_option_t;
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate /*
8380Sstevel@tonic-gate  * Compile-time options.
8390Sstevel@tonic-gate  */
8400Sstevel@tonic-gate static const dt_option_t _dtrace_ctoptions[] = {
8410Sstevel@tonic-gate 	{ "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU },
8420Sstevel@tonic-gate 	{ "amin", dt_opt_amin },
8430Sstevel@tonic-gate 	{ "argref", dt_opt_cflags, DTRACE_C_ARGREF },
8440Sstevel@tonic-gate 	{ "core", dt_opt_core },
8450Sstevel@tonic-gate 	{ "cpp", dt_opt_cflags, DTRACE_C_CPP },
8460Sstevel@tonic-gate 	{ "cpphdrs", dt_opt_cpp_hdrs },
8470Sstevel@tonic-gate 	{ "cpppath", dt_opt_cpp_path },
8480Sstevel@tonic-gate 	{ "ctypes", dt_opt_ctypes },
8490Sstevel@tonic-gate 	{ "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG },
8500Sstevel@tonic-gate 	{ "dtypes", dt_opt_dtypes },
8510Sstevel@tonic-gate 	{ "debug", dt_opt_debug },
8520Sstevel@tonic-gate 	{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
853*457Sbmc 	{ "droptags", dt_opt_droptags },
8540Sstevel@tonic-gate 	{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
8550Sstevel@tonic-gate 	{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
8560Sstevel@tonic-gate 	{ "evaltime", dt_opt_evaltime },
8570Sstevel@tonic-gate 	{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
8580Sstevel@tonic-gate 	{ "iregs", dt_opt_iregs },
8590Sstevel@tonic-gate 	{ "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF },
8600Sstevel@tonic-gate 	{ "knodefs", dt_opt_cflags, DTRACE_C_KNODEF },
861265Smws 	{ "late", dt_opt_xlate },
8620Sstevel@tonic-gate 	{ "lazyload", dt_opt_lazyload },
8630Sstevel@tonic-gate 	{ "ldpath", dt_opt_ld_path },
8640Sstevel@tonic-gate 	{ "libdir", dt_opt_libdir },
8650Sstevel@tonic-gate 	{ "linkmode", dt_opt_linkmode },
8660Sstevel@tonic-gate 	{ "linktype", dt_opt_linktype },
8670Sstevel@tonic-gate 	{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
8680Sstevel@tonic-gate 	{ "pgmax", dt_opt_pgmax },
8690Sstevel@tonic-gate 	{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
8700Sstevel@tonic-gate 	{ "stdc", dt_opt_stdc },
8710Sstevel@tonic-gate 	{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
8720Sstevel@tonic-gate 	{ "syslibdir", dt_opt_syslibdir },
8730Sstevel@tonic-gate 	{ "tree", dt_opt_tree },
8740Sstevel@tonic-gate 	{ "tregs", dt_opt_tregs },
8750Sstevel@tonic-gate 	{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
8760Sstevel@tonic-gate 	{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
8770Sstevel@tonic-gate 	{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
8780Sstevel@tonic-gate 	{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
8790Sstevel@tonic-gate 	{ "version", dt_opt_version },
8800Sstevel@tonic-gate 	{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
8810Sstevel@tonic-gate 	{ NULL }
8820Sstevel@tonic-gate };
8830Sstevel@tonic-gate 
8840Sstevel@tonic-gate /*
8850Sstevel@tonic-gate  * Run-time options.
8860Sstevel@tonic-gate  */
8870Sstevel@tonic-gate static const dt_option_t _dtrace_rtoptions[] = {
8880Sstevel@tonic-gate 	{ "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE },
8890Sstevel@tonic-gate 	{ "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE },
8900Sstevel@tonic-gate 	{ "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY },
8910Sstevel@tonic-gate 	{ "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE },
8920Sstevel@tonic-gate 	{ "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE },
8930Sstevel@tonic-gate 	{ "cpu", dt_opt_runtime, DTRACEOPT_CPU },
8940Sstevel@tonic-gate 	{ "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE },
8950Sstevel@tonic-gate 	{ "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE },
8960Sstevel@tonic-gate 	{ "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON },
8970Sstevel@tonic-gate 	{ "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES },
898*457Sbmc 	{ "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE },
8990Sstevel@tonic-gate 	{ "nspec", dt_opt_runtime, DTRACEOPT_NSPEC },
900*457Sbmc 	{ "specsize", dt_opt_size, DTRACEOPT_SPECSIZE },
901*457Sbmc 	{ "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES },
902*457Sbmc 	{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
903*457Sbmc 	{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
904*457Sbmc 	{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
905*457Sbmc 	{ NULL }
906*457Sbmc };
907*457Sbmc 
908*457Sbmc /*
909*457Sbmc  * Dynamic run-time options.
910*457Sbmc  */
911*457Sbmc static const dt_option_t _dtrace_drtoptions[] = {
912*457Sbmc 	{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
913*457Sbmc 	{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
9140Sstevel@tonic-gate 	{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
9150Sstevel@tonic-gate 	{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
9160Sstevel@tonic-gate 	{ "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT },
9170Sstevel@tonic-gate 	{ "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE },
9180Sstevel@tonic-gate };
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate int
9210Sstevel@tonic-gate dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val)
9220Sstevel@tonic-gate {
9230Sstevel@tonic-gate 	const dt_option_t *op;
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	if (opt == NULL)
9260Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	/*
9290Sstevel@tonic-gate 	 * We only need to search the run-time options -- it's not legal
9300Sstevel@tonic-gate 	 * to get the values of compile-time options.
9310Sstevel@tonic-gate 	 */
9320Sstevel@tonic-gate 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
9330Sstevel@tonic-gate 		if (strcmp(op->o_name, opt) == 0) {
9340Sstevel@tonic-gate 			*val = dtp->dt_options[op->o_option];
9350Sstevel@tonic-gate 			return (0);
9360Sstevel@tonic-gate 		}
9370Sstevel@tonic-gate 	}
9380Sstevel@tonic-gate 
939*457Sbmc 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
940*457Sbmc 		if (strcmp(op->o_name, opt) == 0) {
941*457Sbmc 			*val = dtp->dt_options[op->o_option];
942*457Sbmc 			return (0);
943*457Sbmc 		}
944*457Sbmc 	}
945*457Sbmc 
9460Sstevel@tonic-gate 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
9470Sstevel@tonic-gate }
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate int
9500Sstevel@tonic-gate dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val)
9510Sstevel@tonic-gate {
9520Sstevel@tonic-gate 	const dt_option_t *op;
9530Sstevel@tonic-gate 
9540Sstevel@tonic-gate 	if (opt == NULL)
9550Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	for (op = _dtrace_ctoptions; op->o_name != NULL; op++) {
9580Sstevel@tonic-gate 		if (strcmp(op->o_name, opt) == 0)
9590Sstevel@tonic-gate 			return (op->o_func(dtp, val, op->o_option));
9600Sstevel@tonic-gate 	}
9610Sstevel@tonic-gate 
962*457Sbmc 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
963*457Sbmc 		if (strcmp(op->o_name, opt) == 0)
964*457Sbmc 			return (op->o_func(dtp, val, op->o_option));
965*457Sbmc 	}
966*457Sbmc 
9670Sstevel@tonic-gate 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
9680Sstevel@tonic-gate 		if (strcmp(op->o_name, opt) == 0) {
9690Sstevel@tonic-gate 			/*
970*457Sbmc 			 * Only dynamic run-time options may be set while
9710Sstevel@tonic-gate 			 * tracing is active.
9720Sstevel@tonic-gate 			 */
9730Sstevel@tonic-gate 			if (dtp->dt_active)
9740Sstevel@tonic-gate 				return (dt_set_errno(dtp, EDT_ACTIVE));
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate 			return (op->o_func(dtp, val, op->o_option));
9770Sstevel@tonic-gate 		}
9780Sstevel@tonic-gate 	}
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
9810Sstevel@tonic-gate }
982