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
27250574Smarkj/*
28267942Srpaulo * Copyright (c) 2013, Joyent, Inc. All rights reserved.
29250574Smarkj * Copyright (c) 2012 by Delphix. All rights reserved.
30250574Smarkj */
31250574Smarkj
32178479Sjb#include <sys/resource.h>
33178479Sjb#include <sys/mman.h>
34178479Sjb#include <sys/types.h>
35178479Sjb
36178479Sjb#include <strings.h>
37178479Sjb#include <signal.h>
38178479Sjb#include <stdlib.h>
39178479Sjb#include <unistd.h>
40178479Sjb#include <limits.h>
41277300Ssmh#ifdef illumos
42178479Sjb#include <alloca.h>
43178569Sjb#endif
44178479Sjb#include <errno.h>
45178479Sjb#include <fcntl.h>
46178479Sjb
47178479Sjb#include <dt_impl.h>
48178479Sjb#include <dt_string.h>
49178479Sjb
50178479Sjbstatic int
51178479Sjbdt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
52178479Sjb{
53178479Sjb	dt_aggregate_t *agp = &dtp->dt_aggregate;
54178479Sjb
55178479Sjb	if (arg != NULL)
56178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
57178479Sjb
58178479Sjb	agp->dtat_flags |= option;
59178479Sjb	return (0);
60178479Sjb}
61178479Sjb
62178479Sjb/*ARGSUSED*/
63178479Sjbstatic int
64178479Sjbdt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
65178479Sjb{
66178479Sjb	char str[DTRACE_ATTR2STR_MAX];
67178479Sjb	dtrace_attribute_t attr;
68178479Sjb
69178479Sjb	if (arg == NULL || dtrace_str2attr(arg, &attr) == -1)
70178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
71178479Sjb
72178479Sjb	dt_dprintf("set compiler attribute minimum to %s\n",
73178479Sjb	    dtrace_attr2str(attr, str, sizeof (str)));
74178479Sjb
75178479Sjb	if (dtp->dt_pcb != NULL) {
76178479Sjb		dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR;
77178479Sjb		dtp->dt_pcb->pcb_amin = attr;
78178479Sjb	} else {
79178479Sjb		dtp->dt_cflags |= DTRACE_C_EATTR;
80178479Sjb		dtp->dt_amin = attr;
81178479Sjb	}
82178479Sjb
83178479Sjb	return (0);
84178479Sjb}
85178479Sjb
86178479Sjbstatic void
87178479Sjbdt_coredump(void)
88178479Sjb{
89178479Sjb	const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n";
90178479Sjb
91178479Sjb	struct sigaction act;
92178479Sjb	struct rlimit lim;
93178479Sjb
94178479Sjb	(void) write(STDERR_FILENO, msg, sizeof (msg) - 1);
95178479Sjb
96178479Sjb	act.sa_handler = SIG_DFL;
97178479Sjb	act.sa_flags = 0;
98178479Sjb
99178479Sjb	(void) sigemptyset(&act.sa_mask);
100178479Sjb	(void) sigaction(SIGABRT, &act, NULL);
101178479Sjb
102178479Sjb	lim.rlim_cur = RLIM_INFINITY;
103178479Sjb	lim.rlim_max = RLIM_INFINITY;
104178479Sjb
105178479Sjb	(void) setrlimit(RLIMIT_CORE, &lim);
106178479Sjb	abort();
107178479Sjb}
108178479Sjb
109178479Sjb/*ARGSUSED*/
110178479Sjbstatic int
111178479Sjbdt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
112178479Sjb{
113178479Sjb	static int enabled = 0;
114178479Sjb
115178479Sjb	if (arg != NULL)
116178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
117178479Sjb
118178479Sjb	if (enabled++ || atexit(dt_coredump) == 0)
119178479Sjb		return (0);
120178479Sjb
121178479Sjb	return (dt_set_errno(dtp, errno));
122178479Sjb}
123178479Sjb
124178479Sjb/*ARGSUSED*/
125178479Sjbstatic int
126178479Sjbdt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
127178479Sjb{
128178479Sjb	if (arg != NULL)
129178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
130178479Sjb
131178479Sjb	if (dtp->dt_pcb != NULL)
132178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
133178479Sjb
134178479Sjb	if (dt_cpp_add_arg(dtp, "-H") == NULL)
135178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
136178479Sjb
137178479Sjb	return (0);
138178479Sjb}
139178479Sjb
140178479Sjb/*ARGSUSED*/
141178479Sjbstatic int
142178479Sjbdt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
143178479Sjb{
144178479Sjb	char *cpp;
145178479Sjb
146178479Sjb	if (arg == NULL)
147178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
148178479Sjb
149178479Sjb	if (dtp->dt_pcb != NULL)
150178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
151178479Sjb
152178479Sjb	if ((cpp = strdup(arg)) == NULL)
153178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
154178479Sjb
155178479Sjb	dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);
156178479Sjb	free(dtp->dt_cpp_path);
157178479Sjb	dtp->dt_cpp_path = cpp;
158178479Sjb
159178479Sjb	return (0);
160178479Sjb}
161178479Sjb
162178479Sjbstatic int
163178479Sjbdt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
164178479Sjb{
165178479Sjb	char *buf;
166178479Sjb	size_t len;
167178479Sjb	const char *opt = (const char *)option;
168178479Sjb
169178479Sjb	if (opt == NULL || arg == NULL)
170178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
171178479Sjb
172178479Sjb	if (dtp->dt_pcb != NULL)
173178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
174178479Sjb
175178479Sjb	len = strlen(opt) + strlen(arg) + 1;
176178479Sjb	buf = alloca(len);
177178479Sjb
178178479Sjb	(void) strcpy(buf, opt);
179178479Sjb	(void) strcat(buf, arg);
180178479Sjb
181178479Sjb	if (dt_cpp_add_arg(dtp, buf) == NULL)
182178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
183178479Sjb
184178479Sjb	return (0);
185178479Sjb}
186178479Sjb
187178479Sjb/*ARGSUSED*/
188178479Sjbstatic int
189178479Sjbdt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
190178479Sjb{
191178479Sjb	int fd;
192178479Sjb
193178479Sjb	if (arg == NULL)
194178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
195178479Sjb
196178479Sjb	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
197178479Sjb		return (dt_set_errno(dtp, errno));
198178479Sjb
199178479Sjb	(void) close(dtp->dt_cdefs_fd);
200178479Sjb	dtp->dt_cdefs_fd = fd;
201178479Sjb	return (0);
202178479Sjb}
203178479Sjb
204178479Sjb/*ARGSUSED*/
205178479Sjbstatic int
206178479Sjbdt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
207178479Sjb{
208178479Sjb	dtp->dt_droptags = 1;
209178479Sjb	return (0);
210178479Sjb}
211178479Sjb
212178479Sjb/*ARGSUSED*/
213178479Sjbstatic int
214178479Sjbdt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
215178479Sjb{
216178479Sjb	int fd;
217178479Sjb
218178479Sjb	if (arg == NULL)
219178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
220178479Sjb
221178479Sjb	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
222178479Sjb		return (dt_set_errno(dtp, errno));
223178479Sjb
224178479Sjb	(void) close(dtp->dt_ddefs_fd);
225178479Sjb	dtp->dt_ddefs_fd = fd;
226178479Sjb	return (0);
227178479Sjb}
228178479Sjb
229178479Sjb/*ARGSUSED*/
230178479Sjbstatic int
231178479Sjbdt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
232178479Sjb{
233178479Sjb	if (arg != NULL)
234178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
235178479Sjb
236178479Sjb	_dtrace_debug = 1;
237178479Sjb	return (0);
238178479Sjb}
239178479Sjb
240178479Sjb/*ARGSUSED*/
241178479Sjbstatic int
242178479Sjbdt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
243178479Sjb{
244178479Sjb	int n;
245178479Sjb
246178479Sjb	if (arg == NULL || (n = atoi(arg)) <= 0)
247178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
248178479Sjb
249178479Sjb	dtp->dt_conf.dtc_difintregs = n;
250178479Sjb	return (0);
251178479Sjb}
252178479Sjb
253178479Sjb/*ARGSUSED*/
254178479Sjbstatic int
255178479Sjbdt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
256178479Sjb{
257178479Sjb	dtp->dt_lazyload = 1;
258178479Sjb
259178479Sjb	return (0);
260178479Sjb}
261178479Sjb
262178479Sjb/*ARGSUSED*/
263178479Sjbstatic int
264178479Sjbdt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
265178479Sjb{
266178479Sjb	char *ld;
267178479Sjb
268178479Sjb	if (arg == NULL)
269178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
270178479Sjb
271178479Sjb	if (dtp->dt_pcb != NULL)
272178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
273178479Sjb
274178479Sjb	if ((ld = strdup(arg)) == NULL)
275178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
276178479Sjb
277178479Sjb	free(dtp->dt_ld_path);
278178479Sjb	dtp->dt_ld_path = ld;
279178479Sjb
280178479Sjb	return (0);
281178479Sjb}
282178479Sjb
283278934Smarkj#ifdef __FreeBSD__
284278934Smarkjstatic int
285278934Smarkjdt_opt_objcopy_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
286278934Smarkj{
287278934Smarkj	char *objcopy;
288278934Smarkj
289278934Smarkj	if (arg == NULL)
290278934Smarkj		return (dt_set_errno(dtp, EDT_BADOPTVAL));
291278934Smarkj
292278934Smarkj	if (dtp->dt_pcb != NULL)
293278934Smarkj		return (dt_set_errno(dtp, EDT_BADOPTCTX));
294278934Smarkj
295278934Smarkj	if ((objcopy = strdup(arg)) == NULL)
296278934Smarkj		return (dt_set_errno(dtp, EDT_NOMEM));
297278934Smarkj
298278934Smarkj	free(dtp->dt_objcopy_path);
299278934Smarkj	dtp->dt_objcopy_path = objcopy;
300278934Smarkj
301278934Smarkj	return (0);
302278934Smarkj}
303278934Smarkj#endif
304278934Smarkj
305178479Sjb/*ARGSUSED*/
306178479Sjbstatic int
307178479Sjbdt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
308178479Sjb{
309178479Sjb	dt_dirpath_t *dp;
310178479Sjb
311178479Sjb	if (arg == NULL)
312178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
313178479Sjb
314178479Sjb	if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL ||
315178479Sjb	    (dp->dir_path = strdup(arg)) == NULL) {
316178479Sjb		free(dp);
317178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
318178479Sjb	}
319178479Sjb
320178479Sjb	dt_list_append(&dtp->dt_lib_path, dp);
321178479Sjb	return (0);
322178479Sjb}
323178479Sjb
324178479Sjb/*ARGSUSED*/
325178479Sjbstatic int
326178479Sjbdt_opt_linkmode(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 (strcmp(arg, "kernel") == 0)
332178479Sjb		dtp->dt_linkmode = DT_LINK_KERNEL;
333178479Sjb	else if (strcmp(arg, "primary") == 0)
334178479Sjb		dtp->dt_linkmode = DT_LINK_PRIMARY;
335178479Sjb	else if (strcmp(arg, "dynamic") == 0)
336178479Sjb		dtp->dt_linkmode = DT_LINK_DYNAMIC;
337178479Sjb	else if (strcmp(arg, "static") == 0)
338178479Sjb		dtp->dt_linkmode = DT_LINK_STATIC;
339178479Sjb	else
340178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
341178479Sjb
342178479Sjb	return (0);
343178479Sjb}
344178479Sjb
345178479Sjb/*ARGSUSED*/
346178479Sjbstatic int
347178479Sjbdt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
348178479Sjb{
349178479Sjb	if (arg == NULL)
350178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
351178479Sjb
352178479Sjb	if (strcasecmp(arg, "elf") == 0)
353178479Sjb		dtp->dt_linktype = DT_LTYP_ELF;
354178479Sjb	else if (strcasecmp(arg, "dof") == 0)
355178479Sjb		dtp->dt_linktype = DT_LTYP_DOF;
356178479Sjb	else
357178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
358178479Sjb
359178479Sjb	return (0);
360178479Sjb}
361178479Sjb
362178479Sjb/*ARGSUSED*/
363178479Sjbstatic int
364267942Srpaulodt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
365267942Srpaulo{
366267942Srpaulo	if (arg == NULL)
367267942Srpaulo		return (dt_set_errno(dtp, EDT_BADOPTVAL));
368267942Srpaulo
369267942Srpaulo	if (strcmp(arg, "ascii") == 0)
370267942Srpaulo		dtp->dt_encoding = DT_ENCODING_ASCII;
371267942Srpaulo	else if (strcmp(arg, "utf8") == 0)
372267942Srpaulo		dtp->dt_encoding = DT_ENCODING_UTF8;
373267942Srpaulo	else
374267942Srpaulo		return (dt_set_errno(dtp, EDT_BADOPTVAL));
375267942Srpaulo
376267942Srpaulo	return (0);
377267942Srpaulo}
378267942Srpaulo
379267942Srpaulo/*ARGSUSED*/
380267942Srpaulostatic int
381178479Sjbdt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
382178479Sjb{
383178479Sjb	if (arg == NULL)
384178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
385178479Sjb
386178479Sjb	if (strcmp(arg, "exec") == 0)
387178479Sjb		dtp->dt_prcmode = DT_PROC_STOP_CREATE;
388178479Sjb	else if (strcmp(arg, "preinit") == 0)
389178479Sjb		dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
390178479Sjb	else if (strcmp(arg, "postinit") == 0)
391178479Sjb		dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
392178479Sjb	else if (strcmp(arg, "main") == 0)
393178479Sjb		dtp->dt_prcmode = DT_PROC_STOP_MAIN;
394178479Sjb	else
395178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
396178479Sjb
397178479Sjb	return (0);
398178479Sjb}
399178479Sjb
400178479Sjb/*ARGSUSED*/
401178479Sjbstatic int
402178479Sjbdt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
403178479Sjb{
404178479Sjb	int n;
405178479Sjb
406178479Sjb	if (arg == NULL || (n = atoi(arg)) < 0)
407178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
408178479Sjb
409178479Sjb	dtp->dt_procs->dph_lrulim = n;
410178479Sjb	return (0);
411178479Sjb}
412178479Sjb
413250574Smarkjstatic int
414250574Smarkjdt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
415250574Smarkj{
416250574Smarkj	char **p;
417250574Smarkj	char *var;
418250574Smarkj	int i;
419250574Smarkj
420250574Smarkj	/*
421250574Smarkj	 * We can't effectively set environment variables from #pragma lines
422250574Smarkj	 * since the processes have already been spawned.
423250574Smarkj	 */
424250574Smarkj	if (dtp->dt_pcb != NULL)
425250574Smarkj		return (dt_set_errno(dtp, EDT_BADOPTCTX));
426250574Smarkj
427250574Smarkj	if (arg == NULL)
428250574Smarkj		return (dt_set_errno(dtp, EDT_BADOPTVAL));
429250574Smarkj
430250574Smarkj	if (!option && strchr(arg, '=') != NULL)
431250574Smarkj		return (dt_set_errno(dtp, EDT_BADOPTVAL));
432250574Smarkj
433250574Smarkj	for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++)
434250574Smarkj		continue;
435250574Smarkj
436250574Smarkj	for (p = dtp->dt_proc_env; *p != NULL; p++) {
437250574Smarkj		var = strchr(*p, '=');
438250574Smarkj		if (var == NULL)
439250574Smarkj			var = *p + strlen(*p);
440250574Smarkj		if (strncmp(*p, arg, var - *p) == 0) {
441250574Smarkj			dt_free(dtp, *p);
442250574Smarkj			*p = dtp->dt_proc_env[i - 1];
443250574Smarkj			dtp->dt_proc_env[i - 1] = NULL;
444250574Smarkj			i--;
445250574Smarkj		}
446250574Smarkj	}
447250574Smarkj
448250574Smarkj	if (option) {
449250574Smarkj		if ((var = strdup(arg)) == NULL)
450250574Smarkj			return (dt_set_errno(dtp, EDT_NOMEM));
451250574Smarkj
452250574Smarkj		if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) {
453250574Smarkj			dt_free(dtp, var);
454250574Smarkj			return (dt_set_errno(dtp, EDT_NOMEM));
455250574Smarkj		}
456250574Smarkj
457250574Smarkj		bcopy(dtp->dt_proc_env, p, sizeof (char *) * i);
458250574Smarkj		dt_free(dtp, dtp->dt_proc_env);
459250574Smarkj		dtp->dt_proc_env = p;
460250574Smarkj
461250574Smarkj		dtp->dt_proc_env[i - 1] = var;
462250574Smarkj		dtp->dt_proc_env[i] = NULL;
463250574Smarkj	}
464250574Smarkj
465250574Smarkj	return (0);
466250574Smarkj}
467250574Smarkj
468178479Sjb/*ARGSUSED*/
469178479Sjbstatic int
470178479Sjbdt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
471178479Sjb{
472178479Sjb	if (arg == NULL)
473178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
474178479Sjb
475178479Sjb	if (dtp->dt_pcb != NULL)
476178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTCTX));
477178479Sjb
478178479Sjb	if (strcmp(arg, "a") == 0)
479178479Sjb		dtp->dt_stdcmode = DT_STDC_XA;
480178479Sjb	else if (strcmp(arg, "c") == 0)
481178479Sjb		dtp->dt_stdcmode = DT_STDC_XC;
482178479Sjb	else if (strcmp(arg, "s") == 0)
483178479Sjb		dtp->dt_stdcmode = DT_STDC_XS;
484178479Sjb	else if (strcmp(arg, "t") == 0)
485178479Sjb		dtp->dt_stdcmode = DT_STDC_XT;
486178479Sjb	else
487178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
488178479Sjb
489178479Sjb	return (0);
490178479Sjb}
491178479Sjb
492178479Sjb/*ARGSUSED*/
493178479Sjbstatic int
494178479Sjbdt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
495178479Sjb{
496178479Sjb	dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
497178479Sjb	char *path;
498178479Sjb
499178479Sjb	if (arg == NULL)
500178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
501178479Sjb
502178479Sjb	if ((path = strdup(arg)) == NULL)
503178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
504178479Sjb
505178479Sjb	free(dp->dir_path);
506178479Sjb	dp->dir_path = path;
507178479Sjb
508178479Sjb	return (0);
509178479Sjb}
510178479Sjb
511178479Sjb/*ARGSUSED*/
512178479Sjbstatic int
513178479Sjbdt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
514178479Sjb{
515178479Sjb	int m;
516178479Sjb
517178479Sjb	if (arg == NULL || (m = atoi(arg)) <= 0)
518178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
519178479Sjb
520178479Sjb	dtp->dt_treedump = m;
521178479Sjb	return (0);
522178479Sjb}
523178479Sjb
524178479Sjb/*ARGSUSED*/
525178479Sjbstatic int
526178479Sjbdt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
527178479Sjb{
528178479Sjb	int n;
529178479Sjb
530178479Sjb	if (arg == NULL || (n = atoi(arg)) <= 0)
531178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
532178479Sjb
533178479Sjb	dtp->dt_conf.dtc_diftupregs = n;
534178479Sjb	return (0);
535178479Sjb}
536178479Sjb
537178479Sjb/*ARGSUSED*/
538178479Sjbstatic int
539178479Sjbdt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
540178479Sjb{
541178479Sjb	if (arg == NULL)
542178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
543178479Sjb
544178479Sjb	if (strcmp(arg, "dynamic") == 0)
545178479Sjb		dtp->dt_xlatemode = DT_XL_DYNAMIC;
546178479Sjb	else if (strcmp(arg, "static") == 0)
547178479Sjb		dtp->dt_xlatemode = DT_XL_STATIC;
548178479Sjb	else
549178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
550178479Sjb
551178479Sjb	return (0);
552178479Sjb}
553178479Sjb
554178479Sjb/*ARGSUSED*/
555178479Sjbstatic int
556178479Sjbdt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
557178479Sjb{
558178479Sjb	if (arg != NULL)
559178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
560178479Sjb
561178479Sjb	if (dtp->dt_pcb != NULL)
562178479Sjb		dtp->dt_pcb->pcb_cflags |= option;
563178479Sjb	else
564178479Sjb		dtp->dt_cflags |= option;
565178479Sjb
566178479Sjb	return (0);
567178479Sjb}
568178479Sjb
569178479Sjbstatic int
570178479Sjbdt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
571178479Sjb{
572178479Sjb	if (arg != NULL)
573178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
574178479Sjb
575178479Sjb	dtp->dt_dflags |= option;
576178479Sjb	return (0);
577178479Sjb}
578178479Sjb
579178479Sjbstatic int
580178479Sjbdt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
581178479Sjb{
582178479Sjb	if (arg != NULL)
583178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
584178479Sjb
585178479Sjb	if (dtp->dt_pcb != NULL)
586178479Sjb		dtp->dt_pcb->pcb_cflags &= ~option;
587178479Sjb	else
588178479Sjb		dtp->dt_cflags &= ~option;
589178479Sjb
590178479Sjb	return (0);
591178479Sjb}
592178479Sjb
593178479Sjb/*ARGSUSED*/
594178479Sjbstatic int
595178479Sjbdt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
596178479Sjb{
597178479Sjb	dt_version_t v;
598178479Sjb
599178479Sjb	if (arg == NULL)
600178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
601178479Sjb
602178479Sjb	if (dt_version_str2num(arg, &v) == -1)
603178479Sjb		return (dt_set_errno(dtp, EDT_VERSINVAL));
604178479Sjb
605178479Sjb	if (!dt_version_defined(v))
606178479Sjb		return (dt_set_errno(dtp, EDT_VERSUNDEF));
607178479Sjb
608178479Sjb	return (dt_reduce(dtp, v));
609178479Sjb}
610178479Sjb
611178479Sjbstatic int
612178479Sjbdt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
613178479Sjb{
614178479Sjb	char *end;
615178479Sjb	dtrace_optval_t val = 0;
616178479Sjb	int i;
617178479Sjb
618178479Sjb	const struct {
619178479Sjb		char *positive;
620178479Sjb		char *negative;
621178479Sjb	} couples[] = {
622178479Sjb		{ "yes",	"no" },
623178479Sjb		{ "enable",	"disable" },
624178479Sjb		{ "enabled",	"disabled" },
625178479Sjb		{ "true",	"false" },
626178479Sjb		{ "on",		"off" },
627178479Sjb		{ "set",	"unset" },
628178479Sjb		{ NULL }
629178479Sjb	};
630178479Sjb
631178479Sjb	if (arg != NULL) {
632178479Sjb		if (arg[0] == '\0') {
633178479Sjb			val = DTRACEOPT_UNSET;
634178479Sjb			goto out;
635178479Sjb		}
636178479Sjb
637178479Sjb		for (i = 0; couples[i].positive != NULL; i++) {
638178479Sjb			if (strcasecmp(couples[i].positive, arg) == 0) {
639178479Sjb				val = 1;
640178479Sjb				goto out;
641178479Sjb			}
642178479Sjb
643178479Sjb			if (strcasecmp(couples[i].negative, arg) == 0) {
644178479Sjb				val = DTRACEOPT_UNSET;
645178479Sjb				goto out;
646178479Sjb			}
647178479Sjb		}
648178479Sjb
649178479Sjb		errno = 0;
650178479Sjb		val = strtoull(arg, &end, 0);
651178479Sjb
652178479Sjb		if (*end != '\0' || errno != 0 || val < 0)
653178479Sjb			return (dt_set_errno(dtp, EDT_BADOPTVAL));
654178479Sjb	}
655178479Sjb
656178479Sjbout:
657178479Sjb	dtp->dt_options[option] = val;
658178479Sjb	return (0);
659178479Sjb}
660178479Sjb
661178479Sjbstatic int
662178479Sjbdt_optval_parse(const char *arg, dtrace_optval_t *rval)
663178479Sjb{
664178479Sjb	dtrace_optval_t mul = 1;
665178479Sjb	size_t len;
666178479Sjb	char *end;
667178479Sjb
668178479Sjb	len = strlen(arg);
669178479Sjb	errno = 0;
670178479Sjb
671178479Sjb	switch (arg[len - 1]) {
672178479Sjb	case 't':
673178479Sjb	case 'T':
674178479Sjb		mul *= 1024;
675178479Sjb		/*FALLTHRU*/
676178479Sjb	case 'g':
677178479Sjb	case 'G':
678178479Sjb		mul *= 1024;
679178479Sjb		/*FALLTHRU*/
680178479Sjb	case 'm':
681178479Sjb	case 'M':
682178479Sjb		mul *= 1024;
683178479Sjb		/*FALLTHRU*/
684178479Sjb	case 'k':
685178479Sjb	case 'K':
686178479Sjb		mul *= 1024;
687178479Sjb		/*FALLTHRU*/
688178479Sjb	default:
689178479Sjb		break;
690178479Sjb	}
691178479Sjb
692178479Sjb	errno = 0;
693178479Sjb	*rval = strtoull(arg, &end, 0) * mul;
694178479Sjb
695178479Sjb	if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') ||
696178479Sjb	    *rval < 0 || errno != 0)
697178479Sjb		return (-1);
698178479Sjb
699178479Sjb	return (0);
700178479Sjb}
701178479Sjb
702178479Sjbstatic int
703178479Sjbdt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
704178479Sjb{
705178479Sjb	dtrace_optval_t val = 0;
706178479Sjb
707178479Sjb	if (arg != NULL && dt_optval_parse(arg, &val) != 0)
708178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
709178479Sjb
710178479Sjb	dtp->dt_options[option] = val;
711178479Sjb	return (0);
712178479Sjb}
713178479Sjb
714178479Sjbstatic int
715178479Sjbdt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
716178479Sjb{
717178479Sjb	char *end;
718178479Sjb	int i;
719178479Sjb	dtrace_optval_t mul = 1, val = 0;
720178479Sjb
721178479Sjb	const struct {
722178479Sjb		char *name;
723178479Sjb		hrtime_t mul;
724178479Sjb	} suffix[] = {
725178479Sjb		{ "ns", 	NANOSEC / NANOSEC },
726178479Sjb		{ "nsec",	NANOSEC / NANOSEC },
727178479Sjb		{ "us",		NANOSEC / MICROSEC },
728178479Sjb		{ "usec",	NANOSEC / MICROSEC },
729178479Sjb		{ "ms",		NANOSEC / MILLISEC },
730178479Sjb		{ "msec",	NANOSEC / MILLISEC },
731178479Sjb		{ "s",		NANOSEC / SEC },
732178479Sjb		{ "sec",	NANOSEC / SEC },
733178479Sjb		{ "m",		NANOSEC * (hrtime_t)60 },
734178479Sjb		{ "min",	NANOSEC * (hrtime_t)60 },
735178479Sjb		{ "h",		NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
736178479Sjb		{ "hour",	NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
737178479Sjb		{ "d",		NANOSEC * (hrtime_t)(24 * 60 * 60) },
738178479Sjb		{ "day",	NANOSEC * (hrtime_t)(24 * 60 * 60) },
739178479Sjb		{ "hz",		0 },
740178479Sjb		{ NULL }
741178479Sjb	};
742178479Sjb
743178479Sjb	if (arg != NULL) {
744178479Sjb		errno = 0;
745178479Sjb		val = strtoull(arg, &end, 0);
746178479Sjb
747178479Sjb		for (i = 0; suffix[i].name != NULL; i++) {
748178479Sjb			if (strcasecmp(suffix[i].name, end) == 0) {
749178479Sjb				mul = suffix[i].mul;
750178479Sjb				break;
751178479Sjb			}
752178479Sjb		}
753178479Sjb
754178479Sjb		if (suffix[i].name == NULL && *end != '\0' || val < 0)
755178479Sjb			return (dt_set_errno(dtp, EDT_BADOPTVAL));
756178479Sjb
757178479Sjb		if (mul == 0) {
758178479Sjb			/*
759178479Sjb			 * The rate has been specified in frequency-per-second.
760178479Sjb			 */
761178479Sjb			if (val != 0)
762178479Sjb				val = NANOSEC / val;
763178479Sjb		} else {
764178479Sjb			val *= mul;
765178479Sjb		}
766178479Sjb	}
767178479Sjb
768178479Sjb	dtp->dt_options[option] = val;
769178479Sjb	return (0);
770178479Sjb}
771178479Sjb
772178479Sjb/*
773178479Sjb * When setting the strsize option, set the option in the dt_options array
774178479Sjb * using dt_opt_size() as usual, and then update the definition of the CTF
775178479Sjb * type for the D intrinsic "string" to be an array of the corresponding size.
776178479Sjb * If any errors occur, reset dt_options[option] to its previous value.
777178479Sjb */
778178479Sjbstatic int
779178479Sjbdt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
780178479Sjb{
781178479Sjb	dtrace_optval_t val = dtp->dt_options[option];
782178479Sjb	ctf_file_t *fp = DT_STR_CTFP(dtp);
783178479Sjb	ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp));
784178479Sjb	ctf_arinfo_t r;
785178479Sjb
786178479Sjb	if (dt_opt_size(dtp, arg, option) != 0)
787178479Sjb		return (-1); /* dt_errno is set for us */
788178479Sjb
789178479Sjb	if (dtp->dt_options[option] > UINT_MAX) {
790178479Sjb		dtp->dt_options[option] = val;
791178479Sjb		return (dt_set_errno(dtp, EOVERFLOW));
792178479Sjb	}
793178479Sjb
794178479Sjb	if (ctf_array_info(fp, type, &r) == CTF_ERR) {
795178479Sjb		dtp->dt_options[option] = val;
796178479Sjb		dtp->dt_ctferr = ctf_errno(fp);
797178479Sjb		return (dt_set_errno(dtp, EDT_CTF));
798178479Sjb	}
799178479Sjb
800178479Sjb	r.ctr_nelems = (uint_t)dtp->dt_options[option];
801178479Sjb
802178479Sjb	if (ctf_set_array(fp, type, &r) == CTF_ERR ||
803178479Sjb	    ctf_update(fp) == CTF_ERR) {
804178479Sjb		dtp->dt_options[option] = val;
805178479Sjb		dtp->dt_ctferr = ctf_errno(fp);
806178479Sjb		return (dt_set_errno(dtp, EDT_CTF));
807178479Sjb	}
808178479Sjb
809178479Sjb	return (0);
810178479Sjb}
811178479Sjb
812178479Sjbstatic const struct {
813178479Sjb	const char *dtbp_name;
814178479Sjb	int dtbp_policy;
815178479Sjb} _dtrace_bufpolicies[] = {
816178479Sjb	{ "ring", DTRACEOPT_BUFPOLICY_RING },
817178479Sjb	{ "fill", DTRACEOPT_BUFPOLICY_FILL },
818178479Sjb	{ "switch", DTRACEOPT_BUFPOLICY_SWITCH },
819178479Sjb	{ NULL, 0 }
820178479Sjb};
821178479Sjb
822178479Sjb/*ARGSUSED*/
823178479Sjbstatic int
824178479Sjbdt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
825178479Sjb{
826178479Sjb	dtrace_optval_t policy = DTRACEOPT_UNSET;
827178479Sjb	int i;
828178479Sjb
829178479Sjb	if (arg == NULL)
830178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
831178479Sjb
832178479Sjb	for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) {
833178479Sjb		if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) {
834178479Sjb			policy = _dtrace_bufpolicies[i].dtbp_policy;
835178479Sjb			break;
836178479Sjb		}
837178479Sjb	}
838178479Sjb
839178479Sjb	if (policy == DTRACEOPT_UNSET)
840178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
841178479Sjb
842178479Sjb	dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy;
843178479Sjb
844178479Sjb	return (0);
845178479Sjb}
846178479Sjb
847178479Sjbstatic const struct {
848178479Sjb	const char *dtbr_name;
849178479Sjb	int dtbr_policy;
850178479Sjb} _dtrace_bufresize[] = {
851178479Sjb	{ "auto", DTRACEOPT_BUFRESIZE_AUTO },
852178479Sjb	{ "manual", DTRACEOPT_BUFRESIZE_MANUAL },
853178479Sjb	{ NULL, 0 }
854178479Sjb};
855178479Sjb
856178479Sjb/*ARGSUSED*/
857178479Sjbstatic int
858178479Sjbdt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
859178479Sjb{
860178479Sjb	dtrace_optval_t policy = DTRACEOPT_UNSET;
861178479Sjb	int i;
862178479Sjb
863178479Sjb	if (arg == NULL)
864178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
865178479Sjb
866178479Sjb	for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) {
867178479Sjb		if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) {
868178479Sjb			policy = _dtrace_bufresize[i].dtbr_policy;
869178479Sjb			break;
870178479Sjb		}
871178479Sjb	}
872178479Sjb
873178479Sjb	if (policy == DTRACEOPT_UNSET)
874178479Sjb		return (dt_set_errno(dtp, EDT_BADOPTVAL));
875178479Sjb
876178479Sjb	dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy;
877178479Sjb
878178479Sjb	return (0);
879178479Sjb}
880178479Sjb
881178479Sjbint
882178479Sjbdt_options_load(dtrace_hdl_t *dtp)
883178479Sjb{
884178479Sjb	dof_hdr_t hdr, *dof;
885178479Sjb	dof_sec_t *sec;
886178479Sjb	size_t offs;
887178479Sjb	int i;
888178479Sjb
889178479Sjb	/*
890178479Sjb	 * To load the option values, we need to ask the kernel to provide its
891178479Sjb	 * DOF, which we'll sift through to look for OPTDESC sections.
892178479Sjb	 */
893178479Sjb	bzero(&hdr, sizeof (dof_hdr_t));
894178479Sjb	hdr.dofh_loadsz = sizeof (dof_hdr_t);
895178479Sjb
896277300Ssmh#ifdef illumos
897178479Sjb	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1)
898178569Sjb#else
899178569Sjb	dof = &hdr;
900178569Sjb	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)
901178569Sjb#endif
902178479Sjb		return (dt_set_errno(dtp, errno));
903178479Sjb
904178479Sjb	if (hdr.dofh_loadsz < sizeof (dof_hdr_t))
905178479Sjb		return (dt_set_errno(dtp, EINVAL));
906178479Sjb
907178479Sjb	dof = alloca(hdr.dofh_loadsz);
908178479Sjb	bzero(dof, sizeof (dof_hdr_t));
909178479Sjb	dof->dofh_loadsz = hdr.dofh_loadsz;
910178479Sjb
911178479Sjb	for (i = 0; i < DTRACEOPT_MAX; i++)
912178479Sjb		dtp->dt_options[i] = DTRACEOPT_UNSET;
913178479Sjb
914277300Ssmh#ifdef illumos
915178479Sjb	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1)
916178569Sjb#else
917178569Sjb	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)
918178569Sjb#endif
919178479Sjb		return (dt_set_errno(dtp, errno));
920178479Sjb
921178479Sjb	for (i = 0; i < dof->dofh_secnum; i++) {
922178479Sjb		sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof +
923178479Sjb		    dof->dofh_secoff + i * dof->dofh_secsize);
924178479Sjb
925178479Sjb		if (sec->dofs_type != DOF_SECT_OPTDESC)
926178479Sjb			continue;
927178479Sjb
928178479Sjb		break;
929178479Sjb	}
930178479Sjb
931178479Sjb	for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {
932178479Sjb		dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t)
933178479Sjb		    ((uintptr_t)dof + sec->dofs_offset + offs);
934178479Sjb
935178479Sjb		if (opt->dofo_strtab != DOF_SECIDX_NONE)
936178479Sjb			continue;
937178479Sjb
938178479Sjb		if (opt->dofo_option >= DTRACEOPT_MAX)
939178479Sjb			continue;
940178479Sjb
941178479Sjb		dtp->dt_options[opt->dofo_option] = opt->dofo_value;
942178479Sjb	}
943178479Sjb
944178479Sjb	return (0);
945178479Sjb}
946178479Sjb
947178479Sjbtypedef struct dt_option {
948178479Sjb	const char *o_name;
949178479Sjb	int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
950178479Sjb	uintptr_t o_option;
951178479Sjb} dt_option_t;
952178479Sjb
953178479Sjb/*
954178479Sjb * Compile-time options.
955178479Sjb */
956178479Sjbstatic const dt_option_t _dtrace_ctoptions[] = {
957178479Sjb	{ "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU },
958178479Sjb	{ "amin", dt_opt_amin },
959178479Sjb	{ "argref", dt_opt_cflags, DTRACE_C_ARGREF },
960178479Sjb	{ "core", dt_opt_core },
961178479Sjb	{ "cpp", dt_opt_cflags, DTRACE_C_CPP },
962178479Sjb	{ "cpphdrs", dt_opt_cpp_hdrs },
963178479Sjb	{ "cpppath", dt_opt_cpp_path },
964178479Sjb	{ "ctypes", dt_opt_ctypes },
965178479Sjb	{ "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG },
966178479Sjb	{ "dtypes", dt_opt_dtypes },
967178479Sjb	{ "debug", dt_opt_debug },
968178479Sjb	{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
969178479Sjb	{ "droptags", dt_opt_droptags },
970178479Sjb	{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
971267942Srpaulo	{ "encoding", dt_opt_encoding },
972178479Sjb	{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
973178479Sjb	{ "evaltime", dt_opt_evaltime },
974178479Sjb	{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
975178479Sjb	{ "iregs", dt_opt_iregs },
976178479Sjb	{ "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF },
977178479Sjb	{ "knodefs", dt_opt_cflags, DTRACE_C_KNODEF },
978178479Sjb	{ "late", dt_opt_xlate },
979178479Sjb	{ "lazyload", dt_opt_lazyload },
980178479Sjb	{ "ldpath", dt_opt_ld_path },
981178479Sjb	{ "libdir", dt_opt_libdir },
982178479Sjb	{ "linkmode", dt_opt_linkmode },
983178479Sjb	{ "linktype", dt_opt_linktype },
984178479Sjb	{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
985278934Smarkj#ifdef __FreeBSD__
986278934Smarkj	{ "objcopypath", dt_opt_objcopy_path },
987278934Smarkj#endif
988178479Sjb	{ "pgmax", dt_opt_pgmax },
989178479Sjb	{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
990250574Smarkj	{ "setenv", dt_opt_setenv, 1 },
991178479Sjb	{ "stdc", dt_opt_stdc },
992178479Sjb	{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
993178479Sjb	{ "syslibdir", dt_opt_syslibdir },
994178479Sjb	{ "tree", dt_opt_tree },
995178479Sjb	{ "tregs", dt_opt_tregs },
996178479Sjb	{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
997178479Sjb	{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
998178479Sjb	{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
999250574Smarkj	{ "unsetenv", dt_opt_setenv, 0 },
1000178479Sjb	{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
1001178479Sjb	{ "version", dt_opt_version },
1002178479Sjb	{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
1003178569Sjb	{ NULL, NULL, 0 }
1004178479Sjb};
1005178479Sjb
1006178479Sjb/*
1007178479Sjb * Run-time options.
1008178479Sjb */
1009178479Sjbstatic const dt_option_t _dtrace_rtoptions[] = {
1010178479Sjb	{ "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE },
1011178479Sjb	{ "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE },
1012178479Sjb	{ "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY },
1013178479Sjb	{ "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE },
1014178479Sjb	{ "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE },
1015178479Sjb	{ "cpu", dt_opt_runtime, DTRACEOPT_CPU },
1016178479Sjb	{ "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE },
1017178479Sjb	{ "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE },
1018178479Sjb	{ "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON },
1019178479Sjb	{ "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES },
1020178479Sjb	{ "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE },
1021178479Sjb	{ "nspec", dt_opt_runtime, DTRACEOPT_NSPEC },
1022178479Sjb	{ "specsize", dt_opt_size, DTRACEOPT_SPECSIZE },
1023178479Sjb	{ "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES },
1024178479Sjb	{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
1025178479Sjb	{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
1026178479Sjb	{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
1027250574Smarkj	{ "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },
1028178569Sjb	{ NULL, NULL, 0 }
1029178479Sjb};
1030178479Sjb
1031178479Sjb/*
1032178479Sjb * Dynamic run-time options.
1033178479Sjb */
1034178479Sjbstatic const dt_option_t _dtrace_drtoptions[] = {
1035267942Srpaulo	{ "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST },
1036267942Srpaulo	{ "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK },
1037178479Sjb	{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
1038178479Sjb	{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },
1039178479Sjb	{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },
1040178479Sjb	{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },
1041178479Sjb	{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },
1042267942Srpaulo	{ "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM },
1043178479Sjb	{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
1044178479Sjb	{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
1045178479Sjb	{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
1046178479Sjb	{ "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT },
1047178479Sjb	{ "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE },
1048178569Sjb	{ NULL, NULL, 0 }
1049178479Sjb};
1050178479Sjb
1051178479Sjbint
1052178479Sjbdtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val)
1053178479Sjb{
1054178479Sjb	const dt_option_t *op;
1055178479Sjb
1056178479Sjb	if (opt == NULL)
1057178479Sjb		return (dt_set_errno(dtp, EINVAL));
1058178479Sjb
1059178479Sjb	/*
1060178479Sjb	 * We only need to search the run-time options -- it's not legal
1061178479Sjb	 * to get the values of compile-time options.
1062178479Sjb	 */
1063178479Sjb	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
1064178479Sjb		if (strcmp(op->o_name, opt) == 0) {
1065178479Sjb			*val = dtp->dt_options[op->o_option];
1066178479Sjb			return (0);
1067178479Sjb		}
1068178479Sjb	}
1069178479Sjb
1070178479Sjb	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
1071178479Sjb		if (strcmp(op->o_name, opt) == 0) {
1072178479Sjb			*val = dtp->dt_options[op->o_option];
1073178479Sjb			return (0);
1074178479Sjb		}
1075178479Sjb	}
1076178479Sjb
1077178479Sjb	return (dt_set_errno(dtp, EDT_BADOPTNAME));
1078178479Sjb}
1079178479Sjb
1080178479Sjbint
1081178479Sjbdtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val)
1082178479Sjb{
1083178479Sjb	const dt_option_t *op;
1084178479Sjb
1085178479Sjb	if (opt == NULL)
1086178479Sjb		return (dt_set_errno(dtp, EINVAL));
1087178479Sjb
1088178479Sjb	for (op = _dtrace_ctoptions; op->o_name != NULL; op++) {
1089178479Sjb		if (strcmp(op->o_name, opt) == 0)
1090178479Sjb			return (op->o_func(dtp, val, op->o_option));
1091178479Sjb	}
1092178479Sjb
1093178479Sjb	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
1094178479Sjb		if (strcmp(op->o_name, opt) == 0)
1095178479Sjb			return (op->o_func(dtp, val, op->o_option));
1096178479Sjb	}
1097178479Sjb
1098178479Sjb	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
1099178479Sjb		if (strcmp(op->o_name, opt) == 0) {
1100178479Sjb			/*
1101178479Sjb			 * Only dynamic run-time options may be set while
1102178479Sjb			 * tracing is active.
1103178479Sjb			 */
1104178479Sjb			if (dtp->dt_active)
1105178479Sjb				return (dt_set_errno(dtp, EDT_ACTIVE));
1106178479Sjb
1107178479Sjb			return (op->o_func(dtp, val, op->o_option));
1108178479Sjb		}
1109178479Sjb	}
1110178479Sjb
1111178479Sjb	return (dt_set_errno(dtp, EDT_BADOPTNAME));
1112178479Sjb}
1113