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