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