17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
573427c57Sahl  * Common Development and Distribution License (the "License").
673427c57Sahl  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2173427c57Sahl 
227c478bd9Sstevel@tonic-gate /*
2373427c57Sahl  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27e5803b76SAdam H. Leventhal /*
2833093f5bSBryan Cantrill  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
29e5803b76SAdam H. Leventhal  * Copyright (c) 2012 by Delphix. All rights reserved.
30e5803b76SAdam H. Leventhal  */
31e5803b76SAdam H. Leventhal 
327c478bd9Sstevel@tonic-gate #include <sys/resource.h>
3373427c57Sahl #include <sys/mman.h>
3473427c57Sahl #include <sys/types.h>
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <strings.h>
377c478bd9Sstevel@tonic-gate #include <signal.h>
387c478bd9Sstevel@tonic-gate #include <stdlib.h>
397c478bd9Sstevel@tonic-gate #include <unistd.h>
407c478bd9Sstevel@tonic-gate #include <limits.h>
417c478bd9Sstevel@tonic-gate #include <alloca.h>
427c478bd9Sstevel@tonic-gate #include <errno.h>
437c478bd9Sstevel@tonic-gate #include <fcntl.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #include <dt_impl.h>
467c478bd9Sstevel@tonic-gate #include <dt_string.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate static int
dt_opt_agg(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)497c478bd9Sstevel@tonic-gate dt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
507c478bd9Sstevel@tonic-gate {
517c478bd9Sstevel@tonic-gate 	dt_aggregate_t *agp = &dtp->dt_aggregate;
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate 	if (arg != NULL)
547c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate 	agp->dtat_flags |= option;
577c478bd9Sstevel@tonic-gate 	return (0);
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /*ARGSUSED*/
617c478bd9Sstevel@tonic-gate static int
dt_opt_amin(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)627c478bd9Sstevel@tonic-gate dt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
637c478bd9Sstevel@tonic-gate {
647c478bd9Sstevel@tonic-gate 	char str[DTRACE_ATTR2STR_MAX];
657c478bd9Sstevel@tonic-gate 	dtrace_attribute_t attr;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 	if (arg == NULL || dtrace_str2attr(arg, &attr) == -1)
687c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	dt_dprintf("set compiler attribute minimum to %s\n",
717c478bd9Sstevel@tonic-gate 	    dtrace_attr2str(attr, str, sizeof (str)));
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL) {
747c478bd9Sstevel@tonic-gate 		dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR;
757c478bd9Sstevel@tonic-gate 		dtp->dt_pcb->pcb_amin = attr;
767c478bd9Sstevel@tonic-gate 	} else {
777c478bd9Sstevel@tonic-gate 		dtp->dt_cflags |= DTRACE_C_EATTR;
787c478bd9Sstevel@tonic-gate 		dtp->dt_amin = attr;
797c478bd9Sstevel@tonic-gate 	}
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	return (0);
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate static void
dt_coredump(void)857c478bd9Sstevel@tonic-gate dt_coredump(void)
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate 	const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n";
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	struct sigaction act;
907c478bd9Sstevel@tonic-gate 	struct rlimit lim;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	(void) write(STDERR_FILENO, msg, sizeof (msg) - 1);
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	act.sa_handler = SIG_DFL;
957c478bd9Sstevel@tonic-gate 	act.sa_flags = 0;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
987c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGABRT, &act, NULL);
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	lim.rlim_cur = RLIM_INFINITY;
1017c478bd9Sstevel@tonic-gate 	lim.rlim_max = RLIM_INFINITY;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	(void) setrlimit(RLIMIT_CORE, &lim);
1047c478bd9Sstevel@tonic-gate 	abort();
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1087c478bd9Sstevel@tonic-gate static int
dt_opt_core(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1097c478bd9Sstevel@tonic-gate dt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1107c478bd9Sstevel@tonic-gate {
1117c478bd9Sstevel@tonic-gate 	static int enabled = 0;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	if (arg != NULL)
1147c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (enabled++ || atexit(dt_coredump) == 0)
1177c478bd9Sstevel@tonic-gate 		return (0);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	return (dt_set_errno(dtp, errno));
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1237c478bd9Sstevel@tonic-gate static int
dt_opt_cpp_hdrs(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1247c478bd9Sstevel@tonic-gate dt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate 	if (arg != NULL)
1277c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
1307c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	if (dt_cpp_add_arg(dtp, "-H") == NULL)
1337c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	return (0);
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1397c478bd9Sstevel@tonic-gate static int
dt_opt_cpp_path(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1407c478bd9Sstevel@tonic-gate dt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1417c478bd9Sstevel@tonic-gate {
1427c478bd9Sstevel@tonic-gate 	char *cpp;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (arg == NULL)
1457c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
1487c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	if ((cpp = strdup(arg)) == NULL)
1517c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);
1547c478bd9Sstevel@tonic-gate 	free(dtp->dt_cpp_path);
1557c478bd9Sstevel@tonic-gate 	dtp->dt_cpp_path = cpp;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	return (0);
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate static int
dt_opt_cpp_opts(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1617c478bd9Sstevel@tonic-gate dt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate 	char *buf;
1647c478bd9Sstevel@tonic-gate 	size_t len;
1657c478bd9Sstevel@tonic-gate 	const char *opt = (const char *)option;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	if (opt == NULL || arg == NULL)
1687c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
1717c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	len = strlen(opt) + strlen(arg) + 1;
1747c478bd9Sstevel@tonic-gate 	buf = alloca(len);
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	(void) strcpy(buf, opt);
1777c478bd9Sstevel@tonic-gate 	(void) strcat(buf, arg);
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	if (dt_cpp_add_arg(dtp, buf) == NULL)
1807c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	return (0);
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1867c478bd9Sstevel@tonic-gate static int
dt_opt_ctypes(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)1877c478bd9Sstevel@tonic-gate dt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
1887c478bd9Sstevel@tonic-gate {
1897c478bd9Sstevel@tonic-gate 	int fd;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	if (arg == NULL)
1927c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
1957c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	(void) close(dtp->dt_cdefs_fd);
1987c478bd9Sstevel@tonic-gate 	dtp->dt_cdefs_fd = fd;
1997c478bd9Sstevel@tonic-gate 	return (0);
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2037c478bd9Sstevel@tonic-gate static int
dt_opt_droptags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)204a1b5e537Sbmc dt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
205a1b5e537Sbmc {
206a1b5e537Sbmc 	dtp->dt_droptags = 1;
207a1b5e537Sbmc 	return (0);
208a1b5e537Sbmc }
209a1b5e537Sbmc 
210a1b5e537Sbmc /*ARGSUSED*/
211a1b5e537Sbmc static int
dt_opt_dtypes(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2127c478bd9Sstevel@tonic-gate dt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	int fd;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	if (arg == NULL)
2177c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
2207c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	(void) close(dtp->dt_ddefs_fd);
2237c478bd9Sstevel@tonic-gate 	dtp->dt_ddefs_fd = fd;
2247c478bd9Sstevel@tonic-gate 	return (0);
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2287c478bd9Sstevel@tonic-gate static int
dt_opt_debug(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2297c478bd9Sstevel@tonic-gate dt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	if (arg != NULL)
2327c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	_dtrace_debug = 1;
2357c478bd9Sstevel@tonic-gate 	return (0);
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2397c478bd9Sstevel@tonic-gate static int
dt_opt_iregs(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2407c478bd9Sstevel@tonic-gate dt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate 	int n;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	if (arg == NULL || (n = atoi(arg)) <= 0)
2457c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	dtp->dt_conf.dtc_difintregs = n;
2487c478bd9Sstevel@tonic-gate 	return (0);
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2527c478bd9Sstevel@tonic-gate static int
dt_opt_lazyload(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2537c478bd9Sstevel@tonic-gate dt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 	dtp->dt_lazyload = 1;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	return (0);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2617c478bd9Sstevel@tonic-gate static int
dt_opt_ld_path(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2627c478bd9Sstevel@tonic-gate dt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2637c478bd9Sstevel@tonic-gate {
2647c478bd9Sstevel@tonic-gate 	char *ld;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	if (arg == NULL)
2677c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
2707c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	if ((ld = strdup(arg)) == NULL)
2737c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	free(dtp->dt_ld_path);
2767c478bd9Sstevel@tonic-gate 	dtp->dt_ld_path = ld;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	return (0);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2827c478bd9Sstevel@tonic-gate static int
dt_opt_libdir(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)2837c478bd9Sstevel@tonic-gate dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
2847c478bd9Sstevel@tonic-gate {
2857c478bd9Sstevel@tonic-gate 	dt_dirpath_t *dp;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	if (arg == NULL)
2887c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL ||
2917c478bd9Sstevel@tonic-gate 	    (dp->dir_path = strdup(arg)) == NULL) {
2927c478bd9Sstevel@tonic-gate 		free(dp);
2937c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	dt_list_append(&dtp->dt_lib_path, dp);
2977c478bd9Sstevel@tonic-gate 	return (0);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3017c478bd9Sstevel@tonic-gate static int
dt_opt_linkmode(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)3027c478bd9Sstevel@tonic-gate dt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate 	if (arg == NULL)
3057c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	if (strcmp(arg, "kernel") == 0)
3087c478bd9Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_KERNEL;
3097c478bd9Sstevel@tonic-gate 	else if (strcmp(arg, "primary") == 0)
3107c478bd9Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_PRIMARY;
3117c478bd9Sstevel@tonic-gate 	else if (strcmp(arg, "dynamic") == 0)
3127c478bd9Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_DYNAMIC;
3137c478bd9Sstevel@tonic-gate 	else if (strcmp(arg, "static") == 0)
3147c478bd9Sstevel@tonic-gate 		dtp->dt_linkmode = DT_LINK_STATIC;
3157c478bd9Sstevel@tonic-gate 	else
3167c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	return (0);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3227c478bd9Sstevel@tonic-gate static int
dt_opt_linktype(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)3237c478bd9Sstevel@tonic-gate dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3247c478bd9Sstevel@tonic-gate {
3257c478bd9Sstevel@tonic-gate 	if (arg == NULL)
3267c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	if (strcasecmp(arg, "elf") == 0)
3297c478bd9Sstevel@tonic-gate 		dtp->dt_linktype = DT_LTYP_ELF;
3307c478bd9Sstevel@tonic-gate 	else if (strcasecmp(arg, "dof") == 0)
3317c478bd9Sstevel@tonic-gate 		dtp->dt_linktype = DT_LTYP_DOF;
3327c478bd9Sstevel@tonic-gate 	else
3337c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	return (0);
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3397c478bd9Sstevel@tonic-gate static int
dt_opt_encoding(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)34033093f5bSBryan Cantrill dt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
34133093f5bSBryan Cantrill {
34233093f5bSBryan Cantrill 	if (arg == NULL)
34333093f5bSBryan Cantrill 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
34433093f5bSBryan Cantrill 
34533093f5bSBryan Cantrill 	if (strcmp(arg, "ascii") == 0)
34633093f5bSBryan Cantrill 		dtp->dt_encoding = DT_ENCODING_ASCII;
34733093f5bSBryan Cantrill 	else if (strcmp(arg, "utf8") == 0)
34833093f5bSBryan Cantrill 		dtp->dt_encoding = DT_ENCODING_UTF8;
34933093f5bSBryan Cantrill 	else
35033093f5bSBryan Cantrill 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
35133093f5bSBryan Cantrill 
35233093f5bSBryan Cantrill 	return (0);
35333093f5bSBryan Cantrill }
35433093f5bSBryan Cantrill 
35533093f5bSBryan Cantrill /*ARGSUSED*/
35633093f5bSBryan Cantrill static int
dt_opt_evaltime(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)3577c478bd9Sstevel@tonic-gate dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3587c478bd9Sstevel@tonic-gate {
3597c478bd9Sstevel@tonic-gate 	if (arg == NULL)
3607c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	if (strcmp(arg, "exec") == 0)
3637c478bd9Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_CREATE;
3647c478bd9Sstevel@tonic-gate 	else if (strcmp(arg, "preinit") == 0)
3657c478bd9Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
3667c478bd9Sstevel@tonic-gate 	else if (strcmp(arg, "postinit") == 0)
3677c478bd9Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
3687c478bd9Sstevel@tonic-gate 	else if (strcmp(arg, "main") == 0)
3697c478bd9Sstevel@tonic-gate 		dtp->dt_prcmode = DT_PROC_STOP_MAIN;
3707c478bd9Sstevel@tonic-gate 	else
3717c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	return (0);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3777c478bd9Sstevel@tonic-gate static int
dt_opt_pgmax(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)3787c478bd9Sstevel@tonic-gate dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate 	int n;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	if (arg == NULL || (n = atoi(arg)) < 0)
3837c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	dtp->dt_procs->dph_lrulim = n;
3867c478bd9Sstevel@tonic-gate 	return (0);
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate 
389e5803b76SAdam H. Leventhal static int
dt_opt_setenv(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)390e5803b76SAdam H. Leventhal dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
391e5803b76SAdam H. Leventhal {
392e5803b76SAdam H. Leventhal 	char **p;
393e5803b76SAdam H. Leventhal 	char *var;
394e5803b76SAdam H. Leventhal 	int i;
395e5803b76SAdam H. Leventhal 
396e5803b76SAdam H. Leventhal 	/*
397e5803b76SAdam H. Leventhal 	 * We can't effectively set environment variables from #pragma lines
398e5803b76SAdam H. Leventhal 	 * since the processes have already been spawned.
399e5803b76SAdam H. Leventhal 	 */
400e5803b76SAdam H. Leventhal 	if (dtp->dt_pcb != NULL)
401e5803b76SAdam H. Leventhal 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
402e5803b76SAdam H. Leventhal 
403e5803b76SAdam H. Leventhal 	if (arg == NULL)
404e5803b76SAdam H. Leventhal 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
405e5803b76SAdam H. Leventhal 
406e5803b76SAdam H. Leventhal 	if (!option && strchr(arg, '=') != NULL)
407e5803b76SAdam H. Leventhal 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
408e5803b76SAdam H. Leventhal 
409e5803b76SAdam H. Leventhal 	for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++)
410e5803b76SAdam H. Leventhal 		continue;
411e5803b76SAdam H. Leventhal 
412e5803b76SAdam H. Leventhal 	for (p = dtp->dt_proc_env; *p != NULL; p++) {
413e5803b76SAdam H. Leventhal 		var = strchr(*p, '=');
414e5803b76SAdam H. Leventhal 		if (var == NULL)
415e5803b76SAdam H. Leventhal 			var = *p + strlen(*p);
416e5803b76SAdam H. Leventhal 		if (strncmp(*p, arg, var - *p) == 0) {
417e5803b76SAdam H. Leventhal 			dt_free(dtp, *p);
418e5803b76SAdam H. Leventhal 			*p = dtp->dt_proc_env[i - 1];
419e5803b76SAdam H. Leventhal 			dtp->dt_proc_env[i - 1] = NULL;
420e5803b76SAdam H. Leventhal 			i--;
421e5803b76SAdam H. Leventhal 		}
422e5803b76SAdam H. Leventhal 	}
423e5803b76SAdam H. Leventhal 
424e5803b76SAdam H. Leventhal 	if (option) {
425e5803b76SAdam H. Leventhal 		if ((var = strdup(arg)) == NULL)
426e5803b76SAdam H. Leventhal 			return (dt_set_errno(dtp, EDT_NOMEM));
427e5803b76SAdam H. Leventhal 
428e5803b76SAdam H. Leventhal 		if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) {
429e5803b76SAdam H. Leventhal 			dt_free(dtp, var);
430e5803b76SAdam H. Leventhal 			return (dt_set_errno(dtp, EDT_NOMEM));
431e5803b76SAdam H. Leventhal 		}
432e5803b76SAdam H. Leventhal 
433e5803b76SAdam H. Leventhal 		bcopy(dtp->dt_proc_env, p, sizeof (char *) * i);
434e5803b76SAdam H. Leventhal 		dt_free(dtp, dtp->dt_proc_env);
435e5803b76SAdam H. Leventhal 		dtp->dt_proc_env = p;
436e5803b76SAdam H. Leventhal 
437e5803b76SAdam H. Leventhal 		dtp->dt_proc_env[i - 1] = var;
438e5803b76SAdam H. Leventhal 		dtp->dt_proc_env[i] = NULL;
439e5803b76SAdam H. Leventhal 	}
440e5803b76SAdam H. Leventhal 
441e5803b76SAdam H. Leventhal 	return (0);
442e5803b76SAdam H. Leventhal }
443e5803b76SAdam H. Leventhal 
4447c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4457c478bd9Sstevel@tonic-gate static int
dt_opt_stdc(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)4467c478bd9Sstevel@tonic-gate dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4477c478bd9Sstevel@tonic-gate {
4487c478bd9Sstevel@tonic-gate 	if (arg == NULL)
4497c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
4527c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	if (strcmp(arg, "a") == 0)
4557c478bd9Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XA;
4567c478bd9Sstevel@tonic-gate 	else if (strcmp(arg, "c") == 0)
4577c478bd9Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XC;
4587c478bd9Sstevel@tonic-gate 	else if (strcmp(arg, "s") == 0)
4597c478bd9Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XS;
4607c478bd9Sstevel@tonic-gate 	else if (strcmp(arg, "t") == 0)
4617c478bd9Sstevel@tonic-gate 		dtp->dt_stdcmode = DT_STDC_XT;
4627c478bd9Sstevel@tonic-gate 	else
4637c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	return (0);
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4697c478bd9Sstevel@tonic-gate static int
dt_opt_syslibdir(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)4707c478bd9Sstevel@tonic-gate dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate 	dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
4737c478bd9Sstevel@tonic-gate 	char *path;
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	if (arg == NULL)
4767c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	if ((path = strdup(arg)) == NULL)
4797c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_NOMEM));
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	free(dp->dir_path);
4827c478bd9Sstevel@tonic-gate 	dp->dir_path = path;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	return (0);
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4887c478bd9Sstevel@tonic-gate static int
dt_opt_tree(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)4897c478bd9Sstevel@tonic-gate dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate 	int m;
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	if (arg == NULL || (m = atoi(arg)) <= 0)
4947c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	dtp->dt_treedump = m;
4977c478bd9Sstevel@tonic-gate 	return (0);
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5017c478bd9Sstevel@tonic-gate static int
dt_opt_tregs(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)5027c478bd9Sstevel@tonic-gate dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate 	int n;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	if (arg == NULL || (n = atoi(arg)) <= 0)
5077c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	dtp->dt_conf.dtc_diftupregs = n;
5107c478bd9Sstevel@tonic-gate 	return (0);
5117c478bd9Sstevel@tonic-gate }
5127c478bd9Sstevel@tonic-gate 
5131a7c1b72Smws /*ARGSUSED*/
5141a7c1b72Smws static int
dt_opt_xlate(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)5151a7c1b72Smws dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
5161a7c1b72Smws {
5171a7c1b72Smws 	if (arg == NULL)
5181a7c1b72Smws 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
5191a7c1b72Smws 
5201a7c1b72Smws 	if (strcmp(arg, "dynamic") == 0)
5211a7c1b72Smws 		dtp->dt_xlatemode = DT_XL_DYNAMIC;
5221a7c1b72Smws 	else if (strcmp(arg, "static") == 0)
5231a7c1b72Smws 		dtp->dt_xlatemode = DT_XL_STATIC;
5241a7c1b72Smws 	else
5251a7c1b72Smws 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
5261a7c1b72Smws 
5271a7c1b72Smws 	return (0);
5281a7c1b72Smws }
5291a7c1b72Smws 
5301a7c1b72Smws /*ARGSUSED*/
5317c478bd9Sstevel@tonic-gate static int
dt_opt_cflags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)5327c478bd9Sstevel@tonic-gate dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
5337c478bd9Sstevel@tonic-gate {
5347c478bd9Sstevel@tonic-gate 	if (arg != NULL)
5357c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
5387c478bd9Sstevel@tonic-gate 		dtp->dt_pcb->pcb_cflags |= option;
5397c478bd9Sstevel@tonic-gate 	else
5407c478bd9Sstevel@tonic-gate 		dtp->dt_cflags |= option;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	return (0);
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate static int
dt_opt_dflags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)5467c478bd9Sstevel@tonic-gate dt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate 	if (arg != NULL)
5497c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	dtp->dt_dflags |= option;
5527c478bd9Sstevel@tonic-gate 	return (0);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate static int
dt_opt_invcflags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)5567c478bd9Sstevel@tonic-gate dt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
5577c478bd9Sstevel@tonic-gate {
5587c478bd9Sstevel@tonic-gate 	if (arg != NULL)
5597c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	if (dtp->dt_pcb != NULL)
5627c478bd9Sstevel@tonic-gate 		dtp->dt_pcb->pcb_cflags &= ~option;
5637c478bd9Sstevel@tonic-gate 	else
5647c478bd9Sstevel@tonic-gate 		dtp->dt_cflags &= ~option;
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	return (0);
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5707c478bd9Sstevel@tonic-gate static int
dt_opt_version(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)5717c478bd9Sstevel@tonic-gate dt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
5727c478bd9Sstevel@tonic-gate {
5737c478bd9Sstevel@tonic-gate 	dt_version_t v;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	if (arg == NULL)
5767c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	if (dt_version_str2num(arg, &v) == -1)
5797c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_VERSINVAL));
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	if (!dt_version_defined(v))
5827c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_VERSUNDEF));
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	return (dt_reduce(dtp, v));
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate static int
dt_opt_runtime(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)5887c478bd9Sstevel@tonic-gate dt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate 	char *end;
5917c478bd9Sstevel@tonic-gate 	dtrace_optval_t val = 0;
592a1b5e537Sbmc 	int i;
593a1b5e537Sbmc 
594a1b5e537Sbmc 	const struct {
595a1b5e537Sbmc 		char *positive;
596a1b5e537Sbmc 		char *negative;
597a1b5e537Sbmc 	} couples[] = {
598a1b5e537Sbmc 		{ "yes",	"no" },
599a1b5e537Sbmc 		{ "enable",	"disable" },
600a1b5e537Sbmc 		{ "enabled",	"disabled" },
601a1b5e537Sbmc 		{ "true",	"false" },
602a1b5e537Sbmc 		{ "on",		"off" },
603a1b5e537Sbmc 		{ "set",	"unset" },
604a1b5e537Sbmc 		{ NULL }
605a1b5e537Sbmc 	};
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	if (arg != NULL) {
608a1b5e537Sbmc 		if (arg[0] == '\0') {
609a1b5e537Sbmc 			val = DTRACEOPT_UNSET;
610a1b5e537Sbmc 			goto out;
611a1b5e537Sbmc 		}
612a1b5e537Sbmc 
613a1b5e537Sbmc 		for (i = 0; couples[i].positive != NULL; i++) {
614a1b5e537Sbmc 			if (strcasecmp(couples[i].positive, arg) == 0) {
615a1b5e537Sbmc 				val = 1;
616a1b5e537Sbmc 				goto out;
617a1b5e537Sbmc 			}
618a1b5e537Sbmc 
619a1b5e537Sbmc 			if (strcasecmp(couples[i].negative, arg) == 0) {
620a1b5e537Sbmc 				val = DTRACEOPT_UNSET;
621a1b5e537Sbmc 				goto out;
622a1b5e537Sbmc 			}
623a1b5e537Sbmc 		}
624a1b5e537Sbmc 
6257c478bd9Sstevel@tonic-gate 		errno = 0;
6267c478bd9Sstevel@tonic-gate 		val = strtoull(arg, &end, 0);
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 		if (*end != '\0' || errno != 0 || val < 0)
6297c478bd9Sstevel@tonic-gate 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
6307c478bd9Sstevel@tonic-gate 	}
6317c478bd9Sstevel@tonic-gate 
632a1b5e537Sbmc out:
6337c478bd9Sstevel@tonic-gate 	dtp->dt_options[option] = val;
6347c478bd9Sstevel@tonic-gate 	return (0);
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate static int
dt_optval_parse(const char * arg,dtrace_optval_t * rval)63873427c57Sahl dt_optval_parse(const char *arg, dtrace_optval_t *rval)
6397c478bd9Sstevel@tonic-gate {
64073427c57Sahl 	dtrace_optval_t mul = 1;
64173427c57Sahl 	size_t len;
6427c478bd9Sstevel@tonic-gate 	char *end;
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	len = strlen(arg);
6457c478bd9Sstevel@tonic-gate 	errno = 0;
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	switch (arg[len - 1]) {
6487c478bd9Sstevel@tonic-gate 	case 't':
6497c478bd9Sstevel@tonic-gate 	case 'T':
6507c478bd9Sstevel@tonic-gate 		mul *= 1024;
6517c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
6527c478bd9Sstevel@tonic-gate 	case 'g':
6537c478bd9Sstevel@tonic-gate 	case 'G':
6547c478bd9Sstevel@tonic-gate 		mul *= 1024;
6557c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
6567c478bd9Sstevel@tonic-gate 	case 'm':
6577c478bd9Sstevel@tonic-gate 	case 'M':
6587c478bd9Sstevel@tonic-gate 		mul *= 1024;
6597c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
6607c478bd9Sstevel@tonic-gate 	case 'k':
6617c478bd9Sstevel@tonic-gate 	case 'K':
6627c478bd9Sstevel@tonic-gate 		mul *= 1024;
6637c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
6647c478bd9Sstevel@tonic-gate 	default:
6657c478bd9Sstevel@tonic-gate 		break;
6667c478bd9Sstevel@tonic-gate 	}
6677c478bd9Sstevel@tonic-gate 
66873427c57Sahl 	errno = 0;
66973427c57Sahl 	*rval = strtoull(arg, &end, 0) * mul;
6707c478bd9Sstevel@tonic-gate 
67173427c57Sahl 	if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') ||
67273427c57Sahl 	    *rval < 0 || errno != 0)
67373427c57Sahl 		return (-1);
67473427c57Sahl 
67573427c57Sahl 	return (0);
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate 
67873427c57Sahl static int
dt_opt_size(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)67973427c57Sahl dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
68073427c57Sahl {
68173427c57Sahl 	dtrace_optval_t val = 0;
68273427c57Sahl 
68373427c57Sahl 	if (arg != NULL && dt_optval_parse(arg, &val) != 0)
68473427c57Sahl 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
68573427c57Sahl 
6867c478bd9Sstevel@tonic-gate 	dtp->dt_options[option] = val;
6877c478bd9Sstevel@tonic-gate 	return (0);
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate static int
dt_opt_rate(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)6917c478bd9Sstevel@tonic-gate dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
6927c478bd9Sstevel@tonic-gate {
6937c478bd9Sstevel@tonic-gate 	char *end;
6947c478bd9Sstevel@tonic-gate 	int i;
6957c478bd9Sstevel@tonic-gate 	dtrace_optval_t mul = 1, val = 0;
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	const struct {
6987c478bd9Sstevel@tonic-gate 		char *name;
6997c478bd9Sstevel@tonic-gate 		hrtime_t mul;
7007c478bd9Sstevel@tonic-gate 	} suffix[] = {
7017c478bd9Sstevel@tonic-gate 		{ "ns",		NANOSEC / NANOSEC },
7027c478bd9Sstevel@tonic-gate 		{ "nsec",	NANOSEC / NANOSEC },
7037c478bd9Sstevel@tonic-gate 		{ "us",		NANOSEC / MICROSEC },
7047c478bd9Sstevel@tonic-gate 		{ "usec",	NANOSEC / MICROSEC },
7057c478bd9Sstevel@tonic-gate 		{ "ms",		NANOSEC / MILLISEC },
7067c478bd9Sstevel@tonic-gate 		{ "msec",	NANOSEC / MILLISEC },
7077c478bd9Sstevel@tonic-gate 		{ "s",		NANOSEC / SEC },
7087c478bd9Sstevel@tonic-gate 		{ "sec",	NANOSEC / SEC },
7097c478bd9Sstevel@tonic-gate 		{ "m",		NANOSEC * (hrtime_t)60 },
7107c478bd9Sstevel@tonic-gate 		{ "min",	NANOSEC * (hrtime_t)60 },
7117c478bd9Sstevel@tonic-gate 		{ "h",		NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
7127c478bd9Sstevel@tonic-gate 		{ "hour",	NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
7137c478bd9Sstevel@tonic-gate 		{ "d",		NANOSEC * (hrtime_t)(24 * 60 * 60) },
7147c478bd9Sstevel@tonic-gate 		{ "day",	NANOSEC * (hrtime_t)(24 * 60 * 60) },
7157c478bd9Sstevel@tonic-gate 		{ "hz",		0 },
7167c478bd9Sstevel@tonic-gate 		{ NULL }
7177c478bd9Sstevel@tonic-gate 	};
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	if (arg != NULL) {
7207c478bd9Sstevel@tonic-gate 		errno = 0;
7217c478bd9Sstevel@tonic-gate 		val = strtoull(arg, &end, 0);
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 		for (i = 0; suffix[i].name != NULL; i++) {
7247c478bd9Sstevel@tonic-gate 			if (strcasecmp(suffix[i].name, end) == 0) {
7257c478bd9Sstevel@tonic-gate 				mul = suffix[i].mul;
7267c478bd9Sstevel@tonic-gate 				break;
7277c478bd9Sstevel@tonic-gate 			}
7287c478bd9Sstevel@tonic-gate 		}
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 		if (suffix[i].name == NULL && *end != '\0' || val < 0)
7317c478bd9Sstevel@tonic-gate 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 		if (mul == 0) {
7347c478bd9Sstevel@tonic-gate 			/*
7357c478bd9Sstevel@tonic-gate 			 * The rate has been specified in frequency-per-second.
7367c478bd9Sstevel@tonic-gate 			 */
7377c478bd9Sstevel@tonic-gate 			if (val != 0)
7387c478bd9Sstevel@tonic-gate 				val = NANOSEC / val;
7397c478bd9Sstevel@tonic-gate 		} else {
7407c478bd9Sstevel@tonic-gate 			val *= mul;
7417c478bd9Sstevel@tonic-gate 		}
7427c478bd9Sstevel@tonic-gate 	}
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	dtp->dt_options[option] = val;
7457c478bd9Sstevel@tonic-gate 	return (0);
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate /*
7497c478bd9Sstevel@tonic-gate  * When setting the strsize option, set the option in the dt_options array
7507c478bd9Sstevel@tonic-gate  * using dt_opt_size() as usual, and then update the definition of the CTF
7517c478bd9Sstevel@tonic-gate  * type for the D intrinsic "string" to be an array of the corresponding size.
7527c478bd9Sstevel@tonic-gate  * If any errors occur, reset dt_options[option] to its previous value.
7537c478bd9Sstevel@tonic-gate  */
7547c478bd9Sstevel@tonic-gate static int
dt_opt_strsize(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)7557c478bd9Sstevel@tonic-gate dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
7567c478bd9Sstevel@tonic-gate {
7577c478bd9Sstevel@tonic-gate 	dtrace_optval_t val = dtp->dt_options[option];
7587c478bd9Sstevel@tonic-gate 	ctf_file_t *fp = DT_STR_CTFP(dtp);
7597c478bd9Sstevel@tonic-gate 	ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp));
7607c478bd9Sstevel@tonic-gate 	ctf_arinfo_t r;
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 	if (dt_opt_size(dtp, arg, option) != 0)
7637c478bd9Sstevel@tonic-gate 		return (-1); /* dt_errno is set for us */
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	if (dtp->dt_options[option] > UINT_MAX) {
7667c478bd9Sstevel@tonic-gate 		dtp->dt_options[option] = val;
7677c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EOVERFLOW));
7687c478bd9Sstevel@tonic-gate 	}
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 	if (ctf_array_info(fp, type, &r) == CTF_ERR) {
7717c478bd9Sstevel@tonic-gate 		dtp->dt_options[option] = val;
7727c478bd9Sstevel@tonic-gate 		dtp->dt_ctferr = ctf_errno(fp);
7737c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_CTF));
7747c478bd9Sstevel@tonic-gate 	}
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	r.ctr_nelems = (uint_t)dtp->dt_options[option];
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	if (ctf_set_array(fp, type, &r) == CTF_ERR ||
7797c478bd9Sstevel@tonic-gate 	    ctf_update(fp) == CTF_ERR) {
7807c478bd9Sstevel@tonic-gate 		dtp->dt_options[option] = val;
7817c478bd9Sstevel@tonic-gate 		dtp->dt_ctferr = ctf_errno(fp);
7827c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_CTF));
7837c478bd9Sstevel@tonic-gate 	}
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	return (0);
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate static const struct {
7897c478bd9Sstevel@tonic-gate 	const char *dtbp_name;
7907c478bd9Sstevel@tonic-gate 	int dtbp_policy;
7917c478bd9Sstevel@tonic-gate } _dtrace_bufpolicies[] = {
7927c478bd9Sstevel@tonic-gate 	{ "ring", DTRACEOPT_BUFPOLICY_RING },
7937c478bd9Sstevel@tonic-gate 	{ "fill", DTRACEOPT_BUFPOLICY_FILL },
7947c478bd9Sstevel@tonic-gate 	{ "switch", DTRACEOPT_BUFPOLICY_SWITCH },
7957c478bd9Sstevel@tonic-gate 	{ NULL, 0 }
7967c478bd9Sstevel@tonic-gate };
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7997c478bd9Sstevel@tonic-gate static int
dt_opt_bufpolicy(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)8007c478bd9Sstevel@tonic-gate dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
8017c478bd9Sstevel@tonic-gate {
8027c478bd9Sstevel@tonic-gate 	dtrace_optval_t policy = DTRACEOPT_UNSET;
8037c478bd9Sstevel@tonic-gate 	int i;
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate 	if (arg == NULL)
8067c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 	for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) {
8097c478bd9Sstevel@tonic-gate 		if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) {
8107c478bd9Sstevel@tonic-gate 			policy = _dtrace_bufpolicies[i].dtbp_policy;
8117c478bd9Sstevel@tonic-gate 			break;
8127c478bd9Sstevel@tonic-gate 		}
8137c478bd9Sstevel@tonic-gate 	}
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 	if (policy == DTRACEOPT_UNSET)
8167c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy;
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 	return (0);
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate static const struct {
8247c478bd9Sstevel@tonic-gate 	const char *dtbr_name;
8257c478bd9Sstevel@tonic-gate 	int dtbr_policy;
8267c478bd9Sstevel@tonic-gate } _dtrace_bufresize[] = {
8277c478bd9Sstevel@tonic-gate 	{ "auto", DTRACEOPT_BUFRESIZE_AUTO },
8287c478bd9Sstevel@tonic-gate 	{ "manual", DTRACEOPT_BUFRESIZE_MANUAL },
8297c478bd9Sstevel@tonic-gate 	{ NULL, 0 }
8307c478bd9Sstevel@tonic-gate };
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8337c478bd9Sstevel@tonic-gate static int
dt_opt_bufresize(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)8347c478bd9Sstevel@tonic-gate dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
8357c478bd9Sstevel@tonic-gate {
8367c478bd9Sstevel@tonic-gate 	dtrace_optval_t policy = DTRACEOPT_UNSET;
8377c478bd9Sstevel@tonic-gate 	int i;
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	if (arg == NULL)
8407c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) {
8437c478bd9Sstevel@tonic-gate 		if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) {
8447c478bd9Sstevel@tonic-gate 			policy = _dtrace_bufresize[i].dtbr_policy;
8457c478bd9Sstevel@tonic-gate 			break;
8467c478bd9Sstevel@tonic-gate 		}
8477c478bd9Sstevel@tonic-gate 	}
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	if (policy == DTRACEOPT_UNSET)
8507c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy;
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	return (0);
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate int
dt_options_load(dtrace_hdl_t * dtp)8587c478bd9Sstevel@tonic-gate dt_options_load(dtrace_hdl_t *dtp)
8597c478bd9Sstevel@tonic-gate {
8607c478bd9Sstevel@tonic-gate 	dof_hdr_t hdr, *dof;
8617c478bd9Sstevel@tonic-gate 	dof_sec_t *sec;
8627c478bd9Sstevel@tonic-gate 	size_t offs;
8637c478bd9Sstevel@tonic-gate 	int i;
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	/*
8667c478bd9Sstevel@tonic-gate 	 * To load the option values, we need to ask the kernel to provide its
8677c478bd9Sstevel@tonic-gate 	 * DOF, which we'll sift through to look for OPTDESC sections.
8687c478bd9Sstevel@tonic-gate 	 */
8697c478bd9Sstevel@tonic-gate 	bzero(&hdr, sizeof (dof_hdr_t));
8707c478bd9Sstevel@tonic-gate 	hdr.dofh_loadsz = sizeof (dof_hdr_t);
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1)
8737c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	if (hdr.dofh_loadsz < sizeof (dof_hdr_t))
8767c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
8777c478bd9Sstevel@tonic-gate 
878*b63b86d1SToomas Soome 	dof = calloc(1, hdr.dofh_loadsz);
879*b63b86d1SToomas Soome 	if (dof == NULL)
880*b63b86d1SToomas Soome 		return (dt_set_errno(dtp, errno));
881*b63b86d1SToomas Soome 
8827c478bd9Sstevel@tonic-gate 	dof->dofh_loadsz = hdr.dofh_loadsz;
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 	for (i = 0; i < DTRACEOPT_MAX; i++)
8857c478bd9Sstevel@tonic-gate 		dtp->dt_options[i] = DTRACEOPT_UNSET;
8867c478bd9Sstevel@tonic-gate 
887*b63b86d1SToomas Soome 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1) {
888*b63b86d1SToomas Soome 		free(dof);
8897c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, errno));
890*b63b86d1SToomas Soome 	}
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 	for (i = 0; i < dof->dofh_secnum; i++) {
8930b38a8bdSahl 		sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof +
8947c478bd9Sstevel@tonic-gate 		    dof->dofh_secoff + i * dof->dofh_secsize);
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 		if (sec->dofs_type != DOF_SECT_OPTDESC)
8977c478bd9Sstevel@tonic-gate 			continue;
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 		break;
9007c478bd9Sstevel@tonic-gate 	}
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {
9030b38a8bdSahl 		dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t)
9040b38a8bdSahl 		    ((uintptr_t)dof + sec->dofs_offset + offs);
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 		if (opt->dofo_strtab != DOF_SECIDX_NONE)
9077c478bd9Sstevel@tonic-gate 			continue;
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 		if (opt->dofo_option >= DTRACEOPT_MAX)
9107c478bd9Sstevel@tonic-gate 			continue;
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 		dtp->dt_options[opt->dofo_option] = opt->dofo_value;
9137c478bd9Sstevel@tonic-gate 	}
9147c478bd9Sstevel@tonic-gate 
915*b63b86d1SToomas Soome 	free(dof);
9167c478bd9Sstevel@tonic-gate 	return (0);
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate typedef struct dt_option {
9207c478bd9Sstevel@tonic-gate 	const char *o_name;
9217c478bd9Sstevel@tonic-gate 	int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
9227c478bd9Sstevel@tonic-gate 	uintptr_t o_option;
9237c478bd9Sstevel@tonic-gate } dt_option_t;
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate /*
9267c478bd9Sstevel@tonic-gate  * Compile-time options.
9277c478bd9Sstevel@tonic-gate  */
9287c478bd9Sstevel@tonic-gate static const dt_option_t _dtrace_ctoptions[] = {
9297c478bd9Sstevel@tonic-gate 	{ "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU },
9307c478bd9Sstevel@tonic-gate 	{ "amin", dt_opt_amin },
9317c478bd9Sstevel@tonic-gate 	{ "argref", dt_opt_cflags, DTRACE_C_ARGREF },
9327c478bd9Sstevel@tonic-gate 	{ "core", dt_opt_core },
9337c478bd9Sstevel@tonic-gate 	{ "cpp", dt_opt_cflags, DTRACE_C_CPP },
9347c478bd9Sstevel@tonic-gate 	{ "cpphdrs", dt_opt_cpp_hdrs },
9357c478bd9Sstevel@tonic-gate 	{ "cpppath", dt_opt_cpp_path },
9367c478bd9Sstevel@tonic-gate 	{ "ctypes", dt_opt_ctypes },
9377c478bd9Sstevel@tonic-gate 	{ "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG },
9387c478bd9Sstevel@tonic-gate 	{ "dtypes", dt_opt_dtypes },
9397c478bd9Sstevel@tonic-gate 	{ "debug", dt_opt_debug },
9407c478bd9Sstevel@tonic-gate 	{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
941a1b5e537Sbmc 	{ "droptags", dt_opt_droptags },
9427c478bd9Sstevel@tonic-gate 	{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
94333093f5bSBryan Cantrill 	{ "encoding", dt_opt_encoding },
9447c478bd9Sstevel@tonic-gate 	{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
9457c478bd9Sstevel@tonic-gate 	{ "evaltime", dt_opt_evaltime },
9467c478bd9Sstevel@tonic-gate 	{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
9477c478bd9Sstevel@tonic-gate 	{ "iregs", dt_opt_iregs },
9487c478bd9Sstevel@tonic-gate 	{ "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF },
9497c478bd9Sstevel@tonic-gate 	{ "knodefs", dt_opt_cflags, DTRACE_C_KNODEF },
9501a7c1b72Smws 	{ "late", dt_opt_xlate },
9517c478bd9Sstevel@tonic-gate 	{ "lazyload", dt_opt_lazyload },
9527c478bd9Sstevel@tonic-gate 	{ "ldpath", dt_opt_ld_path },
9537c478bd9Sstevel@tonic-gate 	{ "libdir", dt_opt_libdir },
9547c478bd9Sstevel@tonic-gate 	{ "linkmode", dt_opt_linkmode },
9557c478bd9Sstevel@tonic-gate 	{ "linktype", dt_opt_linktype },
9567c478bd9Sstevel@tonic-gate 	{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
9577c478bd9Sstevel@tonic-gate 	{ "pgmax", dt_opt_pgmax },
9587c478bd9Sstevel@tonic-gate 	{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
959e5803b76SAdam H. Leventhal 	{ "setenv", dt_opt_setenv, 1 },
9607c478bd9Sstevel@tonic-gate 	{ "stdc", dt_opt_stdc },
9617c478bd9Sstevel@tonic-gate 	{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
9627c478bd9Sstevel@tonic-gate 	{ "syslibdir", dt_opt_syslibdir },
9637c478bd9Sstevel@tonic-gate 	{ "tree", dt_opt_tree },
9647c478bd9Sstevel@tonic-gate 	{ "tregs", dt_opt_tregs },
9657c478bd9Sstevel@tonic-gate 	{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
9667c478bd9Sstevel@tonic-gate 	{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
9677c478bd9Sstevel@tonic-gate 	{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
968e5803b76SAdam H. Leventhal 	{ "unsetenv", dt_opt_setenv, 0 },
9697c478bd9Sstevel@tonic-gate 	{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
9707c478bd9Sstevel@tonic-gate 	{ "version", dt_opt_version },
9717c478bd9Sstevel@tonic-gate 	{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
9727c478bd9Sstevel@tonic-gate 	{ NULL }
9737c478bd9Sstevel@tonic-gate };
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate /*
9767c478bd9Sstevel@tonic-gate  * Run-time options.
9777c478bd9Sstevel@tonic-gate  */
9787c478bd9Sstevel@tonic-gate static const dt_option_t _dtrace_rtoptions[] = {
9797c478bd9Sstevel@tonic-gate 	{ "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE },
9807c478bd9Sstevel@tonic-gate 	{ "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE },
9817c478bd9Sstevel@tonic-gate 	{ "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY },
9827c478bd9Sstevel@tonic-gate 	{ "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE },
9837c478bd9Sstevel@tonic-gate 	{ "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE },
9847c478bd9Sstevel@tonic-gate 	{ "cpu", dt_opt_runtime, DTRACEOPT_CPU },
9857c478bd9Sstevel@tonic-gate 	{ "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE },
9867c478bd9Sstevel@tonic-gate 	{ "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE },
9877c478bd9Sstevel@tonic-gate 	{ "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON },
9887c478bd9Sstevel@tonic-gate 	{ "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES },
989a1b5e537Sbmc 	{ "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE },
9907c478bd9Sstevel@tonic-gate 	{ "nspec", dt_opt_runtime, DTRACEOPT_NSPEC },
9917c478bd9Sstevel@tonic-gate 	{ "specsize", dt_opt_size, DTRACEOPT_SPECSIZE },
9927c478bd9Sstevel@tonic-gate 	{ "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES },
9937c478bd9Sstevel@tonic-gate 	{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
9947c478bd9Sstevel@tonic-gate 	{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
9957c478bd9Sstevel@tonic-gate 	{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
996e5803b76SAdam H. Leventhal 	{ "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },
9977c478bd9Sstevel@tonic-gate 	{ NULL }
9987c478bd9Sstevel@tonic-gate };
9997c478bd9Sstevel@tonic-gate 
1000a1b5e537Sbmc /*
1001a1b5e537Sbmc  * Dynamic run-time options.
1002a1b5e537Sbmc  */
1003a1b5e537Sbmc static const dt_option_t _dtrace_drtoptions[] = {
100433093f5bSBryan Cantrill 	{ "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST },
100533093f5bSBryan Cantrill 	{ "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK },
1006a1b5e537Sbmc 	{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
100730ef842dSbmc 	{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },
100830ef842dSbmc 	{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },
100930ef842dSbmc 	{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },
101030ef842dSbmc 	{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },
101133093f5bSBryan Cantrill 	{ "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM },
1012a1b5e537Sbmc 	{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
1013a1b5e537Sbmc 	{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
1014a1b5e537Sbmc 	{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
1015a1b5e537Sbmc 	{ "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT },
1016a1b5e537Sbmc 	{ "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE },
1017b365acd0Sbmc 	{ NULL }
1018a1b5e537Sbmc };
1019a1b5e537Sbmc 
10207c478bd9Sstevel@tonic-gate int
dtrace_getopt(dtrace_hdl_t * dtp,const char * opt,dtrace_optval_t * val)10217c478bd9Sstevel@tonic-gate dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val)
10227c478bd9Sstevel@tonic-gate {
10237c478bd9Sstevel@tonic-gate 	const dt_option_t *op;
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	if (opt == NULL)
10267c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 	/*
10297c478bd9Sstevel@tonic-gate 	 * We only need to search the run-time options -- it's not legal
10307c478bd9Sstevel@tonic-gate 	 * to get the values of compile-time options.
10317c478bd9Sstevel@tonic-gate 	 */
10327c478bd9Sstevel@tonic-gate 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
10337c478bd9Sstevel@tonic-gate 		if (strcmp(op->o_name, opt) == 0) {
10347c478bd9Sstevel@tonic-gate 			*val = dtp->dt_options[op->o_option];
10357c478bd9Sstevel@tonic-gate 			return (0);
10367c478bd9Sstevel@tonic-gate 		}
10377c478bd9Sstevel@tonic-gate 	}
10387c478bd9Sstevel@tonic-gate 
1039a1b5e537Sbmc 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
1040a1b5e537Sbmc 		if (strcmp(op->o_name, opt) == 0) {
1041a1b5e537Sbmc 			*val = dtp->dt_options[op->o_option];
1042a1b5e537Sbmc 			return (0);
1043a1b5e537Sbmc 		}
1044a1b5e537Sbmc 	}
1045a1b5e537Sbmc 
10467c478bd9Sstevel@tonic-gate 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate int
dtrace_setopt(dtrace_hdl_t * dtp,const char * opt,const char * val)10507c478bd9Sstevel@tonic-gate dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val)
10517c478bd9Sstevel@tonic-gate {
10527c478bd9Sstevel@tonic-gate 	const dt_option_t *op;
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate 	if (opt == NULL)
10557c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 	for (op = _dtrace_ctoptions; op->o_name != NULL; op++) {
10587c478bd9Sstevel@tonic-gate 		if (strcmp(op->o_name, opt) == 0)
10597c478bd9Sstevel@tonic-gate 			return (op->o_func(dtp, val, op->o_option));
10607c478bd9Sstevel@tonic-gate 	}
10617c478bd9Sstevel@tonic-gate 
1062a1b5e537Sbmc 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
1063a1b5e537Sbmc 		if (strcmp(op->o_name, opt) == 0)
1064a1b5e537Sbmc 			return (op->o_func(dtp, val, op->o_option));
1065a1b5e537Sbmc 	}
1066a1b5e537Sbmc 
10677c478bd9Sstevel@tonic-gate 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
10687c478bd9Sstevel@tonic-gate 		if (strcmp(op->o_name, opt) == 0) {
10697c478bd9Sstevel@tonic-gate 			/*
1070a1b5e537Sbmc 			 * Only dynamic run-time options may be set while
10717c478bd9Sstevel@tonic-gate 			 * tracing is active.
10727c478bd9Sstevel@tonic-gate 			 */
10737c478bd9Sstevel@tonic-gate 			if (dtp->dt_active)
10747c478bd9Sstevel@tonic-gate 				return (dt_set_errno(dtp, EDT_ACTIVE));
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 			return (op->o_func(dtp, val, op->o_option));
10777c478bd9Sstevel@tonic-gate 		}
10787c478bd9Sstevel@tonic-gate 	}
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
10817c478bd9Sstevel@tonic-gate }
1082