xref: /netbsd-src/external/cddl/osnet/dist/lib/libdtrace/common/dt_options.c (revision 86b0983beaca0a2e397ea0b3d15f94693b1e6574)
1a864dc36Sdarran /*
2a864dc36Sdarran  * CDDL HEADER START
3a864dc36Sdarran  *
4a864dc36Sdarran  * The contents of this file are subject to the terms of the
5a864dc36Sdarran  * Common Development and Distribution License (the "License").
6a864dc36Sdarran  * You may not use this file except in compliance with the License.
7a864dc36Sdarran  *
8a864dc36Sdarran  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a864dc36Sdarran  * or http://www.opensolaris.org/os/licensing.
10a864dc36Sdarran  * See the License for the specific language governing permissions
11a864dc36Sdarran  * and limitations under the License.
12a864dc36Sdarran  *
13a864dc36Sdarran  * When distributing Covered Code, include this CDDL HEADER in each
14a864dc36Sdarran  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a864dc36Sdarran  * If applicable, add the following below this CDDL HEADER, with the
16a864dc36Sdarran  * fields enclosed by brackets "[]" replaced with your own identifying
17a864dc36Sdarran  * information: Portions Copyright [yyyy] [name of copyright owner]
18a864dc36Sdarran  *
19a864dc36Sdarran  * CDDL HEADER END
20a864dc36Sdarran  */
21a864dc36Sdarran 
22a864dc36Sdarran /*
23a864dc36Sdarran  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24a864dc36Sdarran  * Use is subject to license terms.
25a864dc36Sdarran  */
26a864dc36Sdarran 
27c0855460Schristos /*
28c0855460Schristos  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
29c0855460Schristos  * Copyright (c) 2012 by Delphix. All rights reserved.
30c0855460Schristos  */
31a864dc36Sdarran 
32a864dc36Sdarran #include <sys/resource.h>
33a864dc36Sdarran #include <sys/mman.h>
34a864dc36Sdarran #include <sys/types.h>
35a864dc36Sdarran 
36a864dc36Sdarran #include <strings.h>
37a864dc36Sdarran #include <signal.h>
38a864dc36Sdarran #include <stdlib.h>
39a864dc36Sdarran #include <unistd.h>
40a864dc36Sdarran #include <limits.h>
41c0855460Schristos #ifdef illumos
42a864dc36Sdarran #include <alloca.h>
43bb8023b5Sdarran #endif
44a864dc36Sdarran #include <errno.h>
45a864dc36Sdarran #include <fcntl.h>
46a864dc36Sdarran 
47a864dc36Sdarran #include <dt_impl.h>
48a864dc36Sdarran #include <dt_string.h>
49a864dc36Sdarran 
50a864dc36Sdarran static int
dt_opt_agg(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)51a864dc36Sdarran dt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
52a864dc36Sdarran {
53a864dc36Sdarran 	dt_aggregate_t *agp = &dtp->dt_aggregate;
54a864dc36Sdarran 
55a864dc36Sdarran 	if (arg != NULL)
56a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
57a864dc36Sdarran 
58a864dc36Sdarran 	agp->dtat_flags |= option;
59a864dc36Sdarran 	return (0);
60a864dc36Sdarran }
61a864dc36Sdarran 
62a864dc36Sdarran /*ARGSUSED*/
63a864dc36Sdarran static int
dt_opt_amin(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)64a864dc36Sdarran dt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
65a864dc36Sdarran {
66a864dc36Sdarran 	char str[DTRACE_ATTR2STR_MAX];
67a864dc36Sdarran 	dtrace_attribute_t attr;
68a864dc36Sdarran 
69a864dc36Sdarran 	if (arg == NULL || dtrace_str2attr(arg, &attr) == -1)
70a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
71a864dc36Sdarran 
72a864dc36Sdarran 	dt_dprintf("set compiler attribute minimum to %s\n",
73a864dc36Sdarran 	    dtrace_attr2str(attr, str, sizeof (str)));
74a864dc36Sdarran 
75a864dc36Sdarran 	if (dtp->dt_pcb != NULL) {
76a864dc36Sdarran 		dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR;
77a864dc36Sdarran 		dtp->dt_pcb->pcb_amin = attr;
78a864dc36Sdarran 	} else {
79a864dc36Sdarran 		dtp->dt_cflags |= DTRACE_C_EATTR;
80a864dc36Sdarran 		dtp->dt_amin = attr;
81a864dc36Sdarran 	}
82a864dc36Sdarran 
83a864dc36Sdarran 	return (0);
84a864dc36Sdarran }
85a864dc36Sdarran 
86a864dc36Sdarran static void
dt_coredump(void)87a864dc36Sdarran dt_coredump(void)
88a864dc36Sdarran {
89a864dc36Sdarran 	const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n";
90a864dc36Sdarran 
91a864dc36Sdarran 	struct sigaction act;
92a864dc36Sdarran 	struct rlimit lim;
93a864dc36Sdarran 
94a864dc36Sdarran 	(void) write(STDERR_FILENO, msg, sizeof (msg) - 1);
95a864dc36Sdarran 
96a864dc36Sdarran 	act.sa_handler = SIG_DFL;
97a864dc36Sdarran 	act.sa_flags = 0;
98a864dc36Sdarran 
99a864dc36Sdarran 	(void) sigemptyset(&act.sa_mask);
100a864dc36Sdarran 	(void) sigaction(SIGABRT, &act, NULL);
101a864dc36Sdarran 
102a864dc36Sdarran 	lim.rlim_cur = RLIM_INFINITY;
103a864dc36Sdarran 	lim.rlim_max = RLIM_INFINITY;
104a864dc36Sdarran 
105a864dc36Sdarran 	(void) setrlimit(RLIMIT_CORE, &lim);
106a864dc36Sdarran 	abort();
107a864dc36Sdarran }
108a864dc36Sdarran 
109a864dc36Sdarran /*ARGSUSED*/
110a864dc36Sdarran static int
dt_opt_core(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)111a864dc36Sdarran dt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
112a864dc36Sdarran {
113a864dc36Sdarran 	static int enabled = 0;
114a864dc36Sdarran 
115a864dc36Sdarran 	if (arg != NULL)
116a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
117a864dc36Sdarran 
118a864dc36Sdarran 	if (enabled++ || atexit(dt_coredump) == 0)
119a864dc36Sdarran 		return (0);
120a864dc36Sdarran 
121a864dc36Sdarran 	return (dt_set_errno(dtp, errno));
122a864dc36Sdarran }
123a864dc36Sdarran 
124a864dc36Sdarran /*ARGSUSED*/
125a864dc36Sdarran static int
dt_opt_cpp_hdrs(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)126a864dc36Sdarran dt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
127a864dc36Sdarran {
128a864dc36Sdarran 	if (arg != NULL)
129a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
130a864dc36Sdarran 
131a864dc36Sdarran 	if (dtp->dt_pcb != NULL)
132a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
133a864dc36Sdarran 
134a864dc36Sdarran 	if (dt_cpp_add_arg(dtp, "-H") == NULL)
135a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_NOMEM));
136a864dc36Sdarran 
137a864dc36Sdarran 	return (0);
138a864dc36Sdarran }
139a864dc36Sdarran 
140a864dc36Sdarran /*ARGSUSED*/
141a864dc36Sdarran static int
dt_opt_cpp_path(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)142a864dc36Sdarran dt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
143a864dc36Sdarran {
144a864dc36Sdarran 	char *cpp;
145a864dc36Sdarran 
146a864dc36Sdarran 	if (arg == NULL)
147a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
148a864dc36Sdarran 
149a864dc36Sdarran 	if (dtp->dt_pcb != NULL)
150a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
151a864dc36Sdarran 
152a864dc36Sdarran 	if ((cpp = strdup(arg)) == NULL)
153a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_NOMEM));
154a864dc36Sdarran 
155a864dc36Sdarran 	dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);
156a864dc36Sdarran 	free(dtp->dt_cpp_path);
157a864dc36Sdarran 	dtp->dt_cpp_path = cpp;
158a864dc36Sdarran 
159a864dc36Sdarran 	return (0);
160a864dc36Sdarran }
161a864dc36Sdarran 
162a864dc36Sdarran static int
dt_opt_cpp_opts(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)163a864dc36Sdarran dt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
164a864dc36Sdarran {
165a864dc36Sdarran 	char *buf;
166a864dc36Sdarran 	size_t len;
167a864dc36Sdarran 	const char *opt = (const char *)option;
168a864dc36Sdarran 
169a864dc36Sdarran 	if (opt == NULL || arg == NULL)
170a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
171a864dc36Sdarran 
172a864dc36Sdarran 	if (dtp->dt_pcb != NULL)
173a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
174a864dc36Sdarran 
175a864dc36Sdarran 	len = strlen(opt) + strlen(arg) + 1;
176a864dc36Sdarran 	buf = alloca(len);
177a864dc36Sdarran 
178a864dc36Sdarran 	(void) strcpy(buf, opt);
179a864dc36Sdarran 	(void) strcat(buf, arg);
180a864dc36Sdarran 
181a864dc36Sdarran 	if (dt_cpp_add_arg(dtp, buf) == NULL)
182a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_NOMEM));
183a864dc36Sdarran 
184a864dc36Sdarran 	return (0);
185a864dc36Sdarran }
186a864dc36Sdarran 
187a864dc36Sdarran /*ARGSUSED*/
188a864dc36Sdarran static int
dt_opt_ctypes(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)189a864dc36Sdarran dt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
190a864dc36Sdarran {
191a864dc36Sdarran 	int fd;
192a864dc36Sdarran 
193a864dc36Sdarran 	if (arg == NULL)
194a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
195a864dc36Sdarran 
196a864dc36Sdarran 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
197a864dc36Sdarran 		return (dt_set_errno(dtp, errno));
198a864dc36Sdarran 
199a864dc36Sdarran 	(void) close(dtp->dt_cdefs_fd);
200a864dc36Sdarran 	dtp->dt_cdefs_fd = fd;
201a864dc36Sdarran 	return (0);
202a864dc36Sdarran }
203a864dc36Sdarran 
204a864dc36Sdarran /*ARGSUSED*/
205a864dc36Sdarran static int
dt_opt_droptags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)206a864dc36Sdarran dt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
207a864dc36Sdarran {
208a864dc36Sdarran 	dtp->dt_droptags = 1;
209a864dc36Sdarran 	return (0);
210a864dc36Sdarran }
211a864dc36Sdarran 
212a864dc36Sdarran /*ARGSUSED*/
213a864dc36Sdarran static int
dt_opt_dtypes(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)214a864dc36Sdarran dt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
215a864dc36Sdarran {
216a864dc36Sdarran 	int fd;
217a864dc36Sdarran 
218a864dc36Sdarran 	if (arg == NULL)
219a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
220a864dc36Sdarran 
221a864dc36Sdarran 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
222a864dc36Sdarran 		return (dt_set_errno(dtp, errno));
223a864dc36Sdarran 
224a864dc36Sdarran 	(void) close(dtp->dt_ddefs_fd);
225a864dc36Sdarran 	dtp->dt_ddefs_fd = fd;
226a864dc36Sdarran 	return (0);
227a864dc36Sdarran }
228a864dc36Sdarran 
229a864dc36Sdarran /*ARGSUSED*/
230a864dc36Sdarran static int
dt_opt_debug(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)231a864dc36Sdarran dt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
232a864dc36Sdarran {
233a864dc36Sdarran 	if (arg != NULL)
234a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
235a864dc36Sdarran 
236a864dc36Sdarran 	_dtrace_debug = 1;
237a864dc36Sdarran 	return (0);
238a864dc36Sdarran }
239a864dc36Sdarran 
240a864dc36Sdarran /*ARGSUSED*/
241a864dc36Sdarran static int
dt_opt_iregs(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)242a864dc36Sdarran dt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
243a864dc36Sdarran {
244a864dc36Sdarran 	int n;
245a864dc36Sdarran 
246a864dc36Sdarran 	if (arg == NULL || (n = atoi(arg)) <= 0)
247a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
248a864dc36Sdarran 
249a864dc36Sdarran 	dtp->dt_conf.dtc_difintregs = n;
250a864dc36Sdarran 	return (0);
251a864dc36Sdarran }
252a864dc36Sdarran 
253a864dc36Sdarran /*ARGSUSED*/
254a864dc36Sdarran static int
dt_opt_lazyload(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)255a864dc36Sdarran dt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
256a864dc36Sdarran {
257a864dc36Sdarran 	dtp->dt_lazyload = 1;
258a864dc36Sdarran 
259a864dc36Sdarran 	return (0);
260a864dc36Sdarran }
261a864dc36Sdarran 
262a864dc36Sdarran /*ARGSUSED*/
263a864dc36Sdarran static int
dt_opt_ld_path(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)264a864dc36Sdarran dt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
265a864dc36Sdarran {
266a864dc36Sdarran 	char *ld;
267a864dc36Sdarran 
268a864dc36Sdarran 	if (arg == NULL)
269a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
270a864dc36Sdarran 
271a864dc36Sdarran 	if (dtp->dt_pcb != NULL)
272a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
273a864dc36Sdarran 
274a864dc36Sdarran 	if ((ld = strdup(arg)) == NULL)
275a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_NOMEM));
276a864dc36Sdarran 
277a864dc36Sdarran 	free(dtp->dt_ld_path);
278a864dc36Sdarran 	dtp->dt_ld_path = ld;
279a864dc36Sdarran 
280a864dc36Sdarran 	return (0);
281a864dc36Sdarran }
282a864dc36Sdarran 
283c0855460Schristos #if defined(__FreeBSD__) || defined(__NetBSD__)
284c0855460Schristos static int
dt_opt_objcopy_path(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)285c0855460Schristos dt_opt_objcopy_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
286c0855460Schristos {
287c0855460Schristos 	char *objcopy;
288c0855460Schristos 
289c0855460Schristos 	if (arg == NULL)
290c0855460Schristos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
291c0855460Schristos 
292c0855460Schristos 	if (dtp->dt_pcb != NULL)
293c0855460Schristos 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
294c0855460Schristos 
295c0855460Schristos 	if ((objcopy = strdup(arg)) == NULL)
296c0855460Schristos 		return (dt_set_errno(dtp, EDT_NOMEM));
297c0855460Schristos 
298c0855460Schristos 	free(dtp->dt_objcopy_path);
299c0855460Schristos 	dtp->dt_objcopy_path = objcopy;
300c0855460Schristos 
301c0855460Schristos 	return (0);
302c0855460Schristos }
303c0855460Schristos #endif
304c0855460Schristos 
305a864dc36Sdarran /*ARGSUSED*/
306a864dc36Sdarran static int
dt_opt_libdir(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)307a864dc36Sdarran dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
308a864dc36Sdarran {
309a864dc36Sdarran 	dt_dirpath_t *dp;
310a864dc36Sdarran 
311a864dc36Sdarran 	if (arg == NULL)
312a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
313a864dc36Sdarran 
314a864dc36Sdarran 	if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL ||
315a864dc36Sdarran 	    (dp->dir_path = strdup(arg)) == NULL) {
316a864dc36Sdarran 		free(dp);
317a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_NOMEM));
318a864dc36Sdarran 	}
319a864dc36Sdarran 
320a864dc36Sdarran 	dt_list_append(&dtp->dt_lib_path, dp);
321a864dc36Sdarran 	return (0);
322a864dc36Sdarran }
323a864dc36Sdarran 
324a864dc36Sdarran /*ARGSUSED*/
325a864dc36Sdarran static int
dt_opt_linkmode(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)326a864dc36Sdarran dt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
327a864dc36Sdarran {
328a864dc36Sdarran 	if (arg == NULL)
329a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
330a864dc36Sdarran 
331a864dc36Sdarran 	if (strcmp(arg, "kernel") == 0)
332a864dc36Sdarran 		dtp->dt_linkmode = DT_LINK_KERNEL;
333a864dc36Sdarran 	else if (strcmp(arg, "primary") == 0)
334a864dc36Sdarran 		dtp->dt_linkmode = DT_LINK_PRIMARY;
335a864dc36Sdarran 	else if (strcmp(arg, "dynamic") == 0)
336a864dc36Sdarran 		dtp->dt_linkmode = DT_LINK_DYNAMIC;
337a864dc36Sdarran 	else if (strcmp(arg, "static") == 0)
338a864dc36Sdarran 		dtp->dt_linkmode = DT_LINK_STATIC;
339a864dc36Sdarran 	else
340a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
341a864dc36Sdarran 
342a864dc36Sdarran 	return (0);
343a864dc36Sdarran }
344a864dc36Sdarran 
345a864dc36Sdarran /*ARGSUSED*/
346a864dc36Sdarran static int
dt_opt_linktype(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)347a864dc36Sdarran dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
348a864dc36Sdarran {
349a864dc36Sdarran 	if (arg == NULL)
350a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
351a864dc36Sdarran 
352a864dc36Sdarran 	if (strcasecmp(arg, "elf") == 0)
353a864dc36Sdarran 		dtp->dt_linktype = DT_LTYP_ELF;
354a864dc36Sdarran 	else if (strcasecmp(arg, "dof") == 0)
355a864dc36Sdarran 		dtp->dt_linktype = DT_LTYP_DOF;
356a864dc36Sdarran 	else
357a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
358a864dc36Sdarran 
359a864dc36Sdarran 	return (0);
360a864dc36Sdarran }
361a864dc36Sdarran 
362a864dc36Sdarran /*ARGSUSED*/
363a864dc36Sdarran static int
dt_opt_encoding(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)364c0855460Schristos dt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
365c0855460Schristos {
366c0855460Schristos 	if (arg == NULL)
367c0855460Schristos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
368c0855460Schristos 
369c0855460Schristos 	if (strcmp(arg, "ascii") == 0)
370c0855460Schristos 		dtp->dt_encoding = DT_ENCODING_ASCII;
371c0855460Schristos 	else if (strcmp(arg, "utf8") == 0)
372c0855460Schristos 		dtp->dt_encoding = DT_ENCODING_UTF8;
373c0855460Schristos 	else
374c0855460Schristos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
375c0855460Schristos 
376c0855460Schristos 	return (0);
377c0855460Schristos }
378c0855460Schristos 
379c0855460Schristos /*ARGSUSED*/
380c0855460Schristos static int
dt_opt_evaltime(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)381a864dc36Sdarran dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
382a864dc36Sdarran {
383a864dc36Sdarran 	if (arg == NULL)
384a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
385a864dc36Sdarran 
386a864dc36Sdarran 	if (strcmp(arg, "exec") == 0)
387a864dc36Sdarran 		dtp->dt_prcmode = DT_PROC_STOP_CREATE;
388a864dc36Sdarran 	else if (strcmp(arg, "preinit") == 0)
389a864dc36Sdarran 		dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
390a864dc36Sdarran 	else if (strcmp(arg, "postinit") == 0)
391a864dc36Sdarran 		dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
392a864dc36Sdarran 	else if (strcmp(arg, "main") == 0)
393a864dc36Sdarran 		dtp->dt_prcmode = DT_PROC_STOP_MAIN;
394a864dc36Sdarran 	else
395a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
396a864dc36Sdarran 
397a864dc36Sdarran 	return (0);
398a864dc36Sdarran }
399a864dc36Sdarran 
400a864dc36Sdarran /*ARGSUSED*/
401a864dc36Sdarran static int
dt_opt_pgmax(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)402a864dc36Sdarran dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
403a864dc36Sdarran {
404a864dc36Sdarran 	int n;
405a864dc36Sdarran 
406a864dc36Sdarran 	if (arg == NULL || (n = atoi(arg)) < 0)
407a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
408a864dc36Sdarran 
409a864dc36Sdarran 	dtp->dt_procs->dph_lrulim = n;
410a864dc36Sdarran 	return (0);
411a864dc36Sdarran }
412a864dc36Sdarran 
413c0855460Schristos static int
dt_opt_setenv(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)414c0855460Schristos dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
415c0855460Schristos {
416c0855460Schristos 	char **p;
417c0855460Schristos 	char *var;
418c0855460Schristos 	int i;
419c0855460Schristos 
420c0855460Schristos 	/*
421c0855460Schristos 	 * We can't effectively set environment variables from #pragma lines
422c0855460Schristos 	 * since the processes have already been spawned.
423c0855460Schristos 	 */
424c0855460Schristos 	if (dtp->dt_pcb != NULL)
425c0855460Schristos 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
426c0855460Schristos 
427c0855460Schristos 	if (arg == NULL)
428c0855460Schristos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
429c0855460Schristos 
430c0855460Schristos 	if (!option && strchr(arg, '=') != NULL)
431c0855460Schristos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
432c0855460Schristos 
433c0855460Schristos 	for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++)
434c0855460Schristos 		continue;
435c0855460Schristos 
436c0855460Schristos 	for (p = dtp->dt_proc_env; *p != NULL; p++) {
437c0855460Schristos 		var = strchr(*p, '=');
438c0855460Schristos 		if (var == NULL)
439c0855460Schristos 			var = *p + strlen(*p);
440c0855460Schristos 		if (strncmp(*p, arg, var - *p) == 0) {
441c0855460Schristos 			dt_free(dtp, *p);
442c0855460Schristos 			*p = dtp->dt_proc_env[i - 1];
443c0855460Schristos 			dtp->dt_proc_env[i - 1] = NULL;
444c0855460Schristos 			i--;
445c0855460Schristos 		}
446c0855460Schristos 	}
447c0855460Schristos 
448c0855460Schristos 	if (option) {
449c0855460Schristos 		if ((var = strdup(arg)) == NULL)
450c0855460Schristos 			return (dt_set_errno(dtp, EDT_NOMEM));
451c0855460Schristos 
452c0855460Schristos 		if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) {
453c0855460Schristos 			dt_free(dtp, var);
454c0855460Schristos 			return (dt_set_errno(dtp, EDT_NOMEM));
455c0855460Schristos 		}
456c0855460Schristos 
457c0855460Schristos 		bcopy(dtp->dt_proc_env, p, sizeof (char *) * i);
458c0855460Schristos 		dt_free(dtp, dtp->dt_proc_env);
459c0855460Schristos 		dtp->dt_proc_env = p;
460c0855460Schristos 
461c0855460Schristos 		dtp->dt_proc_env[i - 1] = var;
462c0855460Schristos 		dtp->dt_proc_env[i] = NULL;
463c0855460Schristos 	}
464c0855460Schristos 
465c0855460Schristos 	return (0);
466c0855460Schristos }
467c0855460Schristos 
468a864dc36Sdarran /*ARGSUSED*/
469a864dc36Sdarran static int
dt_opt_stdc(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)470a864dc36Sdarran dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
471a864dc36Sdarran {
472a864dc36Sdarran 	if (arg == NULL)
473a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
474a864dc36Sdarran 
475a864dc36Sdarran 	if (dtp->dt_pcb != NULL)
476a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
477a864dc36Sdarran 
478a864dc36Sdarran 	if (strcmp(arg, "a") == 0)
479a864dc36Sdarran 		dtp->dt_stdcmode = DT_STDC_XA;
480a864dc36Sdarran 	else if (strcmp(arg, "c") == 0)
481a864dc36Sdarran 		dtp->dt_stdcmode = DT_STDC_XC;
482a864dc36Sdarran 	else if (strcmp(arg, "s") == 0)
483a864dc36Sdarran 		dtp->dt_stdcmode = DT_STDC_XS;
484a864dc36Sdarran 	else if (strcmp(arg, "t") == 0)
485a864dc36Sdarran 		dtp->dt_stdcmode = DT_STDC_XT;
486a864dc36Sdarran 	else
487a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
488a864dc36Sdarran 
489a864dc36Sdarran 	return (0);
490a864dc36Sdarran }
491a864dc36Sdarran 
492a864dc36Sdarran /*ARGSUSED*/
493a864dc36Sdarran static int
dt_opt_syslibdir(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)494a864dc36Sdarran dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
495a864dc36Sdarran {
496a864dc36Sdarran 	dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
497a864dc36Sdarran 	char *path;
498a864dc36Sdarran 
499a864dc36Sdarran 	if (arg == NULL)
500a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
501a864dc36Sdarran 
502a864dc36Sdarran 	if ((path = strdup(arg)) == NULL)
503a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_NOMEM));
504a864dc36Sdarran 
505a864dc36Sdarran 	free(dp->dir_path);
506a864dc36Sdarran 	dp->dir_path = path;
507a864dc36Sdarran 
508a864dc36Sdarran 	return (0);
509a864dc36Sdarran }
510a864dc36Sdarran 
511a864dc36Sdarran /*ARGSUSED*/
512a864dc36Sdarran static int
dt_opt_tree(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)513a864dc36Sdarran dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
514a864dc36Sdarran {
515a864dc36Sdarran 	int m;
516a864dc36Sdarran 
517a864dc36Sdarran 	if (arg == NULL || (m = atoi(arg)) <= 0)
518a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
519a864dc36Sdarran 
520a864dc36Sdarran 	dtp->dt_treedump = m;
521a864dc36Sdarran 	return (0);
522a864dc36Sdarran }
523a864dc36Sdarran 
524a864dc36Sdarran /*ARGSUSED*/
525a864dc36Sdarran static int
dt_opt_tregs(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)526a864dc36Sdarran dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
527a864dc36Sdarran {
528a864dc36Sdarran 	int n;
529a864dc36Sdarran 
530a864dc36Sdarran 	if (arg == NULL || (n = atoi(arg)) <= 0)
531a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
532a864dc36Sdarran 
533a864dc36Sdarran 	dtp->dt_conf.dtc_diftupregs = n;
534a864dc36Sdarran 	return (0);
535a864dc36Sdarran }
536a864dc36Sdarran 
537a864dc36Sdarran /*ARGSUSED*/
538a864dc36Sdarran static int
dt_opt_xlate(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)539a864dc36Sdarran dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
540a864dc36Sdarran {
541a864dc36Sdarran 	if (arg == NULL)
542a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
543a864dc36Sdarran 
544a864dc36Sdarran 	if (strcmp(arg, "dynamic") == 0)
545a864dc36Sdarran 		dtp->dt_xlatemode = DT_XL_DYNAMIC;
546a864dc36Sdarran 	else if (strcmp(arg, "static") == 0)
547a864dc36Sdarran 		dtp->dt_xlatemode = DT_XL_STATIC;
548a864dc36Sdarran 	else
549a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
550a864dc36Sdarran 
551a864dc36Sdarran 	return (0);
552a864dc36Sdarran }
553a864dc36Sdarran 
554a864dc36Sdarran /*ARGSUSED*/
555a864dc36Sdarran static int
dt_opt_cflags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)556a864dc36Sdarran dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
557a864dc36Sdarran {
558a864dc36Sdarran 	if (arg != NULL)
559a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
560a864dc36Sdarran 
561a864dc36Sdarran 	if (dtp->dt_pcb != NULL)
562a864dc36Sdarran 		dtp->dt_pcb->pcb_cflags |= option;
563a864dc36Sdarran 	else
564a864dc36Sdarran 		dtp->dt_cflags |= option;
565a864dc36Sdarran 
566a864dc36Sdarran 	return (0);
567a864dc36Sdarran }
568a864dc36Sdarran 
569a864dc36Sdarran static int
dt_opt_dflags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)570a864dc36Sdarran dt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
571a864dc36Sdarran {
572a864dc36Sdarran 	if (arg != NULL)
573a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
574a864dc36Sdarran 
575a864dc36Sdarran 	dtp->dt_dflags |= option;
576a864dc36Sdarran 	return (0);
577a864dc36Sdarran }
578a864dc36Sdarran 
579a864dc36Sdarran static int
dt_opt_invcflags(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)580a864dc36Sdarran dt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
581a864dc36Sdarran {
582a864dc36Sdarran 	if (arg != NULL)
583a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
584a864dc36Sdarran 
585a864dc36Sdarran 	if (dtp->dt_pcb != NULL)
586a864dc36Sdarran 		dtp->dt_pcb->pcb_cflags &= ~option;
587a864dc36Sdarran 	else
588a864dc36Sdarran 		dtp->dt_cflags &= ~option;
589a864dc36Sdarran 
590a864dc36Sdarran 	return (0);
591a864dc36Sdarran }
592a864dc36Sdarran 
593a864dc36Sdarran /*ARGSUSED*/
594a864dc36Sdarran static int
dt_opt_version(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)595a864dc36Sdarran dt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
596a864dc36Sdarran {
597a864dc36Sdarran 	dt_version_t v;
598a864dc36Sdarran 
599a864dc36Sdarran 	if (arg == NULL)
600a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
601a864dc36Sdarran 
602a864dc36Sdarran 	if (dt_version_str2num(arg, &v) == -1)
603a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_VERSINVAL));
604a864dc36Sdarran 
605a864dc36Sdarran 	if (!dt_version_defined(v))
606a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_VERSUNDEF));
607a864dc36Sdarran 
608a864dc36Sdarran 	return (dt_reduce(dtp, v));
609a864dc36Sdarran }
610a864dc36Sdarran 
611a864dc36Sdarran static int
dt_opt_runtime(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)612a864dc36Sdarran dt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
613a864dc36Sdarran {
614a864dc36Sdarran 	char *end;
615a864dc36Sdarran 	dtrace_optval_t val = 0;
616a864dc36Sdarran 	int i;
617a864dc36Sdarran 
618a864dc36Sdarran 	const struct {
619a864dc36Sdarran 		char *positive;
620a864dc36Sdarran 		char *negative;
621a864dc36Sdarran 	} couples[] = {
622a864dc36Sdarran 		{ "yes",	"no" },
623a864dc36Sdarran 		{ "enable",	"disable" },
624a864dc36Sdarran 		{ "enabled",	"disabled" },
625a864dc36Sdarran 		{ "true",	"false" },
626a864dc36Sdarran 		{ "on",		"off" },
627a864dc36Sdarran 		{ "set",	"unset" },
628a864dc36Sdarran 		{ NULL }
629a864dc36Sdarran 	};
630a864dc36Sdarran 
631a864dc36Sdarran 	if (arg != NULL) {
632a864dc36Sdarran 		if (arg[0] == '\0') {
633a864dc36Sdarran 			val = DTRACEOPT_UNSET;
634a864dc36Sdarran 			goto out;
635a864dc36Sdarran 		}
636a864dc36Sdarran 
637a864dc36Sdarran 		for (i = 0; couples[i].positive != NULL; i++) {
638a864dc36Sdarran 			if (strcasecmp(couples[i].positive, arg) == 0) {
639a864dc36Sdarran 				val = 1;
640a864dc36Sdarran 				goto out;
641a864dc36Sdarran 			}
642a864dc36Sdarran 
643a864dc36Sdarran 			if (strcasecmp(couples[i].negative, arg) == 0) {
644a864dc36Sdarran 				val = DTRACEOPT_UNSET;
645a864dc36Sdarran 				goto out;
646a864dc36Sdarran 			}
647a864dc36Sdarran 		}
648a864dc36Sdarran 
649a864dc36Sdarran 		errno = 0;
650a864dc36Sdarran 		val = strtoull(arg, &end, 0);
651a864dc36Sdarran 
652a864dc36Sdarran 		if (*end != '\0' || errno != 0 || val < 0)
653a864dc36Sdarran 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
654a864dc36Sdarran 	}
655a864dc36Sdarran 
656a864dc36Sdarran out:
657a864dc36Sdarran 	dtp->dt_options[option] = val;
658a864dc36Sdarran 	return (0);
659a864dc36Sdarran }
660a864dc36Sdarran 
661a864dc36Sdarran static int
dt_optval_parse(const char * arg,dtrace_optval_t * rval)662a864dc36Sdarran dt_optval_parse(const char *arg, dtrace_optval_t *rval)
663a864dc36Sdarran {
664a864dc36Sdarran 	dtrace_optval_t mul = 1;
665a864dc36Sdarran 	size_t len;
666a864dc36Sdarran 	char *end;
667a864dc36Sdarran 
668a864dc36Sdarran 	len = strlen(arg);
669a864dc36Sdarran 	errno = 0;
670a864dc36Sdarran 
671a864dc36Sdarran 	switch (arg[len - 1]) {
672a864dc36Sdarran 	case 't':
673a864dc36Sdarran 	case 'T':
674a864dc36Sdarran 		mul *= 1024;
675a864dc36Sdarran 		/*FALLTHRU*/
676a864dc36Sdarran 	case 'g':
677a864dc36Sdarran 	case 'G':
678a864dc36Sdarran 		mul *= 1024;
679a864dc36Sdarran 		/*FALLTHRU*/
680a864dc36Sdarran 	case 'm':
681a864dc36Sdarran 	case 'M':
682a864dc36Sdarran 		mul *= 1024;
683a864dc36Sdarran 		/*FALLTHRU*/
684a864dc36Sdarran 	case 'k':
685a864dc36Sdarran 	case 'K':
686a864dc36Sdarran 		mul *= 1024;
687a864dc36Sdarran 		/*FALLTHRU*/
688a864dc36Sdarran 	default:
689a864dc36Sdarran 		break;
690a864dc36Sdarran 	}
691a864dc36Sdarran 
692a864dc36Sdarran 	errno = 0;
693a864dc36Sdarran 	*rval = strtoull(arg, &end, 0) * mul;
694a864dc36Sdarran 
695a864dc36Sdarran 	if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') ||
696a864dc36Sdarran 	    *rval < 0 || errno != 0)
697a864dc36Sdarran 		return (-1);
698a864dc36Sdarran 
699a864dc36Sdarran 	return (0);
700a864dc36Sdarran }
701a864dc36Sdarran 
702a864dc36Sdarran static int
dt_opt_size(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)703a864dc36Sdarran dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
704a864dc36Sdarran {
705a864dc36Sdarran 	dtrace_optval_t val = 0;
706a864dc36Sdarran 
707a864dc36Sdarran 	if (arg != NULL && dt_optval_parse(arg, &val) != 0)
708a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
709a864dc36Sdarran 
710a864dc36Sdarran 	dtp->dt_options[option] = val;
711a864dc36Sdarran 	return (0);
712a864dc36Sdarran }
713a864dc36Sdarran 
714a864dc36Sdarran static int
dt_opt_rate(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)715a864dc36Sdarran dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
716a864dc36Sdarran {
717a864dc36Sdarran 	char *end;
718a864dc36Sdarran 	int i;
719a864dc36Sdarran 	dtrace_optval_t mul = 1, val = 0;
720a864dc36Sdarran 
721a864dc36Sdarran 	const struct {
722a864dc36Sdarran 		char *name;
723a864dc36Sdarran 		hrtime_t mul;
724a864dc36Sdarran 	} suffix[] = {
725a864dc36Sdarran 		{ "ns", 	NANOSEC / NANOSEC },
726a864dc36Sdarran 		{ "nsec",	NANOSEC / NANOSEC },
727a864dc36Sdarran 		{ "us",		NANOSEC / MICROSEC },
728a864dc36Sdarran 		{ "usec",	NANOSEC / MICROSEC },
729a864dc36Sdarran 		{ "ms",		NANOSEC / MILLISEC },
730a864dc36Sdarran 		{ "msec",	NANOSEC / MILLISEC },
731a864dc36Sdarran 		{ "s",		NANOSEC / SEC },
732a864dc36Sdarran 		{ "sec",	NANOSEC / SEC },
733a864dc36Sdarran 		{ "m",		NANOSEC * (hrtime_t)60 },
734a864dc36Sdarran 		{ "min",	NANOSEC * (hrtime_t)60 },
735a864dc36Sdarran 		{ "h",		NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
736a864dc36Sdarran 		{ "hour",	NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
737a864dc36Sdarran 		{ "d",		NANOSEC * (hrtime_t)(24 * 60 * 60) },
738a864dc36Sdarran 		{ "day",	NANOSEC * (hrtime_t)(24 * 60 * 60) },
739a864dc36Sdarran 		{ "hz",		0 },
740a864dc36Sdarran 		{ NULL }
741a864dc36Sdarran 	};
742a864dc36Sdarran 
743a864dc36Sdarran 	if (arg != NULL) {
744a864dc36Sdarran 		errno = 0;
745a864dc36Sdarran 		val = strtoull(arg, &end, 0);
746a864dc36Sdarran 
747a864dc36Sdarran 		for (i = 0; suffix[i].name != NULL; i++) {
748a864dc36Sdarran 			if (strcasecmp(suffix[i].name, end) == 0) {
749a864dc36Sdarran 				mul = suffix[i].mul;
750a864dc36Sdarran 				break;
751a864dc36Sdarran 			}
752a864dc36Sdarran 		}
753a864dc36Sdarran 
754ba2539a9Schs 		if (suffix[i].name == NULL && *end != '\0' || val < 0)
755a864dc36Sdarran 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
756a864dc36Sdarran 
757a864dc36Sdarran 		if (mul == 0) {
758a864dc36Sdarran 			/*
759a864dc36Sdarran 			 * The rate has been specified in frequency-per-second.
760a864dc36Sdarran 			 */
761a864dc36Sdarran 			if (val != 0)
762a864dc36Sdarran 				val = NANOSEC / val;
763a864dc36Sdarran 		} else {
764a864dc36Sdarran 			val *= mul;
765a864dc36Sdarran 		}
766a864dc36Sdarran 	}
767a864dc36Sdarran 
768a864dc36Sdarran 	dtp->dt_options[option] = val;
769a864dc36Sdarran 	return (0);
770a864dc36Sdarran }
771a864dc36Sdarran 
772a864dc36Sdarran /*
773a864dc36Sdarran  * When setting the strsize option, set the option in the dt_options array
774a864dc36Sdarran  * using dt_opt_size() as usual, and then update the definition of the CTF
775a864dc36Sdarran  * type for the D intrinsic "string" to be an array of the corresponding size.
776a864dc36Sdarran  * If any errors occur, reset dt_options[option] to its previous value.
777a864dc36Sdarran  */
778a864dc36Sdarran static int
dt_opt_strsize(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)779a864dc36Sdarran dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
780a864dc36Sdarran {
781a864dc36Sdarran 	dtrace_optval_t val = dtp->dt_options[option];
782a864dc36Sdarran 	ctf_file_t *fp = DT_STR_CTFP(dtp);
783a864dc36Sdarran 	ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp));
784a864dc36Sdarran 	ctf_arinfo_t r;
785a864dc36Sdarran 
786a864dc36Sdarran 	if (dt_opt_size(dtp, arg, option) != 0)
787a864dc36Sdarran 		return (-1); /* dt_errno is set for us */
788a864dc36Sdarran 
789a864dc36Sdarran 	if (dtp->dt_options[option] > UINT_MAX) {
790a864dc36Sdarran 		dtp->dt_options[option] = val;
791a864dc36Sdarran 		return (dt_set_errno(dtp, EOVERFLOW));
792a864dc36Sdarran 	}
793a864dc36Sdarran 
794a864dc36Sdarran 	if (ctf_array_info(fp, type, &r) == CTF_ERR) {
795a864dc36Sdarran 		dtp->dt_options[option] = val;
796a864dc36Sdarran 		dtp->dt_ctferr = ctf_errno(fp);
797a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_CTF));
798a864dc36Sdarran 	}
799a864dc36Sdarran 
800a864dc36Sdarran 	r.ctr_nelems = (uint_t)dtp->dt_options[option];
801a864dc36Sdarran 
802a864dc36Sdarran 	if (ctf_set_array(fp, type, &r) == CTF_ERR ||
803a864dc36Sdarran 	    ctf_update(fp) == CTF_ERR) {
804a864dc36Sdarran 		dtp->dt_options[option] = val;
805a864dc36Sdarran 		dtp->dt_ctferr = ctf_errno(fp);
806a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_CTF));
807a864dc36Sdarran 	}
808a864dc36Sdarran 
809a864dc36Sdarran 	return (0);
810a864dc36Sdarran }
811a864dc36Sdarran 
812a864dc36Sdarran static const struct {
813a864dc36Sdarran 	const char *dtbp_name;
814a864dc36Sdarran 	int dtbp_policy;
815a864dc36Sdarran } _dtrace_bufpolicies[] = {
816a864dc36Sdarran 	{ "ring", DTRACEOPT_BUFPOLICY_RING },
817a864dc36Sdarran 	{ "fill", DTRACEOPT_BUFPOLICY_FILL },
818a864dc36Sdarran 	{ "switch", DTRACEOPT_BUFPOLICY_SWITCH },
819a864dc36Sdarran 	{ NULL, 0 }
820a864dc36Sdarran };
821a864dc36Sdarran 
822a864dc36Sdarran /*ARGSUSED*/
823a864dc36Sdarran static int
dt_opt_bufpolicy(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)824a864dc36Sdarran dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
825a864dc36Sdarran {
826a864dc36Sdarran 	dtrace_optval_t policy = DTRACEOPT_UNSET;
827a864dc36Sdarran 	int i;
828a864dc36Sdarran 
829a864dc36Sdarran 	if (arg == NULL)
830a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
831a864dc36Sdarran 
832a864dc36Sdarran 	for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) {
833a864dc36Sdarran 		if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) {
834a864dc36Sdarran 			policy = _dtrace_bufpolicies[i].dtbp_policy;
835a864dc36Sdarran 			break;
836a864dc36Sdarran 		}
837a864dc36Sdarran 	}
838a864dc36Sdarran 
839a864dc36Sdarran 	if (policy == DTRACEOPT_UNSET)
840a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
841a864dc36Sdarran 
842a864dc36Sdarran 	dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy;
843a864dc36Sdarran 
844a864dc36Sdarran 	return (0);
845a864dc36Sdarran }
846a864dc36Sdarran 
847a864dc36Sdarran static const struct {
848a864dc36Sdarran 	const char *dtbr_name;
849a864dc36Sdarran 	int dtbr_policy;
850a864dc36Sdarran } _dtrace_bufresize[] = {
851a864dc36Sdarran 	{ "auto", DTRACEOPT_BUFRESIZE_AUTO },
852a864dc36Sdarran 	{ "manual", DTRACEOPT_BUFRESIZE_MANUAL },
853a864dc36Sdarran 	{ NULL, 0 }
854a864dc36Sdarran };
855a864dc36Sdarran 
856a864dc36Sdarran /*ARGSUSED*/
857a864dc36Sdarran static int
dt_opt_bufresize(dtrace_hdl_t * dtp,const char * arg,uintptr_t option)858a864dc36Sdarran dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
859a864dc36Sdarran {
860a864dc36Sdarran 	dtrace_optval_t policy = DTRACEOPT_UNSET;
861a864dc36Sdarran 	int i;
862a864dc36Sdarran 
863a864dc36Sdarran 	if (arg == NULL)
864a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
865a864dc36Sdarran 
866a864dc36Sdarran 	for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) {
867a864dc36Sdarran 		if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) {
868a864dc36Sdarran 			policy = _dtrace_bufresize[i].dtbr_policy;
869a864dc36Sdarran 			break;
870a864dc36Sdarran 		}
871a864dc36Sdarran 	}
872a864dc36Sdarran 
873a864dc36Sdarran 	if (policy == DTRACEOPT_UNSET)
874a864dc36Sdarran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
875a864dc36Sdarran 
876a864dc36Sdarran 	dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy;
877a864dc36Sdarran 
878a864dc36Sdarran 	return (0);
879a864dc36Sdarran }
880a864dc36Sdarran 
881a864dc36Sdarran int
dt_options_load(dtrace_hdl_t * dtp)882a864dc36Sdarran dt_options_load(dtrace_hdl_t *dtp)
883a864dc36Sdarran {
884a864dc36Sdarran 	dof_hdr_t hdr, *dof;
885c0855460Schristos 	dof_sec_t *sec = NULL;	// XXX: gcc
886a864dc36Sdarran 	size_t offs;
887a864dc36Sdarran 	int i;
888a864dc36Sdarran 
889a864dc36Sdarran 	/*
890a864dc36Sdarran 	 * To load the option values, we need to ask the kernel to provide its
891a864dc36Sdarran 	 * DOF, which we'll sift through to look for OPTDESC sections.
892a864dc36Sdarran 	 */
893a864dc36Sdarran 	bzero(&hdr, sizeof (dof_hdr_t));
894a864dc36Sdarran 	hdr.dofh_loadsz = sizeof (dof_hdr_t);
895a864dc36Sdarran 
896c0855460Schristos #ifdef illumos
897a864dc36Sdarran 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1)
898bb8023b5Sdarran #else
899bb8023b5Sdarran 	dof = &hdr;
900bb8023b5Sdarran 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)
901bb8023b5Sdarran #endif
902a864dc36Sdarran 		return (dt_set_errno(dtp, errno));
903a864dc36Sdarran 
904a864dc36Sdarran 	if (hdr.dofh_loadsz < sizeof (dof_hdr_t))
905a864dc36Sdarran 		return (dt_set_errno(dtp, EINVAL));
906a864dc36Sdarran 
907*86b0983bSchristos 	dof = calloc(hdr.dofh_loadsz, 1);
908*86b0983bSchristos 	if (dof == NULL)
909*86b0983bSchristos 		return (dt_set_errno(dtp, errno));
910a864dc36Sdarran 	dof->dofh_loadsz = hdr.dofh_loadsz;
911a864dc36Sdarran 
912a864dc36Sdarran 	for (i = 0; i < DTRACEOPT_MAX; i++)
913a864dc36Sdarran 		dtp->dt_options[i] = DTRACEOPT_UNSET;
914a864dc36Sdarran 
915c0855460Schristos #ifdef illumos
916a864dc36Sdarran 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1)
917bb8023b5Sdarran #else
918bb8023b5Sdarran 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)
919bb8023b5Sdarran #endif
920*86b0983bSchristos 	{
921*86b0983bSchristos 		free(dof);
922a864dc36Sdarran 		return (dt_set_errno(dtp, errno));
923*86b0983bSchristos 	}
924a864dc36Sdarran 
925a864dc36Sdarran 	for (i = 0; i < dof->dofh_secnum; i++) {
926a864dc36Sdarran 		sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof +
927a864dc36Sdarran 		    dof->dofh_secoff + i * dof->dofh_secsize);
928a864dc36Sdarran 
929a864dc36Sdarran 		if (sec->dofs_type != DOF_SECT_OPTDESC)
930a864dc36Sdarran 			continue;
931a864dc36Sdarran 
932a864dc36Sdarran 		break;
933a864dc36Sdarran 	}
934a864dc36Sdarran 
935a864dc36Sdarran 	for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {
936a864dc36Sdarran 		dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t)
937a864dc36Sdarran 		    ((uintptr_t)dof + sec->dofs_offset + offs);
938a864dc36Sdarran 
939a864dc36Sdarran 		if (opt->dofo_strtab != DOF_SECIDX_NONE)
940a864dc36Sdarran 			continue;
941a864dc36Sdarran 
942a864dc36Sdarran 		if (opt->dofo_option >= DTRACEOPT_MAX)
943a864dc36Sdarran 			continue;
944a864dc36Sdarran 
945a864dc36Sdarran 		dtp->dt_options[opt->dofo_option] = opt->dofo_value;
946a864dc36Sdarran 	}
947*86b0983bSchristos 	free(dof);
948a864dc36Sdarran 	return (0);
949a864dc36Sdarran }
950a864dc36Sdarran 
951a864dc36Sdarran typedef struct dt_option {
952a864dc36Sdarran 	const char *o_name;
953a864dc36Sdarran 	int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
954a864dc36Sdarran 	uintptr_t o_option;
955a864dc36Sdarran } dt_option_t;
956a864dc36Sdarran 
957a864dc36Sdarran /*
958a864dc36Sdarran  * Compile-time options.
959a864dc36Sdarran  */
960a864dc36Sdarran static const dt_option_t _dtrace_ctoptions[] = {
961a864dc36Sdarran 	{ "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU },
962a864dc36Sdarran 	{ "amin", dt_opt_amin },
963a864dc36Sdarran 	{ "argref", dt_opt_cflags, DTRACE_C_ARGREF },
964a864dc36Sdarran 	{ "core", dt_opt_core },
965a864dc36Sdarran 	{ "cpp", dt_opt_cflags, DTRACE_C_CPP },
966a864dc36Sdarran 	{ "cpphdrs", dt_opt_cpp_hdrs },
967a864dc36Sdarran 	{ "cpppath", dt_opt_cpp_path },
968a864dc36Sdarran 	{ "ctypes", dt_opt_ctypes },
969a864dc36Sdarran 	{ "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG },
970a864dc36Sdarran 	{ "dtypes", dt_opt_dtypes },
971a864dc36Sdarran 	{ "debug", dt_opt_debug },
972a864dc36Sdarran 	{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
973a864dc36Sdarran 	{ "droptags", dt_opt_droptags },
974a864dc36Sdarran 	{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
975c0855460Schristos 	{ "encoding", dt_opt_encoding },
976a864dc36Sdarran 	{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
977a864dc36Sdarran 	{ "evaltime", dt_opt_evaltime },
978a864dc36Sdarran 	{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
979a864dc36Sdarran 	{ "iregs", dt_opt_iregs },
980a864dc36Sdarran 	{ "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF },
981a864dc36Sdarran 	{ "knodefs", dt_opt_cflags, DTRACE_C_KNODEF },
982a864dc36Sdarran 	{ "late", dt_opt_xlate },
983a864dc36Sdarran 	{ "lazyload", dt_opt_lazyload },
984a864dc36Sdarran 	{ "ldpath", dt_opt_ld_path },
985a864dc36Sdarran 	{ "libdir", dt_opt_libdir },
986a864dc36Sdarran 	{ "linkmode", dt_opt_linkmode },
987a864dc36Sdarran 	{ "linktype", dt_opt_linktype },
988a864dc36Sdarran 	{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
989c0855460Schristos #if defined(__FreeBSD__) || defined(__NetBSD__)
990c0855460Schristos 	{ "objcopypath", dt_opt_objcopy_path },
991c0855460Schristos #endif
992a864dc36Sdarran 	{ "pgmax", dt_opt_pgmax },
993a864dc36Sdarran 	{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
994c0855460Schristos 	{ "setenv", dt_opt_setenv, 1 },
995a864dc36Sdarran 	{ "stdc", dt_opt_stdc },
996a864dc36Sdarran 	{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
997a864dc36Sdarran 	{ "syslibdir", dt_opt_syslibdir },
998a864dc36Sdarran 	{ "tree", dt_opt_tree },
999a864dc36Sdarran 	{ "tregs", dt_opt_tregs },
1000a864dc36Sdarran 	{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
1001a864dc36Sdarran 	{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
1002a864dc36Sdarran 	{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
1003c0855460Schristos 	{ "unsetenv", dt_opt_setenv, 0 },
1004a864dc36Sdarran 	{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
1005a864dc36Sdarran 	{ "version", dt_opt_version },
1006a864dc36Sdarran 	{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
1007bb8023b5Sdarran 	{ NULL, NULL, 0 }
1008a864dc36Sdarran };
1009a864dc36Sdarran 
1010a864dc36Sdarran /*
1011a864dc36Sdarran  * Run-time options.
1012a864dc36Sdarran  */
1013a864dc36Sdarran static const dt_option_t _dtrace_rtoptions[] = {
1014a864dc36Sdarran 	{ "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE },
1015a864dc36Sdarran 	{ "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE },
1016a864dc36Sdarran 	{ "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY },
1017a864dc36Sdarran 	{ "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE },
1018a864dc36Sdarran 	{ "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE },
1019a864dc36Sdarran 	{ "cpu", dt_opt_runtime, DTRACEOPT_CPU },
1020a864dc36Sdarran 	{ "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE },
1021a864dc36Sdarran 	{ "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE },
1022a864dc36Sdarran 	{ "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON },
1023a864dc36Sdarran 	{ "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES },
1024a864dc36Sdarran 	{ "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE },
1025a864dc36Sdarran 	{ "nspec", dt_opt_runtime, DTRACEOPT_NSPEC },
1026a864dc36Sdarran 	{ "specsize", dt_opt_size, DTRACEOPT_SPECSIZE },
1027a864dc36Sdarran 	{ "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES },
1028a864dc36Sdarran 	{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
1029a864dc36Sdarran 	{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
1030a864dc36Sdarran 	{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
1031c0855460Schristos 	{ "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },
1032bb8023b5Sdarran 	{ NULL, NULL, 0 }
1033a864dc36Sdarran };
1034a864dc36Sdarran 
1035a864dc36Sdarran /*
1036a864dc36Sdarran  * Dynamic run-time options.
1037a864dc36Sdarran  */
1038a864dc36Sdarran static const dt_option_t _dtrace_drtoptions[] = {
1039c0855460Schristos 	{ "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST },
1040c0855460Schristos 	{ "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK },
1041a864dc36Sdarran 	{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
1042a864dc36Sdarran 	{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },
1043a864dc36Sdarran 	{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },
1044a864dc36Sdarran 	{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },
1045a864dc36Sdarran 	{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },
1046c0855460Schristos 	{ "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM },
1047a864dc36Sdarran 	{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
1048a864dc36Sdarran 	{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
1049a864dc36Sdarran 	{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
1050a864dc36Sdarran 	{ "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT },
1051a864dc36Sdarran 	{ "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE },
1052bb8023b5Sdarran 	{ NULL, NULL, 0 }
1053a864dc36Sdarran };
1054a864dc36Sdarran 
1055a864dc36Sdarran int
dtrace_getopt(dtrace_hdl_t * dtp,const char * opt,dtrace_optval_t * val)1056a864dc36Sdarran dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val)
1057a864dc36Sdarran {
1058a864dc36Sdarran 	const dt_option_t *op;
1059a864dc36Sdarran 
1060a864dc36Sdarran 	if (opt == NULL)
1061a864dc36Sdarran 		return (dt_set_errno(dtp, EINVAL));
1062a864dc36Sdarran 
1063a864dc36Sdarran 	/*
1064a864dc36Sdarran 	 * We only need to search the run-time options -- it's not legal
1065a864dc36Sdarran 	 * to get the values of compile-time options.
1066a864dc36Sdarran 	 */
1067a864dc36Sdarran 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
1068a864dc36Sdarran 		if (strcmp(op->o_name, opt) == 0) {
1069a864dc36Sdarran 			*val = dtp->dt_options[op->o_option];
1070a864dc36Sdarran 			return (0);
1071a864dc36Sdarran 		}
1072a864dc36Sdarran 	}
1073a864dc36Sdarran 
1074a864dc36Sdarran 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
1075a864dc36Sdarran 		if (strcmp(op->o_name, opt) == 0) {
1076a864dc36Sdarran 			*val = dtp->dt_options[op->o_option];
1077a864dc36Sdarran 			return (0);
1078a864dc36Sdarran 		}
1079a864dc36Sdarran 	}
1080a864dc36Sdarran 
1081a864dc36Sdarran 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
1082a864dc36Sdarran }
1083a864dc36Sdarran 
1084a864dc36Sdarran int
dtrace_setopt(dtrace_hdl_t * dtp,const char * opt,const char * val)1085a864dc36Sdarran dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val)
1086a864dc36Sdarran {
1087a864dc36Sdarran 	const dt_option_t *op;
1088a864dc36Sdarran 
1089a864dc36Sdarran 	if (opt == NULL)
1090a864dc36Sdarran 		return (dt_set_errno(dtp, EINVAL));
1091a864dc36Sdarran 
1092a864dc36Sdarran 	for (op = _dtrace_ctoptions; op->o_name != NULL; op++) {
1093a864dc36Sdarran 		if (strcmp(op->o_name, opt) == 0)
1094a864dc36Sdarran 			return (op->o_func(dtp, val, op->o_option));
1095a864dc36Sdarran 	}
1096a864dc36Sdarran 
1097a864dc36Sdarran 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
1098a864dc36Sdarran 		if (strcmp(op->o_name, opt) == 0)
1099a864dc36Sdarran 			return (op->o_func(dtp, val, op->o_option));
1100a864dc36Sdarran 	}
1101a864dc36Sdarran 
1102a864dc36Sdarran 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
1103a864dc36Sdarran 		if (strcmp(op->o_name, opt) == 0) {
1104a864dc36Sdarran 			/*
1105a864dc36Sdarran 			 * Only dynamic run-time options may be set while
1106a864dc36Sdarran 			 * tracing is active.
1107a864dc36Sdarran 			 */
1108a864dc36Sdarran 			if (dtp->dt_active)
1109a864dc36Sdarran 				return (dt_set_errno(dtp, EDT_ACTIVE));
1110a864dc36Sdarran 
1111a864dc36Sdarran 			return (op->o_func(dtp, val, op->o_option));
1112a864dc36Sdarran 		}
1113a864dc36Sdarran 	}
1114a864dc36Sdarran 
1115a864dc36Sdarran 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
1116a864dc36Sdarran }
1117