xref: /onnv-gate/usr/src/lib/libdtrace/common/dt_options.c (revision 3944:75371f172291)
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
5*3944Sahl  * Common Development and Distribution License (the "License").
6*3944Sahl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*3944Sahl 
220Sstevel@tonic-gate /*
23*3944Sahl  * Copyright 2007 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 
29*3944Sahl #include <sys/resource.h>
30*3944Sahl #include <sys/mman.h>
310Sstevel@tonic-gate #include <sys/types.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <strings.h>
340Sstevel@tonic-gate #include <signal.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <unistd.h>
370Sstevel@tonic-gate #include <limits.h>
380Sstevel@tonic-gate #include <alloca.h>
390Sstevel@tonic-gate #include <errno.h>
400Sstevel@tonic-gate #include <fcntl.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include <dt_impl.h>
430Sstevel@tonic-gate #include <dt_string.h>
440Sstevel@tonic-gate 
450Sstevel@tonic-gate static int
dt_opt_agg(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)460Sstevel@tonic-gate dt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
470Sstevel@tonic-gate {
480Sstevel@tonic-gate 	dt_aggregate_t *agp = &dtp->dt_aggregate;
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 	if (arg != NULL)
510Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
520Sstevel@tonic-gate 
530Sstevel@tonic-gate 	agp->dtat_flags |= option;
540Sstevel@tonic-gate 	return (0);
550Sstevel@tonic-gate }
560Sstevel@tonic-gate 
570Sstevel@tonic-gate /*ARGSUSED*/
580Sstevel@tonic-gate static int
dt_opt_amin(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)590Sstevel@tonic-gate dt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	char str[DTRACE_ATTR2STR_MAX];
620Sstevel@tonic-gate 	dtrace_attribute_t attr;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	if (arg == NULL || dtrace_str2attr(arg, &attr) == -1)
650Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 	dt_dprintf("set compiler attribute minimum to %s\n",
680Sstevel@tonic-gate 	    dtrace_attr2str(attr, str, sizeof (str)));
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL) {
710Sstevel@tonic-gate 		dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR;
720Sstevel@tonic-gate 		dtp->dt_pcb->pcb_amin = attr;
730Sstevel@tonic-gate 	} else {
740Sstevel@tonic-gate 		dtp->dt_cflags |= DTRACE_C_EATTR;
750Sstevel@tonic-gate 		dtp->dt_amin = attr;
760Sstevel@tonic-gate 	}
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	return (0);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate 
810Sstevel@tonic-gate static void
dt_coredump(void)820Sstevel@tonic-gate dt_coredump(void)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate 	const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n";
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	struct sigaction act;
870Sstevel@tonic-gate 	struct rlimit lim;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	(void) write(STDERR_FILENO, msg, sizeof (msg) - 1);
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	act.sa_handler = SIG_DFL;
920Sstevel@tonic-gate 	act.sa_flags = 0;
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
950Sstevel@tonic-gate 	(void) sigaction(SIGABRT, &act, NULL);
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	lim.rlim_cur = RLIM_INFINITY;
980Sstevel@tonic-gate 	lim.rlim_max = RLIM_INFINITY;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	(void) setrlimit(RLIMIT_CORE, &lim);
1010Sstevel@tonic-gate 	abort();
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate /*ARGSUSED*/
1050Sstevel@tonic-gate static int
dt_opt_core(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1060Sstevel@tonic-gate dt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate 	static int enabled = 0;
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	if (arg != NULL)
1110Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	if (enabled++ || atexit(dt_coredump) == 0)
1140Sstevel@tonic-gate 		return (0);
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	return (dt_set_errno(dtp, errno));
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate /*ARGSUSED*/
1200Sstevel@tonic-gate static int
dt_opt_cpp_hdrs(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1210Sstevel@tonic-gate dt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate 	if (arg != NULL)
1240Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
1270Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	if (dt_cpp_add_arg(dtp, "-H") == NULL)
1300Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	return (0);
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate /*ARGSUSED*/
1360Sstevel@tonic-gate static int
dt_opt_cpp_path(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1370Sstevel@tonic-gate dt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate 	char *cpp;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	if (arg == NULL)
1420Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
1450Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	if ((cpp = strdup(arg)) == NULL)
1480Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);
1510Sstevel@tonic-gate 	free(dtp->dt_cpp_path);
1520Sstevel@tonic-gate 	dtp->dt_cpp_path = cpp;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	return (0);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate static int
dt_opt_cpp_opts(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1580Sstevel@tonic-gate dt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate 	char *buf;
1610Sstevel@tonic-gate 	size_t len;
1620Sstevel@tonic-gate 	const char *opt = (const char *)option;
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	if (opt == NULL || arg == NULL)
1650Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
1680Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	len = strlen(opt) + strlen(arg) + 1;
1710Sstevel@tonic-gate 	buf = alloca(len);
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	(void) strcpy(buf, opt);
1740Sstevel@tonic-gate 	(void) strcat(buf, arg);
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	if (dt_cpp_add_arg(dtp, buf) == NULL)
1770Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	return (0);
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate /*ARGSUSED*/
1830Sstevel@tonic-gate static int
dt_opt_ctypes(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1840Sstevel@tonic-gate dt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate 	int fd;
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	if (arg == NULL)
1890Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
1920Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	(void) close(dtp->dt_cdefs_fd);
1950Sstevel@tonic-gate 	dtp->dt_cdefs_fd = fd;
1960Sstevel@tonic-gate 	return (0);
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate /*ARGSUSED*/
2000Sstevel@tonic-gate static int
dt_opt_droptags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)201457Sbmc dt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
202457Sbmc {
203457Sbmc 	dtp->dt_droptags = 1;
204457Sbmc 	return (0);
205457Sbmc }
206457Sbmc 
207457Sbmc /*ARGSUSED*/
208457Sbmc static int
dt_opt_dtypes(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2090Sstevel@tonic-gate dt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2100Sstevel@tonic-gate {
2110Sstevel@tonic-gate 	int fd;
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	if (arg == NULL)
2140Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
2170Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	(void) close(dtp->dt_ddefs_fd);
2200Sstevel@tonic-gate 	dtp->dt_ddefs_fd = fd;
2210Sstevel@tonic-gate 	return (0);
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate /*ARGSUSED*/
2250Sstevel@tonic-gate static int
dt_opt_debug(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2260Sstevel@tonic-gate dt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2270Sstevel@tonic-gate {
2280Sstevel@tonic-gate 	if (arg != NULL)
2290Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	_dtrace_debug = 1;
2320Sstevel@tonic-gate 	return (0);
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate /*ARGSUSED*/
2360Sstevel@tonic-gate static int
dt_opt_iregs(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2370Sstevel@tonic-gate dt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate 	int n;
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	if (arg == NULL || (n = atoi(arg)) <= 0)
2420Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	dtp->dt_conf.dtc_difintregs = n;
2450Sstevel@tonic-gate 	return (0);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate /*ARGSUSED*/
2490Sstevel@tonic-gate static int
dt_opt_lazyload(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2500Sstevel@tonic-gate dt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate 	dtp->dt_lazyload = 1;
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	return (0);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate /*ARGSUSED*/
2580Sstevel@tonic-gate static int
dt_opt_ld_path(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2590Sstevel@tonic-gate dt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2600Sstevel@tonic-gate {
2610Sstevel@tonic-gate 	char *ld;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	if (arg == NULL)
2640Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
2670Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	if ((ld = strdup(arg)) == NULL)
2700Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	free(dtp->dt_ld_path);
2730Sstevel@tonic-gate 	dtp->dt_ld_path = ld;
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	return (0);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate /*ARGSUSED*/
2790Sstevel@tonic-gate static int
dt_opt_libdir(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2800Sstevel@tonic-gate dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2810Sstevel@tonic-gate {
2820Sstevel@tonic-gate 	dt_dirpath_t *dp;
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	if (arg == NULL)
2850Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL ||
2880Sstevel@tonic-gate 	    (dp->dir_path = strdup(arg)) == NULL) {
2890Sstevel@tonic-gate 		free(dp);
2900Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
2910Sstevel@tonic-gate 	}
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	dt_list_append(&dtp->dt_lib_path, dp);
2940Sstevel@tonic-gate 	return (0);
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate /*ARGSUSED*/
2980Sstevel@tonic-gate static int
dt_opt_linkmode(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2990Sstevel@tonic-gate dt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3000Sstevel@tonic-gate {
3010Sstevel@tonic-gate 	if (arg == NULL)
3020Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	if (strcmp(arg, "kernel") == 0)
3050Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_KERNEL;
3060Sstevel@tonic-gate 	else if (strcmp(arg, "primary") == 0)
3070Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_PRIMARY;
3080Sstevel@tonic-gate 	else if (strcmp(arg, "dynamic") == 0)
3090Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_DYNAMIC;
3100Sstevel@tonic-gate 	else if (strcmp(arg, "static") == 0)
3110Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_STATIC;
3120Sstevel@tonic-gate 	else
3130Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	return (0);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate /*ARGSUSED*/
3190Sstevel@tonic-gate static int
dt_opt_linktype(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)3200Sstevel@tonic-gate dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3210Sstevel@tonic-gate {
3220Sstevel@tonic-gate 	if (arg == NULL)
3230Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	if (strcasecmp(arg, "elf") == 0)
3260Sstevel@tonic-gate 		dtp->dt_linktype = DT_LTYP_ELF;
3270Sstevel@tonic-gate 	else if (strcasecmp(arg, "dof") == 0)
3280Sstevel@tonic-gate 		dtp->dt_linktype = DT_LTYP_DOF;
3290Sstevel@tonic-gate 	else
3300Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	return (0);
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate /*ARGSUSED*/
3360Sstevel@tonic-gate static int
dt_opt_evaltime(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)3370Sstevel@tonic-gate dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3380Sstevel@tonic-gate {
3390Sstevel@tonic-gate 	if (arg == NULL)
3400Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	if (strcmp(arg, "exec") == 0)
3430Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_CREATE;
3440Sstevel@tonic-gate 	else if (strcmp(arg, "preinit") == 0)
3450Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
3460Sstevel@tonic-gate 	else if (strcmp(arg, "postinit") == 0)
3470Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
3480Sstevel@tonic-gate 	else if (strcmp(arg, "main") == 0)
3490Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_MAIN;
3500Sstevel@tonic-gate 	else
3510Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	return (0);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate /*ARGSUSED*/
3570Sstevel@tonic-gate static int
dt_opt_pgmax(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)3580Sstevel@tonic-gate dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3590Sstevel@tonic-gate {
3600Sstevel@tonic-gate 	int n;
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	if (arg == NULL || (n = atoi(arg)) < 0)
3630Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	dtp->dt_procs->dph_lrulim = n;
3660Sstevel@tonic-gate 	return (0);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate /*ARGSUSED*/
3700Sstevel@tonic-gate static int
dt_opt_stdc(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)3710Sstevel@tonic-gate dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3720Sstevel@tonic-gate {
3730Sstevel@tonic-gate 	if (arg == NULL)
3740Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
3770Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	if (strcmp(arg, "a") == 0)
3800Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XA;
3810Sstevel@tonic-gate 	else if (strcmp(arg, "c") == 0)
3820Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XC;
3830Sstevel@tonic-gate 	else if (strcmp(arg, "s") == 0)
3840Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XS;
3850Sstevel@tonic-gate 	else if (strcmp(arg, "t") == 0)
3860Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XT;
3870Sstevel@tonic-gate 	else
3880Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	return (0);
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate /*ARGSUSED*/
3940Sstevel@tonic-gate static int
dt_opt_syslibdir(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)3950Sstevel@tonic-gate dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate 	dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
3980Sstevel@tonic-gate 	char *path;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	if (arg == NULL)
4010Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	if ((path = strdup(arg)) == NULL)
4040Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	free(dp->dir_path);
4070Sstevel@tonic-gate 	dp->dir_path = path;
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	return (0);
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate /*ARGSUSED*/
4140Sstevel@tonic-gate static int
dt_opt_tree(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)4150Sstevel@tonic-gate dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate 	int m;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	if (arg == NULL || (m = atoi(arg)) <= 0)
4200Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	dtp->dt_treedump = m;
4230Sstevel@tonic-gate 	return (0);
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate /*ARGSUSED*/
4270Sstevel@tonic-gate static int
dt_opt_tregs(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)4280Sstevel@tonic-gate dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4290Sstevel@tonic-gate {
4300Sstevel@tonic-gate 	int n;
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	if (arg == NULL || (n = atoi(arg)) <= 0)
4330Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	dtp->dt_conf.dtc_diftupregs = n;
4360Sstevel@tonic-gate 	return (0);
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate 
439265Smws /*ARGSUSED*/
440265Smws static int
dt_opt_xlate(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)441265Smws dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
442265Smws {
443265Smws 	if (arg == NULL)
444265Smws 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
445265Smws 
446265Smws 	if (strcmp(arg, "dynamic") == 0)
447265Smws 		dtp->dt_xlatemode = DT_XL_DYNAMIC;
448265Smws 	else if (strcmp(arg, "static") == 0)
449265Smws 		dtp->dt_xlatemode = DT_XL_STATIC;
450265Smws 	else
451265Smws 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
452265Smws 
453265Smws 	return (0);
454265Smws }
455265Smws 
456265Smws /*ARGSUSED*/
4570Sstevel@tonic-gate static int
dt_opt_cflags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)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
dt_opt_dflags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)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
dt_opt_invcflags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)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
dt_opt_version(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)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
dt_opt_runtime(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)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;
518457Sbmc 	int i;
519457Sbmc 
520457Sbmc 	const struct {
521457Sbmc 		char *positive;
522457Sbmc 		char *negative;
523457Sbmc 	} couples[] = {
524457Sbmc 		{ "yes",	"no" },
525457Sbmc 		{ "enable",	"disable" },
526457Sbmc 		{ "enabled",	"disabled" },
527457Sbmc 		{ "true",	"false" },
528457Sbmc 		{ "on",		"off" },
529457Sbmc 		{ "set",	"unset" },
530457Sbmc 		{ NULL }
531457Sbmc 	};
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	if (arg != NULL) {
534457Sbmc 		if (arg[0] == '\0') {
535457Sbmc 			val = DTRACEOPT_UNSET;
536457Sbmc 			goto out;
537457Sbmc 		}
538457Sbmc 
539457Sbmc 		for (i = 0; couples[i].positive != NULL; i++) {
540457Sbmc 			if (strcasecmp(couples[i].positive, arg) == 0) {
541457Sbmc 				val = 1;
542457Sbmc 				goto out;
543457Sbmc 			}
544457Sbmc 
545457Sbmc 			if (strcasecmp(couples[i].negative, arg) == 0) {
546457Sbmc 				val = DTRACEOPT_UNSET;
547457Sbmc 				goto out;
548457Sbmc 			}
549457Sbmc 		}
550457Sbmc 
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 
558457Sbmc 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
dt_optval_parse(const char * arg,dtrace_optval_t * rval)564*3944Sahl dt_optval_parse(const char *arg, dtrace_optval_t *rval)
565*3944Sahl {
566*3944Sahl 	dtrace_optval_t mul = 1;
567*3944Sahl 	size_t len;
568*3944Sahl 	char *end;
569*3944Sahl 
570*3944Sahl 	len = strlen(arg);
571*3944Sahl 	errno = 0;
572*3944Sahl 
573*3944Sahl 	switch (arg[len - 1]) {
574*3944Sahl 	case 't':
575*3944Sahl 	case 'T':
576*3944Sahl 		mul *= 1024;
577*3944Sahl 		/*FALLTHRU*/
578*3944Sahl 	case 'g':
579*3944Sahl 	case 'G':
580*3944Sahl 		mul *= 1024;
581*3944Sahl 		/*FALLTHRU*/
582*3944Sahl 	case 'm':
583*3944Sahl 	case 'M':
584*3944Sahl 		mul *= 1024;
585*3944Sahl 		/*FALLTHRU*/
586*3944Sahl 	case 'k':
587*3944Sahl 	case 'K':
588*3944Sahl 		mul *= 1024;
589*3944Sahl 		/*FALLTHRU*/
590*3944Sahl 	default:
591*3944Sahl 		break;
592*3944Sahl 	}
593*3944Sahl 
594*3944Sahl 	errno = 0;
595*3944Sahl 	*rval = strtoull(arg, &end, 0) * mul;
596*3944Sahl 
597*3944Sahl 	if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') ||
598*3944Sahl 	    *rval < 0 || errno != 0)
599*3944Sahl 		return (-1);
600*3944Sahl 
601*3944Sahl 	return (0);
602*3944Sahl }
603*3944Sahl 
604*3944Sahl static int
dt_opt_size(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)6050Sstevel@tonic-gate dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
6060Sstevel@tonic-gate {
607*3944Sahl 	dtrace_optval_t val = 0;
6080Sstevel@tonic-gate 
609*3944Sahl 	if (arg != NULL && dt_optval_parse(arg, &val) != 0)
610*3944Sahl 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	dtp->dt_options[option] = val;
6130Sstevel@tonic-gate 	return (0);
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate static int
dt_opt_rate(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)6170Sstevel@tonic-gate dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
6180Sstevel@tonic-gate {
6190Sstevel@tonic-gate 	char *end;
6200Sstevel@tonic-gate 	int i;
6210Sstevel@tonic-gate 	dtrace_optval_t mul = 1, val = 0;
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	const struct {
6240Sstevel@tonic-gate 		char *name;
6250Sstevel@tonic-gate 		hrtime_t mul;
6260Sstevel@tonic-gate 	} suffix[] = {
6270Sstevel@tonic-gate 		{ "ns", 	NANOSEC / NANOSEC },
6280Sstevel@tonic-gate 		{ "nsec",	NANOSEC / NANOSEC },
6290Sstevel@tonic-gate 		{ "us",		NANOSEC / MICROSEC },
6300Sstevel@tonic-gate 		{ "usec",	NANOSEC / MICROSEC },
6310Sstevel@tonic-gate 		{ "ms",		NANOSEC / MILLISEC },
6320Sstevel@tonic-gate 		{ "msec",	NANOSEC / MILLISEC },
6330Sstevel@tonic-gate 		{ "s",		NANOSEC / SEC },
6340Sstevel@tonic-gate 		{ "sec",	NANOSEC / SEC },
6350Sstevel@tonic-gate 		{ "m",		NANOSEC * (hrtime_t)60 },
6360Sstevel@tonic-gate 		{ "min",	NANOSEC * (hrtime_t)60 },
6370Sstevel@tonic-gate 		{ "h",		NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
6380Sstevel@tonic-gate 		{ "hour",	NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
6390Sstevel@tonic-gate 		{ "d",		NANOSEC * (hrtime_t)(24 * 60 * 60) },
6400Sstevel@tonic-gate 		{ "day",	NANOSEC * (hrtime_t)(24 * 60 * 60) },
6410Sstevel@tonic-gate 		{ "hz",		0 },
6420Sstevel@tonic-gate 		{ NULL }
6430Sstevel@tonic-gate 	};
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	if (arg != NULL) {
6460Sstevel@tonic-gate 		errno = 0;
6470Sstevel@tonic-gate 		val = strtoull(arg, &end, 0);
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 		for (i = 0; suffix[i].name != NULL; i++) {
6500Sstevel@tonic-gate 			if (strcasecmp(suffix[i].name, end) == 0) {
6510Sstevel@tonic-gate 				mul = suffix[i].mul;
6520Sstevel@tonic-gate 				break;
6530Sstevel@tonic-gate 			}
6540Sstevel@tonic-gate 		}
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 		if (suffix[i].name == NULL && *end != '\0' || val < 0)
6570Sstevel@tonic-gate 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 		if (mul == 0) {
6600Sstevel@tonic-gate 			/*
6610Sstevel@tonic-gate 			 * The rate has been specified in frequency-per-second.
6620Sstevel@tonic-gate 			 */
6630Sstevel@tonic-gate 			if (val != 0)
6640Sstevel@tonic-gate 				val = NANOSEC / val;
6650Sstevel@tonic-gate 		} else {
6660Sstevel@tonic-gate 			val *= mul;
6670Sstevel@tonic-gate 		}
6680Sstevel@tonic-gate 	}
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 	dtp->dt_options[option] = val;
6710Sstevel@tonic-gate 	return (0);
6720Sstevel@tonic-gate }
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate /*
6750Sstevel@tonic-gate  * When setting the strsize option, set the option in the dt_options array
6760Sstevel@tonic-gate  * using dt_opt_size() as usual, and then update the definition of the CTF
6770Sstevel@tonic-gate  * type for the D intrinsic "string" to be an array of the corresponding size.
6780Sstevel@tonic-gate  * If any errors occur, reset dt_options[option] to its previous value.
6790Sstevel@tonic-gate  */
6800Sstevel@tonic-gate static int
dt_opt_strsize(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)6810Sstevel@tonic-gate dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
6820Sstevel@tonic-gate {
6830Sstevel@tonic-gate 	dtrace_optval_t val = dtp->dt_options[option];
6840Sstevel@tonic-gate 	ctf_file_t *fp = DT_STR_CTFP(dtp);
6850Sstevel@tonic-gate 	ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp));
6860Sstevel@tonic-gate 	ctf_arinfo_t r;
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 	if (dt_opt_size(dtp, arg, option) != 0)
6890Sstevel@tonic-gate 		return (-1); /* dt_errno is set for us */
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate 	if (dtp->dt_options[option] > UINT_MAX) {
6920Sstevel@tonic-gate 		dtp->dt_options[option] = val;
6930Sstevel@tonic-gate 		return (dt_set_errno(dtp, EOVERFLOW));
6940Sstevel@tonic-gate 	}
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	if (ctf_array_info(fp, type, &r) == 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 	r.ctr_nelems = (uint_t)dtp->dt_options[option];
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate 	if (ctf_set_array(fp, type, &r) == CTF_ERR ||
7050Sstevel@tonic-gate 	    ctf_update(fp) == CTF_ERR) {
7060Sstevel@tonic-gate 		dtp->dt_options[option] = val;
7070Sstevel@tonic-gate 		dtp->dt_ctferr = ctf_errno(fp);
7080Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_CTF));
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 	return (0);
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate static const struct {
7150Sstevel@tonic-gate 	const char *dtbp_name;
7160Sstevel@tonic-gate 	int dtbp_policy;
7170Sstevel@tonic-gate } _dtrace_bufpolicies[] = {
7180Sstevel@tonic-gate 	{ "ring", DTRACEOPT_BUFPOLICY_RING },
7190Sstevel@tonic-gate 	{ "fill", DTRACEOPT_BUFPOLICY_FILL },
7200Sstevel@tonic-gate 	{ "switch", DTRACEOPT_BUFPOLICY_SWITCH },
7210Sstevel@tonic-gate 	{ NULL, 0 }
7220Sstevel@tonic-gate };
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate /*ARGSUSED*/
7250Sstevel@tonic-gate static int
dt_opt_bufpolicy(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)7260Sstevel@tonic-gate dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
7270Sstevel@tonic-gate {
7280Sstevel@tonic-gate 	dtrace_optval_t policy = DTRACEOPT_UNSET;
7290Sstevel@tonic-gate 	int i;
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 	if (arg == NULL)
7320Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) {
7350Sstevel@tonic-gate 		if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) {
7360Sstevel@tonic-gate 			policy = _dtrace_bufpolicies[i].dtbp_policy;
7370Sstevel@tonic-gate 			break;
7380Sstevel@tonic-gate 		}
7390Sstevel@tonic-gate 	}
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 	if (policy == DTRACEOPT_UNSET)
7420Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy;
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	return (0);
7470Sstevel@tonic-gate }
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate static const struct {
7500Sstevel@tonic-gate 	const char *dtbr_name;
7510Sstevel@tonic-gate 	int dtbr_policy;
7520Sstevel@tonic-gate } _dtrace_bufresize[] = {
7530Sstevel@tonic-gate 	{ "auto", DTRACEOPT_BUFRESIZE_AUTO },
7540Sstevel@tonic-gate 	{ "manual", DTRACEOPT_BUFRESIZE_MANUAL },
7550Sstevel@tonic-gate 	{ NULL, 0 }
7560Sstevel@tonic-gate };
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate /*ARGSUSED*/
7590Sstevel@tonic-gate static int
dt_opt_bufresize(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)7600Sstevel@tonic-gate dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
7610Sstevel@tonic-gate {
7620Sstevel@tonic-gate 	dtrace_optval_t policy = DTRACEOPT_UNSET;
7630Sstevel@tonic-gate 	int i;
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	if (arg == NULL)
7660Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) {
7690Sstevel@tonic-gate 		if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) {
7700Sstevel@tonic-gate 			policy = _dtrace_bufresize[i].dtbr_policy;
7710Sstevel@tonic-gate 			break;
7720Sstevel@tonic-gate 		}
7730Sstevel@tonic-gate 	}
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 	if (policy == DTRACEOPT_UNSET)
7760Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy;
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	return (0);
7810Sstevel@tonic-gate }
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate int
dt_options_load(dtrace_hdl_t * dtp)7840Sstevel@tonic-gate dt_options_load(dtrace_hdl_t *dtp)
7850Sstevel@tonic-gate {
7860Sstevel@tonic-gate 	dof_hdr_t hdr, *dof;
7870Sstevel@tonic-gate 	dof_sec_t *sec;
7880Sstevel@tonic-gate 	size_t offs;
7890Sstevel@tonic-gate 	int i;
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 	/*
7920Sstevel@tonic-gate 	 * To load the option values, we need to ask the kernel to provide its
7930Sstevel@tonic-gate 	 * DOF, which we'll sift through to look for OPTDESC sections.
7940Sstevel@tonic-gate 	 */
7950Sstevel@tonic-gate 	bzero(&hdr, sizeof (dof_hdr_t));
7960Sstevel@tonic-gate 	hdr.dofh_loadsz = sizeof (dof_hdr_t);
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1)
7990Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate 	if (hdr.dofh_loadsz < sizeof (dof_hdr_t))
8020Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate 	dof = alloca(hdr.dofh_loadsz);
8050Sstevel@tonic-gate 	bzero(dof, sizeof (dof_hdr_t));
8060Sstevel@tonic-gate 	dof->dofh_loadsz = hdr.dofh_loadsz;
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	for (i = 0; i < DTRACEOPT_MAX; i++)
8090Sstevel@tonic-gate 		dtp->dt_options[i] = DTRACEOPT_UNSET;
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1)
8120Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	for (i = 0; i < dof->dofh_secnum; i++) {
815191Sahl 		sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof +
8160Sstevel@tonic-gate 		    dof->dofh_secoff + i * dof->dofh_secsize);
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 		if (sec->dofs_type != DOF_SECT_OPTDESC)
8190Sstevel@tonic-gate 			continue;
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 		break;
8220Sstevel@tonic-gate 	}
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 	for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {
825191Sahl 		dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t)
826191Sahl 		    ((uintptr_t)dof + sec->dofs_offset + offs);
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 		if (opt->dofo_strtab != DOF_SECIDX_NONE)
8290Sstevel@tonic-gate 			continue;
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 		if (opt->dofo_option >= DTRACEOPT_MAX)
8320Sstevel@tonic-gate 			continue;
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 		dtp->dt_options[opt->dofo_option] = opt->dofo_value;
8350Sstevel@tonic-gate 	}
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate 	return (0);
8380Sstevel@tonic-gate }
8390Sstevel@tonic-gate 
840*3944Sahl /*ARGSUSED*/
841*3944Sahl static int
dt_opt_preallocate(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)842*3944Sahl dt_opt_preallocate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
843*3944Sahl {
844*3944Sahl 	dtrace_optval_t size;
845*3944Sahl 	void *p;
846*3944Sahl 
847*3944Sahl 	if (arg == NULL || dt_optval_parse(arg, &size) != 0)
848*3944Sahl 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
849*3944Sahl 
850*3944Sahl 	if (size > SIZE_MAX)
851*3944Sahl 		size = SIZE_MAX;
852*3944Sahl 
853*3944Sahl 	if ((p = dt_zalloc(dtp, size)) == NULL) {
854*3944Sahl 		do {
855*3944Sahl 			size /= 2;
856*3944Sahl 		} while ((p = dt_zalloc(dtp, size)) == NULL);
857*3944Sahl 	}
858*3944Sahl 
859*3944Sahl 	dt_free(dtp, p);
860*3944Sahl 
861*3944Sahl 	return (0);
862*3944Sahl }
863*3944Sahl 
8640Sstevel@tonic-gate typedef struct dt_option {
8650Sstevel@tonic-gate 	const char *o_name;
8660Sstevel@tonic-gate 	int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
8670Sstevel@tonic-gate 	uintptr_t o_option;
8680Sstevel@tonic-gate } dt_option_t;
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate /*
8710Sstevel@tonic-gate  * Compile-time options.
8720Sstevel@tonic-gate  */
8730Sstevel@tonic-gate static const dt_option_t _dtrace_ctoptions[] = {
8740Sstevel@tonic-gate 	{ "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU },
8750Sstevel@tonic-gate 	{ "amin", dt_opt_amin },
8760Sstevel@tonic-gate 	{ "argref", dt_opt_cflags, DTRACE_C_ARGREF },
8770Sstevel@tonic-gate 	{ "core", dt_opt_core },
8780Sstevel@tonic-gate 	{ "cpp", dt_opt_cflags, DTRACE_C_CPP },
8790Sstevel@tonic-gate 	{ "cpphdrs", dt_opt_cpp_hdrs },
8800Sstevel@tonic-gate 	{ "cpppath", dt_opt_cpp_path },
8810Sstevel@tonic-gate 	{ "ctypes", dt_opt_ctypes },
8820Sstevel@tonic-gate 	{ "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG },
8830Sstevel@tonic-gate 	{ "dtypes", dt_opt_dtypes },
8840Sstevel@tonic-gate 	{ "debug", dt_opt_debug },
8850Sstevel@tonic-gate 	{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
886457Sbmc 	{ "droptags", dt_opt_droptags },
8870Sstevel@tonic-gate 	{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
8880Sstevel@tonic-gate 	{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
8890Sstevel@tonic-gate 	{ "evaltime", dt_opt_evaltime },
8900Sstevel@tonic-gate 	{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
8910Sstevel@tonic-gate 	{ "iregs", dt_opt_iregs },
8920Sstevel@tonic-gate 	{ "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF },
8930Sstevel@tonic-gate 	{ "knodefs", dt_opt_cflags, DTRACE_C_KNODEF },
894265Smws 	{ "late", dt_opt_xlate },
8950Sstevel@tonic-gate 	{ "lazyload", dt_opt_lazyload },
8960Sstevel@tonic-gate 	{ "ldpath", dt_opt_ld_path },
8970Sstevel@tonic-gate 	{ "libdir", dt_opt_libdir },
8980Sstevel@tonic-gate 	{ "linkmode", dt_opt_linkmode },
8990Sstevel@tonic-gate 	{ "linktype", dt_opt_linktype },
9000Sstevel@tonic-gate 	{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
9010Sstevel@tonic-gate 	{ "pgmax", dt_opt_pgmax },
902*3944Sahl 	{ "preallocate", dt_opt_preallocate },
9030Sstevel@tonic-gate 	{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
9040Sstevel@tonic-gate 	{ "stdc", dt_opt_stdc },
9050Sstevel@tonic-gate 	{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
9060Sstevel@tonic-gate 	{ "syslibdir", dt_opt_syslibdir },
9070Sstevel@tonic-gate 	{ "tree", dt_opt_tree },
9080Sstevel@tonic-gate 	{ "tregs", dt_opt_tregs },
9090Sstevel@tonic-gate 	{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
9100Sstevel@tonic-gate 	{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
9110Sstevel@tonic-gate 	{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
9120Sstevel@tonic-gate 	{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
9130Sstevel@tonic-gate 	{ "version", dt_opt_version },
9140Sstevel@tonic-gate 	{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
9150Sstevel@tonic-gate 	{ NULL }
9160Sstevel@tonic-gate };
9170Sstevel@tonic-gate 
9180Sstevel@tonic-gate /*
9190Sstevel@tonic-gate  * Run-time options.
9200Sstevel@tonic-gate  */
9210Sstevel@tonic-gate static const dt_option_t _dtrace_rtoptions[] = {
9220Sstevel@tonic-gate 	{ "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE },
9230Sstevel@tonic-gate 	{ "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE },
9240Sstevel@tonic-gate 	{ "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY },
9250Sstevel@tonic-gate 	{ "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE },
9260Sstevel@tonic-gate 	{ "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE },
9270Sstevel@tonic-gate 	{ "cpu", dt_opt_runtime, DTRACEOPT_CPU },
9280Sstevel@tonic-gate 	{ "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE },
9290Sstevel@tonic-gate 	{ "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE },
9300Sstevel@tonic-gate 	{ "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON },
9310Sstevel@tonic-gate 	{ "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES },
932457Sbmc 	{ "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE },
9330Sstevel@tonic-gate 	{ "nspec", dt_opt_runtime, DTRACEOPT_NSPEC },
934457Sbmc 	{ "specsize", dt_opt_size, DTRACEOPT_SPECSIZE },
935457Sbmc 	{ "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES },
936457Sbmc 	{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
937457Sbmc 	{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
938457Sbmc 	{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
939457Sbmc 	{ NULL }
940457Sbmc };
941457Sbmc 
942457Sbmc /*
943457Sbmc  * Dynamic run-time options.
944457Sbmc  */
945457Sbmc static const dt_option_t _dtrace_drtoptions[] = {
946457Sbmc 	{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
9471017Sbmc 	{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },
9481017Sbmc 	{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },
9491017Sbmc 	{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },
9501017Sbmc 	{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },
951457Sbmc 	{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
9520Sstevel@tonic-gate 	{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
9530Sstevel@tonic-gate 	{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
9540Sstevel@tonic-gate 	{ "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT },
9550Sstevel@tonic-gate 	{ "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE },
956576Sbmc 	{ NULL }
9570Sstevel@tonic-gate };
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate int
dtrace_getopt(dtrace_hdl_t * dtp,const char * opt,dtrace_optval_t * val)9600Sstevel@tonic-gate dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val)
9610Sstevel@tonic-gate {
9620Sstevel@tonic-gate 	const dt_option_t *op;
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 	if (opt == NULL)
9650Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	/*
9680Sstevel@tonic-gate 	 * We only need to search the run-time options -- it's not legal
9690Sstevel@tonic-gate 	 * to get the values of compile-time options.
9700Sstevel@tonic-gate 	 */
9710Sstevel@tonic-gate 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
9720Sstevel@tonic-gate 		if (strcmp(op->o_name, opt) == 0) {
9730Sstevel@tonic-gate 			*val = dtp->dt_options[op->o_option];
9740Sstevel@tonic-gate 			return (0);
9750Sstevel@tonic-gate 		}
9760Sstevel@tonic-gate 	}
9770Sstevel@tonic-gate 
978457Sbmc 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
979457Sbmc 		if (strcmp(op->o_name, opt) == 0) {
980457Sbmc 			*val = dtp->dt_options[op->o_option];
981457Sbmc 			return (0);
982457Sbmc 		}
983457Sbmc 	}
984457Sbmc 
9850Sstevel@tonic-gate 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
9860Sstevel@tonic-gate }
9870Sstevel@tonic-gate 
9880Sstevel@tonic-gate int
dtrace_setopt(dtrace_hdl_t * dtp,const char * opt,const char * val)9890Sstevel@tonic-gate dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val)
9900Sstevel@tonic-gate {
9910Sstevel@tonic-gate 	const dt_option_t *op;
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 	if (opt == NULL)
9940Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 	for (op = _dtrace_ctoptions; op->o_name != NULL; op++) {
9970Sstevel@tonic-gate 		if (strcmp(op->o_name, opt) == 0)
9980Sstevel@tonic-gate 			return (op->o_func(dtp, val, op->o_option));
9990Sstevel@tonic-gate 	}
10000Sstevel@tonic-gate 
1001457Sbmc 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
1002457Sbmc 		if (strcmp(op->o_name, opt) == 0)
1003457Sbmc 			return (op->o_func(dtp, val, op->o_option));
1004457Sbmc 	}
1005457Sbmc 
10060Sstevel@tonic-gate 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
10070Sstevel@tonic-gate 		if (strcmp(op->o_name, opt) == 0) {
10080Sstevel@tonic-gate 			/*
1009457Sbmc 			 * Only dynamic run-time options may be set while
10100Sstevel@tonic-gate 			 * tracing is active.
10110Sstevel@tonic-gate 			 */
10120Sstevel@tonic-gate 			if (dtp->dt_active)
10130Sstevel@tonic-gate 				return (dt_set_errno(dtp, EDT_ACTIVE));
10140Sstevel@tonic-gate 
10150Sstevel@tonic-gate 			return (op->o_func(dtp, val, op->o_option));
10160Sstevel@tonic-gate 		}
10170Sstevel@tonic-gate 	}
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
10200Sstevel@tonic-gate }
1021