dt_options.c revision 250574
1178479Sjb/*
2178479Sjb * CDDL HEADER START
3178479Sjb *
4178479Sjb * The contents of this file are subject to the terms of the
5178479Sjb * Common Development and Distribution License (the "License").
6178479Sjb * You may not use this file except in compliance with the License.
7178479Sjb *
8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9178479Sjb * or http://www.opensolaris.org/os/licensing.
10178479Sjb * See the License for the specific language governing permissions
11178479Sjb * and limitations under the License.
12178479Sjb *
13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each
14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15178479Sjb * If applicable, add the following below this CDDL HEADER, with the
16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying
17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
18178479Sjb *
19178479Sjb * CDDL HEADER END
20178479Sjb */
21178479Sjb
22178479Sjb/*
23178479Sjb * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24178479Sjb * Use is subject to license terms.
25178479Sjb */
26178479Sjb
27178479Sjb#pragma ident	"%Z%%M%	%I%	%E% SMI"
28178479Sjb
29250574Smarkj/*
30250574Smarkj * Copyright (c) 2012 by Delphix. All rights reserved.
31250574Smarkj */
32250574Smarkj
33178479Sjb#include <sys/resource.h>
34178479Sjb#include <sys/mman.h>
35178479Sjb#include <sys/types.h>
36178479Sjb
37178479Sjb#include <strings.h>
38178479Sjb#include <signal.h>
39178479Sjb#include <stdlib.h>
40178479Sjb#include <unistd.h>
41178479Sjb#include <limits.h>
42178569Sjb#if defined(sun)
43178479Sjb#include <alloca.h>
44178569Sjb#endif
45178479Sjb#include <errno.h>
46178479Sjb#include <fcntl.h>
47178479Sjb
48178479Sjb#include <dt_impl.h>
49178479Sjb#include <dt_string.h>
50178479Sjb
51178479Sjbstatic int
52178479Sjbdt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
53178479Sjb{
54178479Sjb	dt_aggregate_t *agp = &dtp->dt_aggregate;
55178479Sjb
56178479Sjb	if (arg != NULL)
57178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
58178479Sjb
59178479Sjb	agp->dtat_flags |= option;
60178479Sjb	return (0);
61178479Sjb}
62178479Sjb
63178479Sjb/*ARGSUSED*/
64178479Sjbstatic int
65178479Sjbdt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
66178479Sjb{
67178479Sjb	char str[DTRACE_ATTR2STR_MAX];
68178479Sjb	dtrace_attribute_t attr;
69178479Sjb
70178479Sjb	if (arg == NULL || dtrace_str2attr(arg, &attr) == -1)
71178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
72178479Sjb
73178479Sjb	dt_dprintf("set compiler attribute minimum to %s\n",
74178479Sjb	    dtrace_attr2str(attr, str, sizeof (str)));
75178479Sjb
76178479Sjb	if (dtp->dt_pcb != NULL) {
77178479Sjb		dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR;
78178479Sjb		dtp->dt_pcb->pcb_amin = attr;
79178479Sjb	} else {
80178479Sjb		dtp->dt_cflags |= DTRACE_C_EATTR;
81178479Sjb		dtp->dt_amin = attr;
82178479Sjb	}
83178479Sjb
84178479Sjb	return (0);
85178479Sjb}
86178479Sjb
87178479Sjbstatic void
88178479Sjbdt_coredump(void)
89178479Sjb{
90178479Sjb	const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n";
91178479Sjb
92178479Sjb	struct sigaction act;
93178479Sjb	struct rlimit lim;
94178479Sjb
95178479Sjb	(void) write(STDERR_FILENO, msg, sizeof (msg) - 1);
96178479Sjb
97178479Sjb	act.sa_handler = SIG_DFL;
98178479Sjb	act.sa_flags = 0;
99178479Sjb
100178479Sjb	(void) sigemptyset(&act.sa_mask);
101178479Sjb	(void) sigaction(SIGABRT, &act, NULL);
102178479Sjb
103178479Sjb	lim.rlim_cur = RLIM_INFINITY;
104178479Sjb	lim.rlim_max = RLIM_INFINITY;
105178479Sjb
106178479Sjb	(void) setrlimit(RLIMIT_CORE, &lim);
107178479Sjb	abort();
108178479Sjb}
109178479Sjb
110178479Sjb/*ARGSUSED*/
111178479Sjbstatic int
112178479Sjbdt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
113178479Sjb{
114178479Sjb	static int enabled = 0;
115178479Sjb
116178479Sjb	if (arg != NULL)
117178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
118178479Sjb
119178479Sjb	if (enabled++ || atexit(dt_coredump) == 0)
120178479Sjb		return (0);
121178479Sjb
122178479Sjb	return (dt_set_errno(dtp, errno));
123178479Sjb}
124178479Sjb
125178479Sjb/*ARGSUSED*/
126178479Sjbstatic int
127178479Sjbdt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
128178479Sjb{
129178479Sjb	if (arg != NULL)
130178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
131178479Sjb
132178479Sjb	if (dtp->dt_pcb != NULL)
133178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
134178479Sjb
135178479Sjb	if (dt_cpp_add_arg(dtp, "-H") == NULL)
136178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
137178479Sjb
138178479Sjb	return (0);
139178479Sjb}
140178479Sjb
141178479Sjb/*ARGSUSED*/
142178479Sjbstatic int
143178479Sjbdt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
144178479Sjb{
145178479Sjb	char *cpp;
146178479Sjb
147178479Sjb	if (arg == NULL)
148178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
149178479Sjb
150178479Sjb	if (dtp->dt_pcb != NULL)
151178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
152178479Sjb
153178479Sjb	if ((cpp = strdup(arg)) == NULL)
154178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
155178479Sjb
156178479Sjb	dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);
157178479Sjb	free(dtp->dt_cpp_path);
158178479Sjb	dtp->dt_cpp_path = cpp;
159178479Sjb
160178479Sjb	return (0);
161178479Sjb}
162178479Sjb
163178479Sjbstatic int
164178479Sjbdt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
165178479Sjb{
166178479Sjb	char *buf;
167178479Sjb	size_t len;
168178479Sjb	const char *opt = (const char *)option;
169178479Sjb
170178479Sjb	if (opt == NULL || arg == NULL)
171178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
172178479Sjb
173178479Sjb	if (dtp->dt_pcb != NULL)
174178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
175178479Sjb
176178479Sjb	len = strlen(opt) + strlen(arg) + 1;
177178479Sjb	buf = alloca(len);
178178479Sjb
179178479Sjb	(void) strcpy(buf, opt);
180178479Sjb	(void) strcat(buf, arg);
181178479Sjb
182178479Sjb	if (dt_cpp_add_arg(dtp, buf) == NULL)
183178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
184178479Sjb
185178479Sjb	return (0);
186178479Sjb}
187178479Sjb
188178479Sjb/*ARGSUSED*/
189178479Sjbstatic int
190178479Sjbdt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
191178479Sjb{
192178479Sjb	int fd;
193178479Sjb
194178479Sjb	if (arg == NULL)
195178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
196178479Sjb
197178479Sjb	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
198178479Sjb		return (dt_set_errno(dtp, errno));
199178479Sjb
200178479Sjb	(void) close(dtp->dt_cdefs_fd);
201178479Sjb	dtp->dt_cdefs_fd = fd;
202178479Sjb	return (0);
203178479Sjb}
204178479Sjb
205178479Sjb/*ARGSUSED*/
206178479Sjbstatic int
207178479Sjbdt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
208178479Sjb{
209178479Sjb	dtp->dt_droptags = 1;
210178479Sjb	return (0);
211178479Sjb}
212178479Sjb
213178479Sjb/*ARGSUSED*/
214178479Sjbstatic int
215178479Sjbdt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
216178479Sjb{
217178479Sjb	int fd;
218178479Sjb
219178479Sjb	if (arg == NULL)
220178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
221178479Sjb
222178479Sjb	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
223178479Sjb		return (dt_set_errno(dtp, errno));
224178479Sjb
225178479Sjb	(void) close(dtp->dt_ddefs_fd);
226178479Sjb	dtp->dt_ddefs_fd = fd;
227178479Sjb	return (0);
228178479Sjb}
229178479Sjb
230178479Sjb/*ARGSUSED*/
231178479Sjbstatic int
232178479Sjbdt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
233178479Sjb{
234178479Sjb	if (arg != NULL)
235178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
236178479Sjb
237178479Sjb	_dtrace_debug = 1;
238178479Sjb	return (0);
239178479Sjb}
240178479Sjb
241178479Sjb/*ARGSUSED*/
242178479Sjbstatic int
243178479Sjbdt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
244178479Sjb{
245178479Sjb	int n;
246178479Sjb
247178479Sjb	if (arg == NULL || (n = atoi(arg)) <= 0)
248178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
249178479Sjb
250178479Sjb	dtp->dt_conf.dtc_difintregs = n;
251178479Sjb	return (0);
252178479Sjb}
253178479Sjb
254178479Sjb/*ARGSUSED*/
255178479Sjbstatic int
256178479Sjbdt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
257178479Sjb{
258178479Sjb	dtp->dt_lazyload = 1;
259178479Sjb
260178479Sjb	return (0);
261178479Sjb}
262178479Sjb
263178479Sjb/*ARGSUSED*/
264178479Sjbstatic int
265178479Sjbdt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
266178479Sjb{
267178479Sjb	char *ld;
268178479Sjb
269178479Sjb	if (arg == NULL)
270178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
271178479Sjb
272178479Sjb	if (dtp->dt_pcb != NULL)
273178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
274178479Sjb
275178479Sjb	if ((ld = strdup(arg)) == NULL)
276178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
277178479Sjb
278178479Sjb	free(dtp->dt_ld_path);
279178479Sjb	dtp->dt_ld_path = ld;
280178479Sjb
281178479Sjb	return (0);
282178479Sjb}
283178479Sjb
284178479Sjb/*ARGSUSED*/
285178479Sjbstatic int
286178479Sjbdt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
287178479Sjb{
288178479Sjb	dt_dirpath_t *dp;
289178479Sjb
290178479Sjb	if (arg == NULL)
291178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
292178479Sjb
293178479Sjb	if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL ||
294178479Sjb	    (dp->dir_path = strdup(arg)) == NULL) {
295178479Sjb		free(dp);
296178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
297178479Sjb	}
298178479Sjb
299178479Sjb	dt_list_append(&dtp->dt_lib_path, dp);
300178479Sjb	return (0);
301178479Sjb}
302178479Sjb
303178479Sjb/*ARGSUSED*/
304178479Sjbstatic int
305178479Sjbdt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
306178479Sjb{
307178479Sjb	if (arg == NULL)
308178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
309178479Sjb
310178479Sjb	if (strcmp(arg, "kernel") == 0)
311178479Sjb		dtp->dt_linkmode = DT_LINK_KERNEL;
312178479Sjb	else if (strcmp(arg, "primary") == 0)
313178479Sjb		dtp->dt_linkmode = DT_LINK_PRIMARY;
314178479Sjb	else if (strcmp(arg, "dynamic") == 0)
315178479Sjb		dtp->dt_linkmode = DT_LINK_DYNAMIC;
316178479Sjb	else if (strcmp(arg, "static") == 0)
317178479Sjb		dtp->dt_linkmode = DT_LINK_STATIC;
318178479Sjb	else
319178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
320178479Sjb
321178479Sjb	return (0);
322178479Sjb}
323178479Sjb
324178479Sjb/*ARGSUSED*/
325178479Sjbstatic int
326178479Sjbdt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
327178479Sjb{
328178479Sjb	if (arg == NULL)
329178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
330178479Sjb
331178479Sjb	if (strcasecmp(arg, "elf") == 0)
332178479Sjb		dtp->dt_linktype = DT_LTYP_ELF;
333178479Sjb	else if (strcasecmp(arg, "dof") == 0)
334178479Sjb		dtp->dt_linktype = DT_LTYP_DOF;
335178479Sjb	else
336178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
337178479Sjb
338178479Sjb	return (0);
339178479Sjb}
340178479Sjb
341178479Sjb/*ARGSUSED*/
342178479Sjbstatic int
343178479Sjbdt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
344178479Sjb{
345178479Sjb	if (arg == NULL)
346178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
347178479Sjb
348178479Sjb	if (strcmp(arg, "exec") == 0)
349178479Sjb		dtp->dt_prcmode = DT_PROC_STOP_CREATE;
350178479Sjb	else if (strcmp(arg, "preinit") == 0)
351178479Sjb		dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
352178479Sjb	else if (strcmp(arg, "postinit") == 0)
353178479Sjb		dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
354178479Sjb	else if (strcmp(arg, "main") == 0)
355178479Sjb		dtp->dt_prcmode = DT_PROC_STOP_MAIN;
356178479Sjb	else
357178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
358178479Sjb
359178479Sjb	return (0);
360178479Sjb}
361178479Sjb
362178479Sjb/*ARGSUSED*/
363178479Sjbstatic int
364178479Sjbdt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
365178479Sjb{
366178479Sjb	int n;
367178479Sjb
368178479Sjb	if (arg == NULL || (n = atoi(arg)) < 0)
369178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
370178479Sjb
371178479Sjb	dtp->dt_procs->dph_lrulim = n;
372178479Sjb	return (0);
373178479Sjb}
374178479Sjb
375250574Smarkjstatic int
376250574Smarkjdt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
377250574Smarkj{
378250574Smarkj	char **p;
379250574Smarkj	char *var;
380250574Smarkj	int i;
381250574Smarkj
382250574Smarkj	/*
383250574Smarkj	 * We can't effectively set environment variables from #pragma lines
384250574Smarkj	 * since the processes have already been spawned.
385250574Smarkj	 */
386250574Smarkj	if (dtp->dt_pcb != NULL)
387250574Smarkj		return (dt_set_errno(dtp, EDT_BADOPTCTX));
388250574Smarkj
389250574Smarkj	if (arg == NULL)
390250574Smarkj		return (dt_set_errno(dtp, EDT_BADOPTVAL));
391250574Smarkj
392250574Smarkj	if (!option && strchr(arg, '=') != NULL)
393250574Smarkj		return (dt_set_errno(dtp, EDT_BADOPTVAL));
394250574Smarkj
395250574Smarkj	for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++)
396250574Smarkj		continue;
397250574Smarkj
398250574Smarkj	for (p = dtp->dt_proc_env; *p != NULL; p++) {
399250574Smarkj		var = strchr(*p, '=');
400250574Smarkj		if (var == NULL)
401250574Smarkj			var = *p + strlen(*p);
402250574Smarkj		if (strncmp(*p, arg, var - *p) == 0) {
403250574Smarkj			dt_free(dtp, *p);
404250574Smarkj			*p = dtp->dt_proc_env[i - 1];
405250574Smarkj			dtp->dt_proc_env[i - 1] = NULL;
406250574Smarkj			i--;
407250574Smarkj		}
408250574Smarkj	}
409250574Smarkj
410250574Smarkj	if (option) {
411250574Smarkj		if ((var = strdup(arg)) == NULL)
412250574Smarkj			return (dt_set_errno(dtp, EDT_NOMEM));
413250574Smarkj
414250574Smarkj		if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) {
415250574Smarkj			dt_free(dtp, var);
416250574Smarkj			return (dt_set_errno(dtp, EDT_NOMEM));
417250574Smarkj		}
418250574Smarkj
419250574Smarkj		bcopy(dtp->dt_proc_env, p, sizeof (char *) * i);
420250574Smarkj		dt_free(dtp, dtp->dt_proc_env);
421250574Smarkj		dtp->dt_proc_env = p;
422250574Smarkj
423250574Smarkj		dtp->dt_proc_env[i - 1] = var;
424250574Smarkj		dtp->dt_proc_env[i] = NULL;
425250574Smarkj	}
426250574Smarkj
427250574Smarkj	return (0);
428250574Smarkj}
429250574Smarkj
430178479Sjb/*ARGSUSED*/
431178479Sjbstatic int
432178479Sjbdt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
433178479Sjb{
434178479Sjb	if (arg == NULL)
435178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
436178479Sjb
437178479Sjb	if (dtp->dt_pcb != NULL)
438178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
439178479Sjb
440178479Sjb	if (strcmp(arg, "a") == 0)
441178479Sjb		dtp->dt_stdcmode = DT_STDC_XA;
442178479Sjb	else if (strcmp(arg, "c") == 0)
443178479Sjb		dtp->dt_stdcmode = DT_STDC_XC;
444178479Sjb	else if (strcmp(arg, "s") == 0)
445178479Sjb		dtp->dt_stdcmode = DT_STDC_XS;
446178479Sjb	else if (strcmp(arg, "t") == 0)
447178479Sjb		dtp->dt_stdcmode = DT_STDC_XT;
448178479Sjb	else
449178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
450178479Sjb
451178479Sjb	return (0);
452178479Sjb}
453178479Sjb
454178479Sjb/*ARGSUSED*/
455178479Sjbstatic int
456178479Sjbdt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
457178479Sjb{
458178479Sjb	dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
459178479Sjb	char *path;
460178479Sjb
461178479Sjb	if (arg == NULL)
462178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
463178479Sjb
464178479Sjb	if ((path = strdup(arg)) == NULL)
465178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
466178479Sjb
467178479Sjb	free(dp->dir_path);
468178479Sjb	dp->dir_path = path;
469178479Sjb
470178479Sjb	return (0);
471178479Sjb}
472178479Sjb
473178479Sjb/*ARGSUSED*/
474178479Sjbstatic int
475178479Sjbdt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
476178479Sjb{
477178479Sjb	int m;
478178479Sjb
479178479Sjb	if (arg == NULL || (m = atoi(arg)) <= 0)
480178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
481178479Sjb
482178479Sjb	dtp->dt_treedump = m;
483178479Sjb	return (0);
484178479Sjb}
485178479Sjb
486178479Sjb/*ARGSUSED*/
487178479Sjbstatic int
488178479Sjbdt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
489178479Sjb{
490178479Sjb	int n;
491178479Sjb
492178479Sjb	if (arg == NULL || (n = atoi(arg)) <= 0)
493178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
494178479Sjb
495178479Sjb	dtp->dt_conf.dtc_diftupregs = n;
496178479Sjb	return (0);
497178479Sjb}
498178479Sjb
499178479Sjb/*ARGSUSED*/
500178479Sjbstatic int
501178479Sjbdt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
502178479Sjb{
503178479Sjb	if (arg == NULL)
504178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
505178479Sjb
506178479Sjb	if (strcmp(arg, "dynamic") == 0)
507178479Sjb		dtp->dt_xlatemode = DT_XL_DYNAMIC;
508178479Sjb	else if (strcmp(arg, "static") == 0)
509178479Sjb		dtp->dt_xlatemode = DT_XL_STATIC;
510178479Sjb	else
511178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
512178479Sjb
513178479Sjb	return (0);
514178479Sjb}
515178479Sjb
516178479Sjb/*ARGSUSED*/
517178479Sjbstatic int
518178479Sjbdt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
519178479Sjb{
520178479Sjb	if (arg != NULL)
521178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
522178479Sjb
523178479Sjb	if (dtp->dt_pcb != NULL)
524178479Sjb		dtp->dt_pcb->pcb_cflags |= option;
525178479Sjb	else
526178479Sjb		dtp->dt_cflags |= option;
527178479Sjb
528178479Sjb	return (0);
529178479Sjb}
530178479Sjb
531178479Sjbstatic int
532178479Sjbdt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
533178479Sjb{
534178479Sjb	if (arg != NULL)
535178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
536178479Sjb
537178479Sjb	dtp->dt_dflags |= option;
538178479Sjb	return (0);
539178479Sjb}
540178479Sjb
541178479Sjbstatic int
542178479Sjbdt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
543178479Sjb{
544178479Sjb	if (arg != NULL)
545178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
546178479Sjb
547178479Sjb	if (dtp->dt_pcb != NULL)
548178479Sjb		dtp->dt_pcb->pcb_cflags &= ~option;
549178479Sjb	else
550178479Sjb		dtp->dt_cflags &= ~option;
551178479Sjb
552178479Sjb	return (0);
553178479Sjb}
554178479Sjb
555178479Sjb/*ARGSUSED*/
556178479Sjbstatic int
557178479Sjbdt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
558178479Sjb{
559178479Sjb	dt_version_t v;
560178479Sjb
561178479Sjb	if (arg == NULL)
562178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
563178479Sjb
564178479Sjb	if (dt_version_str2num(arg, &v) == -1)
565178479Sjb		return (dt_set_errno(dtp, EDT_VERSINVAL));
566178479Sjb
567178479Sjb	if (!dt_version_defined(v))
568178479Sjb		return (dt_set_errno(dtp, EDT_VERSUNDEF));
569178479Sjb
570178479Sjb	return (dt_reduce(dtp, v));
571178479Sjb}
572178479Sjb
573178479Sjbstatic int
574178479Sjbdt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
575178479Sjb{
576178479Sjb	char *end;
577178479Sjb	dtrace_optval_t val = 0;
578178479Sjb	int i;
579178479Sjb
580178479Sjb	const struct {
581178479Sjb		char *positive;
582178479Sjb		char *negative;
583178479Sjb	} couples[] = {
584178479Sjb		{ "yes",	"no" },
585178479Sjb		{ "enable",	"disable" },
586178479Sjb		{ "enabled",	"disabled" },
587178479Sjb		{ "true",	"false" },
588178479Sjb		{ "on",		"off" },
589178479Sjb		{ "set",	"unset" },
590178479Sjb		{ NULL }
591178479Sjb	};
592178479Sjb
593178479Sjb	if (arg != NULL) {
594178479Sjb		if (arg[0] == '\0') {
595178479Sjb			val = DTRACEOPT_UNSET;
596178479Sjb			goto out;
597178479Sjb		}
598178479Sjb
599178479Sjb		for (i = 0; couples[i].positive != NULL; i++) {
600178479Sjb			if (strcasecmp(couples[i].positive, arg) == 0) {
601178479Sjb				val = 1;
602178479Sjb				goto out;
603178479Sjb			}
604178479Sjb
605178479Sjb			if (strcasecmp(couples[i].negative, arg) == 0) {
606178479Sjb				val = DTRACEOPT_UNSET;
607178479Sjb				goto out;
608178479Sjb			}
609178479Sjb		}
610178479Sjb
611178479Sjb		errno = 0;
612178479Sjb		val = strtoull(arg, &end, 0);
613178479Sjb
614178479Sjb		if (*end != '\0' || errno != 0 || val < 0)
615178479Sjb			return (dt_set_errno(dtp, EDT_BADOPTVAL));
616178479Sjb	}
617178479Sjb
618178479Sjbout:
619178479Sjb	dtp->dt_options[option] = val;
620178479Sjb	return (0);
621178479Sjb}
622178479Sjb
623178479Sjbstatic int
624178479Sjbdt_optval_parse(const char *arg, dtrace_optval_t *rval)
625178479Sjb{
626178479Sjb	dtrace_optval_t mul = 1;
627178479Sjb	size_t len;
628178479Sjb	char *end;
629178479Sjb
630178479Sjb	len = strlen(arg);
631178479Sjb	errno = 0;
632178479Sjb
633178479Sjb	switch (arg[len - 1]) {
634178479Sjb	case 't':
635178479Sjb	case 'T':
636178479Sjb		mul *= 1024;
637178479Sjb		/*FALLTHRU*/
638178479Sjb	case 'g':
639178479Sjb	case 'G':
640178479Sjb		mul *= 1024;
641178479Sjb		/*FALLTHRU*/
642178479Sjb	case 'm':
643178479Sjb	case 'M':
644178479Sjb		mul *= 1024;
645178479Sjb		/*FALLTHRU*/
646178479Sjb	case 'k':
647178479Sjb	case 'K':
648178479Sjb		mul *= 1024;
649178479Sjb		/*FALLTHRU*/
650178479Sjb	default:
651178479Sjb		break;
652178479Sjb	}
653178479Sjb
654178479Sjb	errno = 0;
655178479Sjb	*rval = strtoull(arg, &end, 0) * mul;
656178479Sjb
657178479Sjb	if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') ||
658178479Sjb	    *rval < 0 || errno != 0)
659178479Sjb		return (-1);
660178479Sjb
661178479Sjb	return (0);
662178479Sjb}
663178479Sjb
664178479Sjbstatic int
665178479Sjbdt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
666178479Sjb{
667178479Sjb	dtrace_optval_t val = 0;
668178479Sjb
669178479Sjb	if (arg != NULL && dt_optval_parse(arg, &val) != 0)
670178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
671178479Sjb
672178479Sjb	dtp->dt_options[option] = val;
673178479Sjb	return (0);
674178479Sjb}
675178479Sjb
676178479Sjbstatic int
677178479Sjbdt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
678178479Sjb{
679178479Sjb	char *end;
680178479Sjb	int i;
681178479Sjb	dtrace_optval_t mul = 1, val = 0;
682178479Sjb
683178479Sjb	const struct {
684178479Sjb		char *name;
685178479Sjb		hrtime_t mul;
686178479Sjb	} suffix[] = {
687178479Sjb		{ "ns", 	NANOSEC / NANOSEC },
688178479Sjb		{ "nsec",	NANOSEC / NANOSEC },
689178479Sjb		{ "us",		NANOSEC / MICROSEC },
690178479Sjb		{ "usec",	NANOSEC / MICROSEC },
691178479Sjb		{ "ms",		NANOSEC / MILLISEC },
692178479Sjb		{ "msec",	NANOSEC / MILLISEC },
693178479Sjb		{ "s",		NANOSEC / SEC },
694178479Sjb		{ "sec",	NANOSEC / SEC },
695178479Sjb		{ "m",		NANOSEC * (hrtime_t)60 },
696178479Sjb		{ "min",	NANOSEC * (hrtime_t)60 },
697178479Sjb		{ "h",		NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
698178479Sjb		{ "hour",	NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
699178479Sjb		{ "d",		NANOSEC * (hrtime_t)(24 * 60 * 60) },
700178479Sjb		{ "day",	NANOSEC * (hrtime_t)(24 * 60 * 60) },
701178479Sjb		{ "hz",		0 },
702178479Sjb		{ NULL }
703178479Sjb	};
704178479Sjb
705178479Sjb	if (arg != NULL) {
706178479Sjb		errno = 0;
707178479Sjb		val = strtoull(arg, &end, 0);
708178479Sjb
709178479Sjb		for (i = 0; suffix[i].name != NULL; i++) {
710178479Sjb			if (strcasecmp(suffix[i].name, end) == 0) {
711178479Sjb				mul = suffix[i].mul;
712178479Sjb				break;
713178479Sjb			}
714178479Sjb		}
715178479Sjb
716178479Sjb		if (suffix[i].name == NULL && *end != '\0' || val < 0)
717178479Sjb			return (dt_set_errno(dtp, EDT_BADOPTVAL));
718178479Sjb
719178479Sjb		if (mul == 0) {
720178479Sjb			/*
721178479Sjb			 * The rate has been specified in frequency-per-second.
722178479Sjb			 */
723178479Sjb			if (val != 0)
724178479Sjb				val = NANOSEC / val;
725178479Sjb		} else {
726178479Sjb			val *= mul;
727178479Sjb		}
728178479Sjb	}
729178479Sjb
730178479Sjb	dtp->dt_options[option] = val;
731178479Sjb	return (0);
732178479Sjb}
733178479Sjb
734178479Sjb/*
735178479Sjb * When setting the strsize option, set the option in the dt_options array
736178479Sjb * using dt_opt_size() as usual, and then update the definition of the CTF
737178479Sjb * type for the D intrinsic "string" to be an array of the corresponding size.
738178479Sjb * If any errors occur, reset dt_options[option] to its previous value.
739178479Sjb */
740178479Sjbstatic int
741178479Sjbdt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
742178479Sjb{
743178479Sjb	dtrace_optval_t val = dtp->dt_options[option];
744178479Sjb	ctf_file_t *fp = DT_STR_CTFP(dtp);
745178479Sjb	ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp));
746178479Sjb	ctf_arinfo_t r;
747178479Sjb
748178479Sjb	if (dt_opt_size(dtp, arg, option) != 0)
749178479Sjb		return (-1); /* dt_errno is set for us */
750178479Sjb
751178479Sjb	if (dtp->dt_options[option] > UINT_MAX) {
752178479Sjb		dtp->dt_options[option] = val;
753178479Sjb		return (dt_set_errno(dtp, EOVERFLOW));
754178479Sjb	}
755178479Sjb
756178479Sjb	if (ctf_array_info(fp, type, &r) == CTF_ERR) {
757178479Sjb		dtp->dt_options[option] = val;
758178479Sjb		dtp->dt_ctferr = ctf_errno(fp);
759178479Sjb		return (dt_set_errno(dtp, EDT_CTF));
760178479Sjb	}
761178479Sjb
762178479Sjb	r.ctr_nelems = (uint_t)dtp->dt_options[option];
763178479Sjb
764178479Sjb	if (ctf_set_array(fp, type, &r) == CTF_ERR ||
765178479Sjb	    ctf_update(fp) == CTF_ERR) {
766178479Sjb		dtp->dt_options[option] = val;
767178479Sjb		dtp->dt_ctferr = ctf_errno(fp);
768178479Sjb		return (dt_set_errno(dtp, EDT_CTF));
769178479Sjb	}
770178479Sjb
771178479Sjb	return (0);
772178479Sjb}
773178479Sjb
774178479Sjbstatic const struct {
775178479Sjb	const char *dtbp_name;
776178479Sjb	int dtbp_policy;
777178479Sjb} _dtrace_bufpolicies[] = {
778178479Sjb	{ "ring", DTRACEOPT_BUFPOLICY_RING },
779178479Sjb	{ "fill", DTRACEOPT_BUFPOLICY_FILL },
780178479Sjb	{ "switch", DTRACEOPT_BUFPOLICY_SWITCH },
781178479Sjb	{ NULL, 0 }
782178479Sjb};
783178479Sjb
784178479Sjb/*ARGSUSED*/
785178479Sjbstatic int
786178479Sjbdt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
787178479Sjb{
788178479Sjb	dtrace_optval_t policy = DTRACEOPT_UNSET;
789178479Sjb	int i;
790178479Sjb
791178479Sjb	if (arg == NULL)
792178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
793178479Sjb
794178479Sjb	for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) {
795178479Sjb		if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) {
796178479Sjb			policy = _dtrace_bufpolicies[i].dtbp_policy;
797178479Sjb			break;
798178479Sjb		}
799178479Sjb	}
800178479Sjb
801178479Sjb	if (policy == DTRACEOPT_UNSET)
802178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
803178479Sjb
804178479Sjb	dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy;
805178479Sjb
806178479Sjb	return (0);
807178479Sjb}
808178479Sjb
809178479Sjbstatic const struct {
810178479Sjb	const char *dtbr_name;
811178479Sjb	int dtbr_policy;
812178479Sjb} _dtrace_bufresize[] = {
813178479Sjb	{ "auto", DTRACEOPT_BUFRESIZE_AUTO },
814178479Sjb	{ "manual", DTRACEOPT_BUFRESIZE_MANUAL },
815178479Sjb	{ NULL, 0 }
816178479Sjb};
817178479Sjb
818178479Sjb/*ARGSUSED*/
819178479Sjbstatic int
820178479Sjbdt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
821178479Sjb{
822178479Sjb	dtrace_optval_t policy = DTRACEOPT_UNSET;
823178479Sjb	int i;
824178479Sjb
825178479Sjb	if (arg == NULL)
826178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
827178479Sjb
828178479Sjb	for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) {
829178479Sjb		if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) {
830178479Sjb			policy = _dtrace_bufresize[i].dtbr_policy;
831178479Sjb			break;
832178479Sjb		}
833178479Sjb	}
834178479Sjb
835178479Sjb	if (policy == DTRACEOPT_UNSET)
836178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
837178479Sjb
838178479Sjb	dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy;
839178479Sjb
840178479Sjb	return (0);
841178479Sjb}
842178479Sjb
843178479Sjbint
844178479Sjbdt_options_load(dtrace_hdl_t *dtp)
845178479Sjb{
846178479Sjb	dof_hdr_t hdr, *dof;
847178479Sjb	dof_sec_t *sec;
848178479Sjb	size_t offs;
849178479Sjb	int i;
850178479Sjb
851178479Sjb	/*
852178479Sjb	 * To load the option values, we need to ask the kernel to provide its
853178479Sjb	 * DOF, which we'll sift through to look for OPTDESC sections.
854178479Sjb	 */
855178479Sjb	bzero(&hdr, sizeof (dof_hdr_t));
856178479Sjb	hdr.dofh_loadsz = sizeof (dof_hdr_t);
857178479Sjb
858178569Sjb#if defined(sun)
859178479Sjb	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1)
860178569Sjb#else
861178569Sjb	dof = &hdr;
862178569Sjb	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)
863178569Sjb#endif
864178479Sjb		return (dt_set_errno(dtp, errno));
865178479Sjb
866178479Sjb	if (hdr.dofh_loadsz < sizeof (dof_hdr_t))
867178479Sjb		return (dt_set_errno(dtp, EINVAL));
868178479Sjb
869178479Sjb	dof = alloca(hdr.dofh_loadsz);
870178479Sjb	bzero(dof, sizeof (dof_hdr_t));
871178479Sjb	dof->dofh_loadsz = hdr.dofh_loadsz;
872178479Sjb
873178479Sjb	for (i = 0; i < DTRACEOPT_MAX; i++)
874178479Sjb		dtp->dt_options[i] = DTRACEOPT_UNSET;
875178479Sjb
876178569Sjb#if defined(sun)
877178479Sjb	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1)
878178569Sjb#else
879178569Sjb	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)
880178569Sjb#endif
881178479Sjb		return (dt_set_errno(dtp, errno));
882178479Sjb
883178479Sjb	for (i = 0; i < dof->dofh_secnum; i++) {
884178479Sjb		sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof +
885178479Sjb		    dof->dofh_secoff + i * dof->dofh_secsize);
886178479Sjb
887178479Sjb		if (sec->dofs_type != DOF_SECT_OPTDESC)
888178479Sjb			continue;
889178479Sjb
890178479Sjb		break;
891178479Sjb	}
892178479Sjb
893178479Sjb	for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {
894178479Sjb		dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t)
895178479Sjb		    ((uintptr_t)dof + sec->dofs_offset + offs);
896178479Sjb
897178479Sjb		if (opt->dofo_strtab != DOF_SECIDX_NONE)
898178479Sjb			continue;
899178479Sjb
900178479Sjb		if (opt->dofo_option >= DTRACEOPT_MAX)
901178479Sjb			continue;
902178479Sjb
903178479Sjb		dtp->dt_options[opt->dofo_option] = opt->dofo_value;
904178479Sjb	}
905178479Sjb
906178479Sjb	return (0);
907178479Sjb}
908178479Sjb
909178479Sjb/*ARGSUSED*/
910178479Sjbstatic int
911178479Sjbdt_opt_preallocate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
912178479Sjb{
913178479Sjb	dtrace_optval_t size;
914178479Sjb	void *p;
915178479Sjb
916178479Sjb	if (arg == NULL || dt_optval_parse(arg, &size) != 0)
917178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
918178479Sjb
919178479Sjb	if (size > SIZE_MAX)
920178479Sjb		size = SIZE_MAX;
921178479Sjb
922178479Sjb	if ((p = dt_zalloc(dtp, size)) == NULL) {
923178479Sjb		do {
924178479Sjb			size /= 2;
925178479Sjb		} while ((p = dt_zalloc(dtp, size)) == NULL);
926178479Sjb	}
927178479Sjb
928178479Sjb	dt_free(dtp, p);
929178479Sjb
930178479Sjb	return (0);
931178479Sjb}
932178479Sjb
933178479Sjbtypedef struct dt_option {
934178479Sjb	const char *o_name;
935178479Sjb	int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
936178479Sjb	uintptr_t o_option;
937178479Sjb} dt_option_t;
938178479Sjb
939178479Sjb/*
940178479Sjb * Compile-time options.
941178479Sjb */
942178479Sjbstatic const dt_option_t _dtrace_ctoptions[] = {
943178479Sjb	{ "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU },
944178479Sjb	{ "amin", dt_opt_amin },
945178479Sjb	{ "argref", dt_opt_cflags, DTRACE_C_ARGREF },
946178479Sjb	{ "core", dt_opt_core },
947178479Sjb	{ "cpp", dt_opt_cflags, DTRACE_C_CPP },
948178479Sjb	{ "cpphdrs", dt_opt_cpp_hdrs },
949178479Sjb	{ "cpppath", dt_opt_cpp_path },
950178479Sjb	{ "ctypes", dt_opt_ctypes },
951178479Sjb	{ "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG },
952178479Sjb	{ "dtypes", dt_opt_dtypes },
953178479Sjb	{ "debug", dt_opt_debug },
954178479Sjb	{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
955178479Sjb	{ "droptags", dt_opt_droptags },
956178479Sjb	{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
957178479Sjb	{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
958178479Sjb	{ "evaltime", dt_opt_evaltime },
959178479Sjb	{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
960178479Sjb	{ "iregs", dt_opt_iregs },
961178479Sjb	{ "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF },
962178479Sjb	{ "knodefs", dt_opt_cflags, DTRACE_C_KNODEF },
963178479Sjb	{ "late", dt_opt_xlate },
964178479Sjb	{ "lazyload", dt_opt_lazyload },
965178479Sjb	{ "ldpath", dt_opt_ld_path },
966178479Sjb	{ "libdir", dt_opt_libdir },
967178479Sjb	{ "linkmode", dt_opt_linkmode },
968178479Sjb	{ "linktype", dt_opt_linktype },
969178479Sjb	{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
970178479Sjb	{ "pgmax", dt_opt_pgmax },
971178479Sjb	{ "preallocate", dt_opt_preallocate },
972178479Sjb	{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
973250574Smarkj	{ "setenv", dt_opt_setenv, 1 },
974178479Sjb	{ "stdc", dt_opt_stdc },
975178479Sjb	{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
976178479Sjb	{ "syslibdir", dt_opt_syslibdir },
977178479Sjb	{ "tree", dt_opt_tree },
978178479Sjb	{ "tregs", dt_opt_tregs },
979178479Sjb	{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
980178479Sjb	{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
981178479Sjb	{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
982250574Smarkj	{ "unsetenv", dt_opt_setenv, 0 },
983178479Sjb	{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
984178479Sjb	{ "version", dt_opt_version },
985178479Sjb	{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
986178569Sjb	{ NULL, NULL, 0 }
987178479Sjb};
988178479Sjb
989178479Sjb/*
990178479Sjb * Run-time options.
991178479Sjb */
992178479Sjbstatic const dt_option_t _dtrace_rtoptions[] = {
993178479Sjb	{ "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE },
994178479Sjb	{ "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE },
995178479Sjb	{ "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY },
996178479Sjb	{ "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE },
997178479Sjb	{ "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE },
998178479Sjb	{ "cpu", dt_opt_runtime, DTRACEOPT_CPU },
999178479Sjb	{ "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE },
1000178479Sjb	{ "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE },
1001178479Sjb	{ "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON },
1002178479Sjb	{ "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES },
1003178479Sjb	{ "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE },
1004178479Sjb	{ "nspec", dt_opt_runtime, DTRACEOPT_NSPEC },
1005178479Sjb	{ "specsize", dt_opt_size, DTRACEOPT_SPECSIZE },
1006178479Sjb	{ "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES },
1007178479Sjb	{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
1008178479Sjb	{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
1009178479Sjb	{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
1010250574Smarkj	{ "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },
1011178569Sjb	{ NULL, NULL, 0 }
1012178479Sjb};
1013178479Sjb
1014178479Sjb/*
1015178479Sjb * Dynamic run-time options.
1016178479Sjb */
1017178479Sjbstatic const dt_option_t _dtrace_drtoptions[] = {
1018178479Sjb	{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
1019178479Sjb	{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },
1020178479Sjb	{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },
1021178479Sjb	{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },
1022178479Sjb	{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },
1023178479Sjb	{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
1024178479Sjb	{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
1025178479Sjb	{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
1026178479Sjb	{ "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT },
1027178479Sjb	{ "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE },
1028178569Sjb	{ NULL, NULL, 0 }
1029178479Sjb};
1030178479Sjb
1031178479Sjbint
1032178479Sjbdtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val)
1033178479Sjb{
1034178479Sjb	const dt_option_t *op;
1035178479Sjb
1036178479Sjb	if (opt == NULL)
1037178479Sjb		return (dt_set_errno(dtp, EINVAL));
1038178479Sjb
1039178479Sjb	/*
1040178479Sjb	 * We only need to search the run-time options -- it's not legal
1041178479Sjb	 * to get the values of compile-time options.
1042178479Sjb	 */
1043178479Sjb	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
1044178479Sjb		if (strcmp(op->o_name, opt) == 0) {
1045178479Sjb			*val = dtp->dt_options[op->o_option];
1046178479Sjb			return (0);
1047178479Sjb		}
1048178479Sjb	}
1049178479Sjb
1050178479Sjb	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
1051178479Sjb		if (strcmp(op->o_name, opt) == 0) {
1052178479Sjb			*val = dtp->dt_options[op->o_option];
1053178479Sjb			return (0);
1054178479Sjb		}
1055178479Sjb	}
1056178479Sjb
1057178479Sjb	return (dt_set_errno(dtp, EDT_BADOPTNAME));
1058178479Sjb}
1059178479Sjb
1060178479Sjbint
1061178479Sjbdtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val)
1062178479Sjb{
1063178479Sjb	const dt_option_t *op;
1064178479Sjb
1065178479Sjb	if (opt == NULL)
1066178479Sjb		return (dt_set_errno(dtp, EINVAL));
1067178479Sjb
1068178479Sjb	for (op = _dtrace_ctoptions; op->o_name != NULL; op++) {
1069178479Sjb		if (strcmp(op->o_name, opt) == 0)
1070178479Sjb			return (op->o_func(dtp, val, op->o_option));
1071178479Sjb	}
1072178479Sjb
1073178479Sjb	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
1074178479Sjb		if (strcmp(op->o_name, opt) == 0)
1075178479Sjb			return (op->o_func(dtp, val, op->o_option));
1076178479Sjb	}
1077178479Sjb
1078178479Sjb	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
1079178479Sjb		if (strcmp(op->o_name, opt) == 0) {
1080178479Sjb			/*
1081178479Sjb			 * Only dynamic run-time options may be set while
1082178479Sjb			 * tracing is active.
1083178479Sjb			 */
1084178479Sjb			if (dtp->dt_active)
1085178479Sjb				return (dt_set_errno(dtp, EDT_ACTIVE));
1086178479Sjb
1087178479Sjb			return (op->o_func(dtp, val, op->o_option));
1088178479Sjb		}
1089178479Sjb	}
1090178479Sjb
1091178479Sjb	return (dt_set_errno(dtp, EDT_BADOPTNAME));
1092178479Sjb}
1093