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