Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
39562 views
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
}
1154
1155