Bug Summary

File:src/usr.sbin/btrace/btrace.c
Warning:line 1443, column 17
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name btrace.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/btrace/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D PTRACE -D KTRACE -D ACCOUNTING -D NFSCLIENT -D SYSVSHM -D SYSVSEM -D SYSVMSG -I /usr/src/usr.sbin/btrace -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -Wno-unused -fdebug-compilation-dir=/usr/src/usr.sbin/btrace/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/btrace/btrace.c
1/* $OpenBSD: btrace.c,v 1.81 2023/11/10 18:56:21 jasper Exp $ */
2
3/*
4 * Copyright (c) 2019 - 2023 Martin Pieuchot <mpi@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/ioctl.h>
20#include <sys/stat.h>
21#include <sys/syscall.h>
22#include <sys/queue.h>
23
24#include <assert.h>
25#include <err.h>
26#include <errno(*__errno()).h>
27#include <fcntl.h>
28#include <limits.h>
29#include <locale.h>
30#include <paths.h>
31#include <signal.h>
32#include <stdarg.h>
33#include <stdbool.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <time.h>
38#include <unistd.h>
39
40#include <dev/dt/dtvar.h>
41
42#include "btrace.h"
43#include "bt_parser.h"
44
45#define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
46#define MAXIMUM(a, b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b))
47
48/*
49 * Maximum number of operands an arithmetic operation can have. This
50 * is necessary to stop infinite recursion when evaluating expressions.
51 */
52#define __MAXOPERANDS5 5
53
54#define __PATH_DEVDT"/dev/dt" "/dev/dt"
55
56__dead__attribute__((__noreturn__)) void usage(void);
57char *read_btfile(const char *, size_t *);
58
59/*
60 * Retrieve & parse probe information.
61 */
62void dtpi_cache(int);
63void dtpi_print_list(int);
64const char *dtpi_func(struct dtioc_probe_info *);
65int dtpi_is_unit(const char *);
66struct dtioc_probe_info *dtpi_get_by_value(const char *, const char *,
67 const char *);
68
69/*
70 * Main loop and rule evaluation.
71 */
72void rules_do(int);
73int rules_setup(int);
74int rules_apply(int, struct dt_evt *);
75void rules_teardown(int);
76int rule_eval(struct bt_rule *, struct dt_evt *);
77void rule_printmaps(struct bt_rule *);
78
79/*
80 * Language builtins & functions.
81 */
82uint64_t builtin_nsecs(struct dt_evt *);
83const char *builtin_kstack(struct dt_evt *);
84const char *builtin_arg(struct dt_evt *, enum bt_argtype);
85struct bt_arg *fn_str(struct bt_arg *, struct dt_evt *, char *);
86int stmt_eval(struct bt_stmt *, struct dt_evt *);
87void stmt_bucketize(struct bt_stmt *, struct dt_evt *);
88void stmt_clear(struct bt_stmt *);
89void stmt_delete(struct bt_stmt *, struct dt_evt *);
90void stmt_insert(struct bt_stmt *, struct dt_evt *);
91void stmt_print(struct bt_stmt *, struct dt_evt *);
92void stmt_store(struct bt_stmt *, struct dt_evt *);
93bool_Bool stmt_test(struct bt_stmt *, struct dt_evt *);
94void stmt_time(struct bt_stmt *, struct dt_evt *);
95void stmt_zero(struct bt_stmt *);
96struct bt_arg *ba_read(struct bt_arg *);
97struct bt_arg *baeval(struct bt_arg *, struct dt_evt *);
98const char *ba2hash(struct bt_arg *, struct dt_evt *);
99long baexpr2long(struct bt_arg *, struct dt_evt *);
100const char *ba2bucket(struct bt_arg *, struct bt_arg *,
101 struct dt_evt *, long *);
102int ba2dtflags(struct bt_arg *);
103
104/*
105 * Debug routines.
106 */
107__dead__attribute__((__noreturn__)) void xabort(const char *, ...);
108void debug(const char *, ...);
109void debugx(const char *, ...);
110const char *debug_probe_name(struct bt_probe *);
111void debug_dump_term(struct bt_arg *);
112void debug_dump_expr(struct bt_arg *);
113void debug_dump_filter(struct bt_rule *);
114
115struct dtioc_probe_info *dt_dtpis; /* array of available probes */
116size_t dt_ndtpi; /* # of elements in the array */
117struct dtioc_arg_info **dt_args; /* array of probe arguments */
118
119struct dt_evt bt_devt; /* fake event for BEGIN/END */
120#define EVENT_BEGIN0 0
121#define EVENT_END(unsigned int)(-1) (unsigned int)(-1)
122uint64_t bt_filtered; /* # of events filtered out */
123
124struct syms *kelf, *uelf;
125
126char **vargs;
127int nargs = 0;
128int verbose = 0;
129int dtfd;
130volatile sig_atomic_t quit_pending;
131
132static void
133signal_handler(int sig)
134{
135 quit_pending = sig;
136}
137
138
139int
140main(int argc, char *argv[])
141{
142 int fd = -1, ch, error = 0;
143 const char *filename = NULL((void *)0), *btscript = NULL((void *)0);
144 int showprobes = 0, noaction = 0;
145 size_t btslen = 0;
146
147 setlocale(LC_ALL0, "");
148
149 while ((ch = getopt(argc, argv, "e:lnp:v")) != -1) {
150 switch (ch) {
151 case 'e':
152 btscript = optarg;
153 btslen = strlen(btscript);
154 break;
155 case 'l':
156 showprobes = 1;
157 break;
158 case 'n':
159 noaction = 1;
160 break;
161 case 'p':
162 uelf = kelf_open(optarg);
163 break;
164 case 'v':
165 verbose++;
166 break;
167 default:
168 usage();
169 }
170 }
171
172 argc -= optind;
173 argv += optind;
174
175 if (argc > 0 && btscript == NULL((void *)0))
176 filename = argv[0];
177
178 /* Cannot pledge due to special ioctl()s */
179 if (unveil(__PATH_DEVDT"/dev/dt", "r") == -1)
180 err(1, "unveil %s", __PATH_DEVDT"/dev/dt");
181 if (unveil(_PATH_KSYMS"/dev/ksyms", "r") == -1)
182 err(1, "unveil %s", _PATH_KSYMS"/dev/ksyms");
183 if (filename != NULL((void *)0)) {
184 if (unveil(filename, "r") == -1)
185 err(1, "unveil %s", filename);
186 }
187 if (unveil(NULL((void *)0), NULL((void *)0)) == -1)
188 err(1, "unveil");
189
190 if (filename != NULL((void *)0)) {
191 btscript = read_btfile(filename, &btslen);
192 argc--;
193 argv++;
194 }
195
196 nargs = argc;
197 vargs = argv;
198
199 if (btscript == NULL((void *)0) && !showprobes)
200 usage();
201
202 if (btscript != NULL((void *)0)) {
203 error = btparse(btscript, btslen, filename, 1);
204 if (error)
205 return error;
206 }
207
208 if (noaction)
209 return error;
210
211 if (showprobes || g_nprobes > 0) {
212 fd = open(__PATH_DEVDT"/dev/dt", O_RDONLY0x0000);
213 if (fd == -1)
214 err(1, "could not open %s", __PATH_DEVDT"/dev/dt");
215 dtfd = fd;
216 }
217
218 if (showprobes) {
219 dtpi_cache(fd);
220 dtpi_print_list(fd);
221 }
222
223 if (!TAILQ_EMPTY(&g_rules)(((&g_rules)->tqh_first) == ((void *)0)))
224 rules_do(fd);
225
226 if (fd != -1)
227 close(fd);
228
229 return error;
230}
231
232__dead__attribute__((__noreturn__)) void
233usage(void)
234{
235 fprintf(stderr(&__sF[2]), "usage: %s [-lnv] [-e program | file] [-p file] "
236 "[argument ...]\n", getprogname());
237 exit(1);
238}
239
240char *
241read_btfile(const char *filename, size_t *len)
242{
243 FILE *fp;
244 char *fcontent;
245 struct stat st;
246 size_t fsize;
247
248 if (stat(filename, &st))
249 err(1, "can't stat '%s'", filename);
250
251 fsize = st.st_size;
252 fcontent = malloc(fsize + 1);
253 if (fcontent == NULL((void *)0))
254 err(1, "malloc");
255
256 fp = fopen(filename, "r");
257 if (fp == NULL((void *)0))
258 err(1, "can't open '%s'", filename);
259
260 if (fread(fcontent, 1, fsize, fp) != fsize)
261 err(1, "can't read '%s'", filename);
262 fcontent[fsize] = '\0';
263
264 fclose(fp);
265 *len = fsize;
266 return fcontent;
267}
268
269void
270dtpi_cache(int fd)
271{
272 struct dtioc_probe dtpr;
273
274 if (dt_dtpis != NULL((void *)0))
275 return;
276
277 memset(&dtpr, 0, sizeof(dtpr));
278 if (ioctl(fd, DTIOCGPLIST(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct dtioc_probe) & 0x1fff) << 16) | ((('D')) <<
8) | ((1)))
, &dtpr))
279 err(1, "DTIOCGPLIST");
280
281 dt_ndtpi = dtpr.dtpr_size / sizeof(*dt_dtpis);
282 dt_dtpis = reallocarray(NULL((void *)0), dt_ndtpi, sizeof(*dt_dtpis));
283 if (dt_dtpis == NULL((void *)0))
284 err(1, NULL((void *)0));
285
286 dtpr.dtpr_probes = dt_dtpis;
287 if (ioctl(fd, DTIOCGPLIST(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct dtioc_probe) & 0x1fff) << 16) | ((('D')) <<
8) | ((1)))
, &dtpr))
288 err(1, "DTIOCGPLIST");
289}
290
291void
292dtai_cache(int fd, struct dtioc_probe_info *dtpi)
293{
294 struct dtioc_arg dtar;
295
296 if (dt_args == NULL((void *)0)) {
297 dt_args = calloc(dt_ndtpi, sizeof(*dt_args));
298 if (dt_args == NULL((void *)0))
299 err(1, NULL((void *)0));
300 }
301
302 if (dt_args[dtpi->dtpi_pbn - 1] != NULL((void *)0))
303 return;
304
305 dt_args[dtpi->dtpi_pbn - 1] = reallocarray(NULL((void *)0), dtpi->dtpi_nargs,
306 sizeof(**dt_args));
307 if (dt_args[dtpi->dtpi_pbn - 1] == NULL((void *)0))
308 err(1, NULL((void *)0));
309
310 dtar.dtar_pbn = dtpi->dtpi_pbn;
311 dtar.dtar_size = dtpi->dtpi_nargs * sizeof(**dt_args);
312 dtar.dtar_args = dt_args[dtpi->dtpi_pbn - 1];
313 if (ioctl(fd, DTIOCGARGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct dtioc_arg) & 0x1fff) << 16) | ((('D')) <<
8) | ((6)))
, &dtar))
314 err(1, "DTIOCGARGS");
315}
316
317void
318dtpi_print_list(int fd)
319{
320 struct dtioc_probe_info *dtpi;
321 struct dtioc_arg_info *dtai;
322 size_t i, j;
323
324 dtpi = dt_dtpis;
325 for (i = 0; i < dt_ndtpi; i++, dtpi++) {
326 printf("%s:%s:%s", dtpi->dtpi_prov, dtpi_func(dtpi),
327 dtpi->dtpi_name);
328 if (strncmp(dtpi->dtpi_prov, "tracepoint", DTNAMESIZE16) == 0) {
329 dtai_cache(fd, dtpi);
330 dtai = dt_args[dtpi->dtpi_pbn - 1];
331 printf("(");
332 for (j = 0; j < dtpi->dtpi_nargs; j++, dtai++) {
333 if (j > 0)
334 printf(", ");
335 printf("%s", dtai->dtai_argtype);
336 }
337 printf(")");
338 }
339 printf("\n");
340 }
341}
342
343const char *
344dtpi_func(struct dtioc_probe_info *dtpi)
345{
346 char *sysnb, func[DTNAMESIZE16];
347 const char *errstr;
348 int idx;
349
350 if (strncmp(dtpi->dtpi_prov, "syscall", DTNAMESIZE16))
351 return dtpi->dtpi_func;
352
353 /* Translate syscall names */
354 strlcpy(func, dtpi->dtpi_func, sizeof(func));
355 sysnb = func;
356 if (strsep(&sysnb, "%") == NULL((void *)0))
357 return dtpi->dtpi_func;
358
359 idx = strtonum(sysnb, 1, SYS_MAXSYSCALL331, &errstr);
360 if (errstr != NULL((void *)0))
361 return dtpi->dtpi_func;
362
363 return syscallnames[idx];
364}
365
366int
367dtpi_is_unit(const char *unit)
368{
369 return !strncmp("hz", unit, sizeof("hz"));
370}
371
372struct dtioc_probe_info *
373dtpi_get_by_value(const char *prov, const char *func, const char *name)
374{
375 struct dtioc_probe_info *dtpi;
376 size_t i;
377
378 dtpi = dt_dtpis;
379 for (i = 0; i < dt_ndtpi; i++, dtpi++) {
380 if (prov != NULL((void *)0) &&
381 strncmp(prov, dtpi->dtpi_prov, DTNAMESIZE16))
382 continue;
383
384 if (func != NULL((void *)0)) {
385 if (dtpi_is_unit(func))
386 return dtpi;
387
388 if (strncmp(func, dtpi_func(dtpi), DTNAMESIZE16))
389 continue;
390 }
391
392 if (strncmp(name, dtpi->dtpi_name, DTNAMESIZE16))
393 continue;
394
395 debug("matched probe %s:%s:%s\n", dtpi->dtpi_prov,
396 dtpi_func(dtpi), dtpi->dtpi_name);
397 return dtpi;
398 }
399
400 return NULL((void *)0);
401}
402
403void
404rules_do(int fd)
405{
406 struct sigaction sa;
407 int halt = 0;
408
409 memset(&sa, 0, sizeof(sa));
410 sigemptyset(&sa.sa_mask);
411 sa.sa_flags = 0;
412 sa.sa_handler__sigaction_u.__sa_handler = signal_handler;
413 if (sigaction(SIGINT2, &sa, NULL((void *)0)))
414 err(1, "sigaction");
415 if (sigaction(SIGTERM15, &sa, NULL((void *)0)))
416 err(1, "sigaction");
417
418 halt = rules_setup(fd);
419
420 while (!quit_pending && !halt && g_nprobes > 0) {
421 static struct dt_evt devtbuf[64];
422 ssize_t rlen;
423 size_t i;
424
425 rlen = read(fd, devtbuf, sizeof(devtbuf) - 1);
426 if (rlen == -1) {
427 if (errno(*__errno()) == EINTR4 && quit_pending) {
428 printf("\n");
429 break;
430 }
431 err(1, "read");
432 }
433
434 if ((rlen % sizeof(struct dt_evt)) != 0)
435 err(1, "incorrect read");
436
437 for (i = 0; i < rlen / sizeof(struct dt_evt); i++) {
438 halt = rules_apply(fd, &devtbuf[i]);
439 if (halt)
440 break;
441 }
442 }
443
444 rules_teardown(fd);
445
446 if (verbose && fd != -1) {
447 struct dtioc_stat dtst;
448
449 memset(&dtst, 0, sizeof(dtst));
450 if (ioctl(fd, DTIOCGSTATS((unsigned long)0x40000000 | ((sizeof(struct dtioc_stat) &
0x1fff) << 16) | ((('D')) << 8) | ((2)))
, &dtst))
451 warn("DTIOCGSTATS");
452
453 printf("%llu events read\n", dtst.dtst_readevt);
454 printf("%llu events dropped\n", dtst.dtst_dropevt);
455 printf("%llu events filtered\n", bt_filtered);
456 }
457}
458
459static uint64_t
460rules_action_scan(struct bt_stmt *bs)
461{
462 struct bt_arg *ba;
463 uint64_t evtflags = 0;
464
465 while (bs != NULL((void *)0)) {
466 SLIST_FOREACH(ba, &bs->bs_args, ba_next)for((ba) = ((&bs->bs_args)->slh_first); (ba) != ((void
*)0); (ba) = ((ba)->ba_next.sle_next))
467 evtflags |= ba2dtflags(ba);
468
469 /* Also check the value for map/hist insertion */
470 switch (bs->bs_act) {
471 case B_AC_BUCKETIZE:
472 case B_AC_INSERT:
473 ba = (struct bt_arg *)bs->bs_var;
474 evtflags |= ba2dtflags(ba);
475 break;
476 case B_AC_TEST:
477 evtflags |= rules_action_scan(
478 (struct bt_stmt *)bs->bs_var);
479 break;
480 default:
481 break;
482 }
483
484 bs = SLIST_NEXT(bs, bs_next)((bs)->bs_next.sle_next);
485 }
486
487 return evtflags;
488}
489
490int
491rules_setup(int fd)
492{
493 struct dtioc_probe_info *dtpi;
494 struct dtioc_req *dtrq;
495 struct bt_rule *r, *rbegin = NULL((void *)0);
496 struct bt_probe *bp;
497 struct bt_stmt *bs;
498 struct bt_arg *ba;
499 int dokstack = 0, halt = 0, on = 1;
500 uint64_t evtflags;
501
502 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
{
503 evtflags = 0;
504
505 if (r->br_filter != NULL((void *)0) &&
506 r->br_filter->bf_condition != NULL((void *)0)) {
507
508 bs = r->br_filter->bf_condition;
509 ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
510
511 evtflags |= ba2dtflags(ba);
512 }
513
514 evtflags |= rules_action_scan(SLIST_FIRST(&r->br_action)((&r->br_action)->slh_first));
515
516 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
517 debug("parsed probe '%s'", debug_probe_name(bp));
518 debug_dump_filter(r);
519
520 if (bp->bp_type != B_PT_PROBE) {
521 if (bp->bp_type == B_PT_BEGIN)
522 rbegin = r;
523 continue;
524 }
525
526 dtpi_cache(fd);
527 dtpi = dtpi_get_by_value(bp->bp_prov, bp->bp_func,
528 bp->bp_name);
529 if (dtpi == NULL((void *)0)) {
530 errx(1, "probe '%s:%s:%s' not found",
531 bp->bp_prov, bp->bp_func, bp->bp_name);
532 }
533
534 dtrq = calloc(1, sizeof(*dtrq));
535 if (dtrq == NULL((void *)0))
536 err(1, "dtrq: 1alloc");
537
538 bp->bp_pbn = dtpi->dtpi_pbn;
539 dtrq->dtrq_pbn = dtpi->dtpi_pbn;
540 dtrq->dtrq_rate = bp->bp_rate;
541 dtrq->dtrq_evtflags = evtflags;
542 if (dtrq->dtrq_evtflags & DTEVT_KSTACK(1 << 2))
543 dokstack = 1;
544 bp->bp_cookie = dtrq;
545 }
546 }
547
548 if (dokstack)
549 kelf = kelf_open(_PATH_KSYMS"/dev/ksyms");
550
551 /* Initialize "fake" event for BEGIN/END */
552 bt_devt.dtev_pbn = EVENT_BEGIN0;
553 strlcpy(bt_devt.dtev_comm, getprogname(), sizeof(bt_devt.dtev_comm));
554 bt_devt.dtev_pid = getpid();
555 bt_devt.dtev_tid = getthrid();
556 clock_gettime(CLOCK_REALTIME0, &bt_devt.dtev_tsp);
557
558 if (rbegin)
559 halt = rule_eval(rbegin, &bt_devt);
560
561 /* Enable all probes */
562 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
{
563 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
564 if (bp->bp_type != B_PT_PROBE)
565 continue;
566
567 dtrq = bp->bp_cookie;
568 if (ioctl(fd, DTIOCPRBENABLE((unsigned long)0x80000000 | ((sizeof(struct dtioc_req) &
0x1fff) << 16) | ((('D')) << 8) | ((4)))
, dtrq))
569 err(1, "DTIOCPRBENABLE");
570 }
571 }
572
573 if (g_nprobes > 0) {
574 if (ioctl(fd, DTIOCRECORD((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('D')) << 8) | ((3)))
, &on))
575 err(1, "DTIOCRECORD");
576 }
577
578 return halt;
579}
580
581/*
582 * Returns non-zero if the program should halt.
583 */
584int
585rules_apply(int fd, struct dt_evt *dtev)
586{
587 struct bt_rule *r;
588 struct bt_probe *bp;
589
590 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
{
591 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
592 if (bp->bp_type != B_PT_PROBE ||
593 bp->bp_pbn != dtev->dtev_pbn)
594 continue;
595
596 dtai_cache(fd, &dt_dtpis[dtev->dtev_pbn - 1]);
597 if (rule_eval(r, dtev))
598 return 1;
599 }
600 }
601 return 0;
602}
603
604void
605rules_teardown(int fd)
606{
607 struct dtioc_req *dtrq;
608 struct bt_probe *bp;
609 struct bt_rule *r, *rend = NULL((void *)0);
610 int dokstack = 0, off = 0;
611
612 if (g_nprobes > 0) {
613 if (ioctl(fd, DTIOCRECORD((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('D')) << 8) | ((3)))
, &off))
614 err(1, "DTIOCRECORD");
615 }
616
617 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
{
618 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
619 if (bp->bp_type != B_PT_PROBE) {
620 if (bp->bp_type == B_PT_END)
621 rend = r;
622 continue;
623 }
624
625 dtrq = bp->bp_cookie;
626 if (ioctl(fd, DTIOCPRBDISABLE((unsigned long)0x80000000 | ((sizeof(struct dtioc_req) &
0x1fff) << 16) | ((('D')) << 8) | ((5)))
, dtrq))
627 err(1, "DTIOCPRBDISABLE");
628 if (dtrq->dtrq_evtflags & DTEVT_KSTACK(1 << 2))
629 dokstack = 1;
630 }
631 }
632
633 kelf_close(kelf);
634 kelf = NULL((void *)0);
635 kelf_close(uelf);
636 uelf = NULL((void *)0);
637
638 /* Update "fake" event for BEGIN/END */
639 bt_devt.dtev_pbn = EVENT_END(unsigned int)(-1);
640 clock_gettime(CLOCK_REALTIME0, &bt_devt.dtev_tsp);
641
642 if (rend)
643 rule_eval(rend, &bt_devt);
644
645 /* Print non-empty map & hist */
646 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
647 rule_printmaps(r);
648}
649
650/*
651 * Returns non-zero if the program should halt.
652 */
653int
654rule_eval(struct bt_rule *r, struct dt_evt *dtev)
655{
656 struct bt_stmt *bs;
657 struct bt_probe *bp;
658
659 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
660 debug("eval rule '%s'", debug_probe_name(bp));
661 debug_dump_filter(r);
662 }
663
664 if (r->br_filter != NULL((void *)0) && r->br_filter->bf_condition != NULL((void *)0)) {
665 if (stmt_test(r->br_filter->bf_condition, dtev) == false0) {
666 bt_filtered++;
667 return 0;
668 }
669 }
670
671 SLIST_FOREACH(bs, &r->br_action, bs_next)for((bs) = ((&r->br_action)->slh_first); (bs) != ((
void *)0); (bs) = ((bs)->bs_next.sle_next))
{
672 if ((bs->bs_act == B_AC_TEST) && stmt_test(bs, dtev) == true1) {
673 struct bt_stmt *bbs = (struct bt_stmt *)bs->bs_var;
674
675 while (bbs != NULL((void *)0)) {
676 if (stmt_eval(bbs, dtev))
677 return 1;
678 bbs = SLIST_NEXT(bbs, bs_next)((bbs)->bs_next.sle_next);
679 }
680
681 continue;
682 }
683
684 if (stmt_eval(bs, dtev))
685 return 1;
686 }
687
688 return 0;
689}
690
691void
692rule_printmaps(struct bt_rule *r)
693{
694 struct bt_stmt *bs;
695
696 SLIST_FOREACH(bs, &r->br_action, bs_next)for((bs) = ((&r->br_action)->slh_first); (bs) != ((
void *)0); (bs) = ((bs)->bs_next.sle_next))
{
697 struct bt_arg *ba;
698
699 SLIST_FOREACH(ba, &bs->bs_args, ba_next)for((ba) = ((&bs->bs_args)->slh_first); (ba) != ((void
*)0); (ba) = ((ba)->ba_next.sle_next))
{
700 struct bt_var *bv = ba->ba_value;
701 struct map *map;
702
703 if (ba->ba_type != B_AT_MAP && ba->ba_type != B_AT_HIST)
704 continue;
705
706 map = (struct map *)bv->bv_value;
707 if (map == NULL((void *)0))
708 continue;
709
710 if (ba->ba_type == B_AT_MAP)
711 map_print(map, SIZE_T_MAX0xffffffffffffffffUL, bv_name(bv));
712 else
713 hist_print((struct hist *)map, bv_name(bv));
714 map_clear(map);
715 bv->bv_value = NULL((void *)0);
716 }
717 }
718}
719
720time_t
721builtin_gettime(struct dt_evt *dtev)
722{
723 struct timespec ts;
724
725 if (dtev == NULL((void *)0)) {
726 clock_gettime(CLOCK_REALTIME0, &ts);
727 return ts.tv_sec;
728 }
729
730 return dtev->dtev_tsp.tv_sec;
731}
732
733static inline uint64_t
734TIMESPEC_TO_NSEC(struct timespec *ts)
735{
736 return (ts->tv_sec * 1000000000L + ts->tv_nsec);
737}
738
739uint64_t
740builtin_nsecs(struct dt_evt *dtev)
741{
742 struct timespec ts;
743
744 if (dtev == NULL((void *)0)) {
745 clock_gettime(CLOCK_REALTIME0, &ts);
746 return TIMESPEC_TO_NSEC(&ts);
747 }
748
749 return TIMESPEC_TO_NSEC(&dtev->dtev_tsp);
750}
751
752const char *
753builtin_stack(struct dt_evt *dtev, int kernel, unsigned long offset)
754{
755 struct stacktrace *st = &dtev->dtev_kstack;
756 static char buf[4096];
757 const char *last = "\nkernel\n";
758 char *bp;
759 size_t i;
760 int sz;
761
762 if (!kernel) {
763 st = &dtev->dtev_ustack;
764 last = "\nuserland\n";
765 } else if (st->st_count == 0) {
766 return "\nuserland\n";
767 }
768
769 buf[0] = '\0';
770 bp = buf;
771 sz = sizeof(buf);
772 for (i = 0; i < st->st_count; i++) {
773 int l;
774
775 if (!kernel)
776 l = kelf_snprintsym(uelf, bp, sz - 1, st->st_pc[i],
777 offset);
778 else
779 l = kelf_snprintsym(kelf, bp, sz - 1, st->st_pc[i],
780 offset);
781 if (l < 0)
782 break;
783 if (l >= sz - 1) {
784 bp += sz - 1;
785 sz = 1;
786 break;
787 }
788 bp += l;
789 sz -= l;
790 }
791 snprintf(bp, sz, "%s", last);
792
793 return buf;
794}
795
796const char *
797builtin_arg(struct dt_evt *dtev, enum bt_argtype dat)
798{
799 static char buf[sizeof("18446744073709551615")]; /* UINT64_MAX */
800 unsigned int argn;
801 struct dtioc_arg_info *dtai;
802 const char *argtype, *fmt;
803 long value;
804
805 dtai = dt_args[dtev->dtev_pbn - 1];
806 argn = dat - B_AT_BI_ARG0;
807 argtype = dtai[argn].dtai_argtype;
808
809 if (strncmp(argtype, "int", DTNAMESIZE16) == 0) {
810 fmt = "%d";
811 value = (int)dtev->dtev_args_args.E_entry[argn];
812 } else {
813 fmt = "%lu";
814 value = dtev->dtev_args_args.E_entry[argn];
815 }
816
817 snprintf(buf, sizeof(buf), fmt, dtev->dtev_args_args.E_entry[argn]);
818
819 return buf;
820}
821
822/*
823 * Returns non-zero if the program should halt.
824 */
825int
826stmt_eval(struct bt_stmt *bs, struct dt_evt *dtev)
827{
828 int halt = 0;
829
830 switch (bs->bs_act) {
831 case B_AC_BUCKETIZE:
832 stmt_bucketize(bs, dtev);
833 break;
834 case B_AC_CLEAR:
835 stmt_clear(bs);
836 break;
837 case B_AC_DELETE:
838 stmt_delete(bs, dtev);
839 break;
840 case B_AC_EXIT:
841 halt = 1;
842 break;
843 case B_AC_INSERT:
844 stmt_insert(bs, dtev);
845 break;
846 case B_AC_PRINT:
847 stmt_print(bs, dtev);
848 break;
849 case B_AC_PRINTF:
850 stmt_printf(bs, dtev);
851 break;
852 case B_AC_STORE:
853 stmt_store(bs, dtev);
854 break;
855 case B_AC_TEST:
856 /* done before */
857 break;
858 case B_AC_TIME:
859 stmt_time(bs, dtev);
860 break;
861 case B_AC_ZERO:
862 stmt_zero(bs);
863 break;
864 default:
865 xabort("no handler for action type %d", bs->bs_act);
866 }
867 return halt;
868}
869
870/*
871 * Increment a bucket: { @h = hist(v); } or { @h = lhist(v, min, max, step); }
872 *
873 * In this case 'h' is represented by `bv' and '(min, max, step)' by `brange'.
874 */
875void
876stmt_bucketize(struct bt_stmt *bs, struct dt_evt *dtev)
877{
878 struct bt_arg *brange, *bhist = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
879 struct bt_arg *bval = (struct bt_arg *)bs->bs_var;
880 struct bt_var *bv = bhist->ba_value;
881 struct hist *hist;
882 const char *bucket;
883 long step = 0;
884
885 assert(bhist->ba_type == B_AT_HIST)((bhist->ba_type == B_AT_HIST) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 885, __func__, "bhist->ba_type == B_AT_HIST"))
;
886 assert(SLIST_NEXT(bval, ba_next) == NULL)((((bval)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 886, __func__, "SLIST_NEXT(bval, ba_next) == NULL"
))
;
887
888 brange = bhist->ba_key;
889 bucket = ba2bucket(bval, brange, dtev, &step);
890 if (bucket == NULL((void *)0)) {
891 debug("hist=%p '%s' value=%lu out of range\n", bv->bv_value,
892 bv_name(bv), ba2long(bval, dtev));
893 return;
894 }
895 debug("hist=%p '%s' increment bucket '%s'\n", bv->bv_value,
896 bv_name(bv), bucket);
897
898 /* hist is NULL before first insert or after clear() */
899 hist = (struct hist *)bv->bv_value;
900 if (hist == NULL((void *)0))
901 hist = hist_new(step);
902
903 hist_increment(hist, bucket);
904
905 debug("hist=%p '%s' increment bucket=%p '%s' bval=%p\n", hist,
906 bv_name(bv), brange, bucket, bval);
907
908 bv->bv_value = (struct bt_arg *)hist;
909 bv->bv_type = B_VT_HIST;
910}
911
912
913/*
914 * Empty a map: { clear(@map); }
915 */
916void
917stmt_clear(struct bt_stmt *bs)
918{
919 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
920 struct bt_var *bv = ba->ba_value;
921 struct map *map;
922
923 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 923, __func__, "bs->bs_var == NULL"))
;
924 assert(ba->ba_type == B_AT_VAR)((ba->ba_type == B_AT_VAR) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 924, __func__, "ba->ba_type == B_AT_VAR"))
;
925
926 map = (struct map *)bv->bv_value;
927 if (map == NULL((void *)0))
928 return;
929
930 if (bv->bv_type != B_VT_MAP && bv->bv_type != B_VT_HIST)
931 errx(1, "invalid variable type for clear(%s)", ba_name(ba));
932
933 map_clear(map);
934 bv->bv_value = NULL((void *)0);
935
936 debug("map=%p '%s' clear\n", map, bv_name(bv));
937}
938
939/*
940 * Map delete: { delete(@map[key]); }
941 *
942 * In this case 'map' is represented by `bv' and 'key' by `bkey'.
943 */
944void
945stmt_delete(struct bt_stmt *bs, struct dt_evt *dtev)
946{
947 struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
948 struct bt_var *bv = bmap->ba_value;
949 struct map *map;
950 const char *hash;
951
952 assert(bmap->ba_type == B_AT_MAP)((bmap->ba_type == B_AT_MAP) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 952, __func__, "bmap->ba_type == B_AT_MAP"))
;
953 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 953, __func__, "bs->bs_var == NULL"))
;
954
955 map = (struct map *)bv->bv_value;
956 if (map == NULL((void *)0))
957 return;
958
959 bkey = bmap->ba_key;
960 hash = ba2hash(bkey, dtev);
961 debug("map=%p '%s' delete key=%p '%s'\n", map, bv_name(bv), bkey, hash);
962
963 map_delete(map, hash);
964}
965
966/*
967 * Map insert: { @map[key] = 42; }
968 *
969 * In this case 'map' is represented by `bv', 'key' by `bkey' and
970 * '42' by `bval'.
971 */
972void
973stmt_insert(struct bt_stmt *bs, struct dt_evt *dtev)
974{
975 struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
976 struct bt_arg *bval = (struct bt_arg *)bs->bs_var;
977 struct bt_var *bv = bmap->ba_value;
978 struct map *map;
979 const char *hash;
980 long val;
981
982 assert(bmap->ba_type == B_AT_MAP)((bmap->ba_type == B_AT_MAP) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 982, __func__, "bmap->ba_type == B_AT_MAP"))
;
983 assert(SLIST_NEXT(bval, ba_next) == NULL)((((bval)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 983, __func__, "SLIST_NEXT(bval, ba_next) == NULL"
))
;
984
985 bkey = bmap->ba_key;
986 hash = ba2hash(bkey, dtev);
987
988 /* map is NULL before first insert or after clear() */
989 map = (struct map *)bv->bv_value;
990 if (map == NULL((void *)0))
991 map = map_new();
992
993 /* Operate on existring value for count(), max(), min() and sum(). */
994 switch (bval->ba_type) {
995 case B_AT_MF_COUNT:
996 val = ba2long(map_get(map, hash), NULL((void *)0));
997 val++;
998 bval = ba_new(val, B_AT_LONG)ba_new0((void *)(val), (B_AT_LONG));
999 break;
1000 case B_AT_MF_MAX:
1001 val = ba2long(map_get(map, hash), NULL((void *)0));
1002 val = MAXIMUM(val, ba2long(bval->ba_value, dtev))(((val) > (ba2long(bval->ba_value, dtev))) ? (val) : (ba2long
(bval->ba_value, dtev)))
;
1003 bval = ba_new(val, B_AT_LONG)ba_new0((void *)(val), (B_AT_LONG));
1004 break;
1005 case B_AT_MF_MIN:
1006 val = ba2long(map_get(map, hash), NULL((void *)0));
1007 val = MINIMUM(val, ba2long(bval->ba_value, dtev))(((val) < (ba2long(bval->ba_value, dtev))) ? (val) : (ba2long
(bval->ba_value, dtev)))
;
1008 bval = ba_new(val, B_AT_LONG)ba_new0((void *)(val), (B_AT_LONG));
1009 break;
1010 case B_AT_MF_SUM:
1011 val = ba2long(map_get(map, hash), NULL((void *)0));
1012 val += ba2long(bval->ba_value, dtev);
1013 bval = ba_new(val, B_AT_LONG)ba_new0((void *)(val), (B_AT_LONG));
1014 break;
1015 default:
1016 bval = baeval(bval, dtev);
1017 break;
1018 }
1019
1020 map_insert(map, hash, bval);
1021
1022 debug("map=%p '%s' insert key=%p '%s' bval=%p\n", map,
1023 bv_name(bv), bkey, hash, bval);
1024
1025 bv->bv_value = (struct bt_arg *)map;
1026 bv->bv_type = B_VT_MAP;
1027}
1028
1029/*
1030 * Print variables: { print(890); print(@map[, 8]); print(comm); }
1031 *
1032 * In this case the global variable 'map' is pointed at by `ba'
1033 * and '8' is represented by `btop'.
1034 */
1035void
1036stmt_print(struct bt_stmt *bs, struct dt_evt *dtev)
1037{
1038 struct bt_arg *btop, *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
1039 struct bt_var *bv = ba->ba_value;
1040 struct map *map;
1041 size_t top = SIZE_T_MAX0xffffffffffffffffUL;
1042
1043 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1043, __func__, "bs->bs_var == NULL"))
;
1044
1045 /* Parse optional `top' argument. */
1046 btop = SLIST_NEXT(ba, ba_next)((ba)->ba_next.sle_next);
1047 if (btop != NULL((void *)0)) {
1048 assert(SLIST_NEXT(btop, ba_next) == NULL)((((btop)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 1048, __func__, "SLIST_NEXT(btop, ba_next) == NULL"
))
;
1049 top = ba2long(btop, dtev);
1050 }
1051
1052 /* Static argument. */
1053 if (ba->ba_type != B_AT_VAR) {
1054 assert(btop == NULL)((btop == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1054, __func__, "btop == NULL"))
;
1055 printf("%s\n", ba2str(ba, dtev));
1056 return;
1057 }
1058
1059 map = (struct map *)bv->bv_value;
1060 if (map == NULL((void *)0))
1061 return;
1062
1063 debug("map=%p '%s' print (top=%d)\n", bv->bv_value, bv_name(bv), top);
1064
1065 if (bv->bv_type == B_VT_MAP)
1066 map_print(map, top, bv_name(bv));
1067 else if (bv->bv_type == B_VT_HIST)
1068 hist_print((struct hist *)map, bv_name(bv));
1069 else
1070 printf("%s\n", ba2str(ba, dtev));
1071}
1072
1073/*
1074 * Variable store: { @var = 3; }
1075 *
1076 * In this case '3' is represented by `ba', the argument of a STORE
1077 * action.
1078 *
1079 * If the argument depends of the value of an event (builtin) or is
1080 * the result of an operation, its evaluation is stored in a new `ba'.
1081 */
1082void
1083stmt_store(struct bt_stmt *bs, struct dt_evt *dtev)
1084{
1085 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
1086 struct bt_var *bvar, *bv = bs->bs_var;
1087
1088 assert(SLIST_NEXT(ba, ba_next) == NULL)((((ba)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 1088, __func__, "SLIST_NEXT(ba, ba_next) == NULL"
))
;
1
Assuming field 'sle_next' is equal to null
2
'?' condition is true
1089
1090 switch (ba->ba_type) {
3
Control jumps to 'case B_AT_TUPLE:' at line 1104
1091 case B_AT_STR:
1092 bv->bv_value = ba;
1093 bv->bv_type = B_VT_STR;
1094 break;
1095 case B_AT_LONG:
1096 bv->bv_value = ba;
1097 bv->bv_type = B_VT_LONG;
1098 break;
1099 case B_AT_VAR:
1100 bvar = ba->ba_value;
1101 bv->bv_type = bvar->bv_type;
1102 bv->bv_value = bvar->bv_value;
1103 break;
1104 case B_AT_TUPLE:
1105 bv->bv_value = baeval(ba, dtev);
4
Calling 'baeval'
1106 bv->bv_type = B_VT_TUPLE;
1107 break;
1108 case B_AT_BI_PID:
1109 case B_AT_BI_TID:
1110 case B_AT_BI_NSECS:
1111 case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
1112 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1113 bv->bv_value = baeval(ba, dtev);
1114 bv->bv_type = B_VT_LONG;
1115 break;
1116 case B_AT_FN_STR:
1117 bv->bv_value = baeval(ba, dtev);
1118 bv->bv_type = B_VT_STR;
1119 break;
1120 default:
1121 xabort("store not implemented for type %d", ba->ba_type);
1122 }
1123
1124 debug("bv=%p var '%s' store (%p)='%s'\n", bv, bv_name(bv), bv->bv_value,
1125 ba2str(bv->bv_value, dtev));
1126}
1127
1128/*
1129 * String conversion { str($1); string($1, 3); }
1130 *
1131 * Since fn_str is currently only called in ba2str, *buf should be a pointer
1132 * to the static buffer provided by ba2str.
1133 */
1134struct bt_arg *
1135fn_str(struct bt_arg *ba, struct dt_evt *dtev, char *buf)
1136{
1137 struct bt_arg *arg, *index;
1138 ssize_t len = STRLEN64;
1139
1140 assert(ba->ba_type == B_AT_FN_STR)((ba->ba_type == B_AT_FN_STR) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1140, __func__, "ba->ba_type == B_AT_FN_STR"))
;
1141
1142 arg = (struct bt_arg*)ba->ba_value;
1143 assert(arg != NULL)((arg != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1143, __func__, "arg != NULL"))
;
1144
1145 index = SLIST_NEXT(arg, ba_next)((arg)->ba_next.sle_next);
1146 if (index != NULL((void *)0)) {
1147 /* Should have only 1 optional argument. */
1148 assert(SLIST_NEXT(index, ba_next) == NULL)((((index)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 1148, __func__, "SLIST_NEXT(index, ba_next) == NULL"
))
;
1149 len = MINIMUM(ba2long(index, dtev) + 1, STRLEN)(((ba2long(index, dtev) + 1) < (64)) ? (ba2long(index, dtev
) + 1) : (64))
;
1150 }
1151
1152 /* All negative lengths behave the same as a zero length. */
1153 if (len < 1)
1154 return ba_new("", B_AT_STR)ba_new0((void *)(""), (B_AT_STR));
1155
1156 strlcpy(buf, ba2str(arg, dtev), len);
1157 return ba_new(buf, B_AT_STR)ba_new0((void *)(buf), (B_AT_STR));
1158}
1159
1160/*
1161 * Expression test: { if (expr) stmt; }
1162 */
1163bool_Bool
1164stmt_test(struct bt_stmt *bs, struct dt_evt *dtev)
1165{
1166 struct bt_arg *ba;
1167
1168 if (bs == NULL((void *)0))
1169 return true1;
1170
1171 ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
1172
1173 return baexpr2long(ba, dtev) != 0;
1174}
1175
1176/*
1177 * Print time: { time("%H:%M:%S"); }
1178 */
1179void
1180stmt_time(struct bt_stmt *bs, struct dt_evt *dtev)
1181{
1182 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
1183 time_t time;
1184 struct tm *tm;
1185 char buf[64];
1186
1187 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1187, __func__, "bs->bs_var == NULL"))
;
1188 assert(ba->ba_type == B_AT_STR)((ba->ba_type == B_AT_STR) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1188, __func__, "ba->ba_type == B_AT_STR"))
;
1189 assert(strlen(ba2str(ba, dtev)) < (sizeof(buf) - 1))((strlen(ba2str(ba, dtev)) < (sizeof(buf) - 1)) ? (void)0 :
__assert2("/usr/src/usr.sbin/btrace/btrace.c", 1189, __func__
, "strlen(ba2str(ba, dtev)) < (sizeof(buf) - 1)"))
;
1190
1191 time = builtin_gettime(dtev);
1192 tm = localtime(&time);
1193 strftime(buf, sizeof(buf), ba2str(ba, dtev), tm);
1194 printf("%s", buf);
1195}
1196
1197/*
1198 * Set entries to 0: { zero(@map); }
1199 */
1200void
1201stmt_zero(struct bt_stmt *bs)
1202{
1203 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
1204 struct bt_var *bv = ba->ba_value;
1205 struct map *map;
1206
1207 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1207, __func__, "bs->bs_var == NULL"))
;
1208 assert(ba->ba_type == B_AT_VAR)((ba->ba_type == B_AT_VAR) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1208, __func__, "ba->ba_type == B_AT_VAR"))
;
1209
1210 map = (struct map *)bv->bv_value;
1211 if (map == NULL((void *)0))
1212 return;
1213
1214 if (bv->bv_type != B_VT_MAP && bv->bv_type != B_VT_HIST)
1215 errx(1, "invalid variable type for zero(%s)", ba_name(ba));
1216
1217 map_zero(map);
1218
1219 debug("map=%p '%s' zero\n", map, bv_name(bv));
1220}
1221
1222struct bt_arg *
1223ba_read(struct bt_arg *ba)
1224{
1225 struct bt_var *bv = ba->ba_value;
1226
1227 assert(ba->ba_type == B_AT_VAR)((ba->ba_type == B_AT_VAR) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1227, __func__, "ba->ba_type == B_AT_VAR"))
;
1228 debug("bv=%p read '%s' (%p)\n", bv, bv_name(bv), bv->bv_value);
1229
1230 /* Handle map/hist access after clear(). */
1231 if (bv->bv_value == NULL((void *)0))
1232 return &g_nullba;
1233
1234 return bv->bv_value;
1235}
1236
1237// XXX
1238extern struct bt_arg *ba_append(struct bt_arg *, struct bt_arg *);
1239
1240/*
1241 * Return a new argument that doesn't depend on `dtev'. This is used
1242 * when storing values in variables, maps, etc.
1243 */
1244struct bt_arg *
1245baeval(struct bt_arg *bval, struct dt_evt *dtev)
1246{
1247 struct bt_arg *ba, *bh = NULL((void *)0);
1248
1249 switch (bval->ba_type) {
5
Control jumps to 'case B_AT_TUPLE:' at line 1271
7
Control jumps to 'case B_AT_OP_PLUS:' at line 1260
1250 case B_AT_VAR:
1251 ba = baeval(ba_read(bval), NULL((void *)0));
1252 break;
1253 case B_AT_LONG:
1254 case B_AT_BI_PID:
1255 case B_AT_BI_TID:
1256 case B_AT_BI_CPU:
1257 case B_AT_BI_NSECS:
1258 case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
1259 case B_AT_BI_RETVAL:
1260 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1261 ba = ba_new(ba2long(bval, dtev), B_AT_LONG)ba_new0((void *)(ba2long(bval, dtev)), (B_AT_LONG));
8
Calling 'ba2long'
1262 break;
1263 case B_AT_STR:
1264 case B_AT_BI_COMM:
1265 case B_AT_BI_KSTACK:
1266 case B_AT_BI_USTACK:
1267 case B_AT_BI_PROBE:
1268 case B_AT_FN_STR:
1269 ba = ba_new(ba2str(bval, dtev), B_AT_STR)ba_new0((void *)(ba2str(bval, dtev)), (B_AT_STR));
1270 break;
1271 case B_AT_TUPLE:
1272 ba = bval->ba_value;
1273 do {
1274 bh = ba_append(bh, baeval(ba, dtev));
6
Calling 'baeval'
1275 } while ((ba = SLIST_NEXT(ba, ba_next)((ba)->ba_next.sle_next)) != NULL((void *)0));
1276 ba = ba_new(bh, B_AT_TUPLE)ba_new0((void *)(bh), (B_AT_TUPLE));
1277 break;
1278 default:
1279 xabort("no eval support for type %d", bval->ba_type);
1280 }
1281
1282 return ba;
1283}
1284
1285/*
1286 * Return a string of coma-separated values
1287 */
1288const char *
1289ba2hash(struct bt_arg *ba, struct dt_evt *dtev)
1290{
1291 static char buf[KLEN1024];
1292 char *hash;
1293 int l, len;
1294
1295 buf[0] = '\0';
1296 l = snprintf(buf, sizeof(buf), "%s", ba2str(ba, dtev));
1297 if (l < 0 || (size_t)l > sizeof(buf)) {
1298 warn("string too long %d > %lu", l, sizeof(buf));
1299 return buf;
1300 }
1301
1302 len = 0;
1303 while ((ba = SLIST_NEXT(ba, ba_next)((ba)->ba_next.sle_next)) != NULL((void *)0)) {
1304 len += l;
1305 hash = buf + len;
1306
1307 l = snprintf(hash, sizeof(buf) - len, ", %s", ba2str(ba, dtev));
1308 if (l < 0 || (size_t)l > (sizeof(buf) - len)) {
1309 warn("hash too long %d > %lu", l + len, sizeof(buf));
1310 break;
1311 }
1312 }
1313
1314 return buf;
1315}
1316
1317static unsigned long
1318next_pow2(unsigned long x)
1319{
1320 size_t i;
1321
1322 x--;
1323 for (i = 0; i < (sizeof(x) * 8) - 1; i++)
1324 x |= (x >> 1);
1325
1326 return x + 1;
1327}
1328
1329/*
1330 * Return the ceiling value the interval holding `ba' or NULL if it is
1331 * out of the (min, max) values.
1332 */
1333const char *
1334ba2bucket(struct bt_arg *ba, struct bt_arg *brange, struct dt_evt *dtev,
1335 long *pstep)
1336{
1337 static char buf[KLEN1024];
1338 long val, bucket;
1339 int l;
1340
1341 val = ba2long(ba, dtev);
1342 if (brange == NULL((void *)0))
1343 bucket = next_pow2(val);
1344 else {
1345 long min, max, step;
1346
1347 assert(brange->ba_type == B_AT_LONG)((brange->ba_type == B_AT_LONG) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1347, __func__, "brange->ba_type == B_AT_LONG"))
;
1348 min = ba2long(brange, NULL((void *)0));
1349
1350 brange = SLIST_NEXT(brange, ba_next)((brange)->ba_next.sle_next);
1351 assert(brange->ba_type == B_AT_LONG)((brange->ba_type == B_AT_LONG) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1351, __func__, "brange->ba_type == B_AT_LONG"))
;
1352 max = ba2long(brange, NULL((void *)0));
1353
1354 if ((val < min) || (val > max))
1355 return NULL((void *)0);
1356
1357 brange = SLIST_NEXT(brange, ba_next)((brange)->ba_next.sle_next);
1358 assert(brange->ba_type == B_AT_LONG)((brange->ba_type == B_AT_LONG) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1358, __func__, "brange->ba_type == B_AT_LONG"))
;
1359 step = ba2long(brange, NULL((void *)0));
1360
1361 bucket = ((val / step) + 1) * step;
1362 *pstep = step;
1363 }
1364
1365 buf[0] = '\0';
1366 l = snprintf(buf, sizeof(buf), "%lu", bucket);
1367 if (l < 0 || (size_t)l > sizeof(buf)) {
1368 warn("string too long %d > %lu", l, sizeof(buf));
1369 return buf;
1370 }
1371
1372 return buf;
1373}
1374
1375/*
1376 * Evaluate the operation encoded in `ba' and return its result.
1377 */
1378long
1379baexpr2long(struct bt_arg *ba, struct dt_evt *dtev)
1380{
1381 static long recursions;
1382 struct bt_arg *lhs, *rhs;
1383 long lval, rval, result;
1384
1385 if (++recursions >= __MAXOPERANDS5)
11
Taking false branch
1386 errx(1, "too many operands (>%d) in expression", __MAXOPERANDS5);
1387
1388 lhs = ba->ba_value;
1389 rhs = SLIST_NEXT(lhs, ba_next)((lhs)->ba_next.sle_next);
1390
1391 /*
1392 * String comparison also use '==' and '!='.
1393 */
1394 if (lhs->ba_type == B_AT_STR ||
12
Assuming field 'ba_type' is not equal to B_AT_STR
1395 (rhs != NULL((void *)0) && rhs->ba_type == B_AT_STR)) {
13
Assuming 'rhs' is equal to NULL
1396 char lstr[STRLEN64], rstr[STRLEN64];
1397
1398 strlcpy(lstr, ba2str(lhs, dtev), sizeof(lstr));
1399 strlcpy(rstr, ba2str(rhs, dtev), sizeof(rstr));
1400
1401 result = strncmp(lstr, rstr, STRLEN64) == 0;
1402
1403 switch (ba->ba_type) {
1404 case B_AT_OP_EQ:
1405 break;
1406 case B_AT_OP_NE:
1407 result = !result;
1408 break;
1409 default:
1410 warnx("operation '%d' unsupported on strings",
1411 ba->ba_type);
1412 result = 1;
1413 }
1414
1415 debug("ba=%p eval '(%s %s %s) = %d'\n", ba, lstr, ba_name(ba),
1416 rstr, result);
1417
1418 goto out;
1419 }
1420
1421 lval = ba2long(lhs, dtev);
1422 if (rhs
13.1
'rhs' is equal to NULL
== NULL((void *)0)) {
14
Taking true branch
1423 rval = 0;
15
The value 0 is assigned to 'rval'
1424 } else {
1425 assert(SLIST_NEXT(rhs, ba_next) == NULL)((((rhs)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 1425, __func__, "SLIST_NEXT(rhs, ba_next) == NULL"
))
;
1426 rval = ba2long(rhs, dtev);
1427 }
1428
1429 switch (ba->ba_type) {
16
Control jumps to 'case B_AT_OP_MODULO:' at line 1442
1430 case B_AT_OP_PLUS:
1431 result = lval + rval;
1432 break;
1433 case B_AT_OP_MINUS:
1434 result = lval - rval;
1435 break;
1436 case B_AT_OP_MULT:
1437 result = lval * rval;
1438 break;
1439 case B_AT_OP_DIVIDE:
1440 result = lval / rval;
1441 break;
1442 case B_AT_OP_MODULO:
1443 result = lval % rval;
17
Division by zero
1444 break;
1445 case B_AT_OP_BAND:
1446 result = lval & rval;
1447 break;
1448 case B_AT_OP_XOR:
1449 result = lval ^ rval;
1450 break;
1451 case B_AT_OP_BOR:
1452 result = lval | rval;
1453 break;
1454 case B_AT_OP_EQ:
1455 result = (lval == rval);
1456 break;
1457 case B_AT_OP_NE:
1458 result = (lval != rval);
1459 break;
1460 case B_AT_OP_LE:
1461 result = (lval <= rval);
1462 break;
1463 case B_AT_OP_LT:
1464 result = (lval < rval);
1465 break;
1466 case B_AT_OP_GE:
1467 result = (lval >= rval);
1468 break;
1469 case B_AT_OP_GT:
1470 result = (lval > rval);
1471 break;
1472 case B_AT_OP_LAND:
1473 result = (lval && rval);
1474 break;
1475 case B_AT_OP_LOR:
1476 result = (lval || rval);
1477 break;
1478 default:
1479 xabort("unsupported operation %d", ba->ba_type);
1480 }
1481
1482 debug("ba=%p eval '(%ld %s %ld) = %d'\n", ba, lval, ba_name(ba),
1483 rval, result);
1484
1485out:
1486 --recursions;
1487
1488 return result;
1489}
1490
1491const char *
1492ba_name(struct bt_arg *ba)
1493{
1494 switch (ba->ba_type) {
1495 case B_AT_STR:
1496 return (const char *)ba->ba_value;
1497 case B_AT_LONG:
1498 return ba2str(ba, NULL((void *)0));
1499 case B_AT_NIL:
1500 return "0";
1501 case B_AT_VAR:
1502 case B_AT_MAP:
1503 case B_AT_HIST:
1504 break;
1505 case B_AT_BI_PID:
1506 return "pid";
1507 case B_AT_BI_TID:
1508 return "tid";
1509 case B_AT_BI_COMM:
1510 return "comm";
1511 case B_AT_BI_CPU:
1512 return "cpu";
1513 case B_AT_BI_NSECS:
1514 return "nsecs";
1515 case B_AT_BI_KSTACK:
1516 return "kstack";
1517 case B_AT_BI_USTACK:
1518 return "ustack";
1519 case B_AT_BI_ARG0:
1520 return "arg0";
1521 case B_AT_BI_ARG1:
1522 return "arg1";
1523 case B_AT_BI_ARG2:
1524 return "arg2";
1525 case B_AT_BI_ARG3:
1526 return "arg3";
1527 case B_AT_BI_ARG4:
1528 return "arg4";
1529 case B_AT_BI_ARG5:
1530 return "arg5";
1531 case B_AT_BI_ARG6:
1532 return "arg6";
1533 case B_AT_BI_ARG7:
1534 return "arg7";
1535 case B_AT_BI_ARG8:
1536 return "arg8";
1537 case B_AT_BI_ARG9:
1538 return "arg9";
1539 case B_AT_BI_ARGS:
1540 return "args";
1541 case B_AT_BI_RETVAL:
1542 return "retval";
1543 case B_AT_BI_PROBE:
1544 return "probe";
1545 case B_AT_FN_STR:
1546 return "str";
1547 case B_AT_OP_PLUS:
1548 return "+";
1549 case B_AT_OP_MINUS:
1550 return "-";
1551 case B_AT_OP_MULT:
1552 return "*";
1553 case B_AT_OP_DIVIDE:
1554 return "/";
1555 case B_AT_OP_MODULO:
1556 return "%";
1557 case B_AT_OP_BAND:
1558 return "&";
1559 case B_AT_OP_XOR:
1560 return "^";
1561 case B_AT_OP_BOR:
1562 return "|";
1563 case B_AT_OP_EQ:
1564 return "==";
1565 case B_AT_OP_NE:
1566 return "!=";
1567 case B_AT_OP_LE:
1568 return "<=";
1569 case B_AT_OP_LT:
1570 return "<";
1571 case B_AT_OP_GE:
1572 return ">=";
1573 case B_AT_OP_GT:
1574 return ">";
1575 case B_AT_OP_LAND:
1576 return "&&";
1577 case B_AT_OP_LOR:
1578 return "||";
1579 default:
1580 xabort("unsupported type %d", ba->ba_type);
1581 }
1582
1583 assert(ba->ba_type == B_AT_VAR || ba->ba_type == B_AT_MAP ||((ba->ba_type == B_AT_VAR || ba->ba_type == B_AT_MAP ||
ba->ba_type == B_AT_HIST) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1584, __func__, "ba->ba_type == B_AT_VAR || ba->ba_type == B_AT_MAP || ba->ba_type == B_AT_HIST"
))
1584 ba->ba_type == B_AT_HIST)((ba->ba_type == B_AT_VAR || ba->ba_type == B_AT_MAP ||
ba->ba_type == B_AT_HIST) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1584, __func__, "ba->ba_type == B_AT_VAR || ba->ba_type == B_AT_MAP || ba->ba_type == B_AT_HIST"
))
;
1585
1586 static char buf[64];
1587 size_t sz;
1588 int l;
1589
1590 buf[0] = '@';
1591 buf[1] = '\0';
1592 sz = sizeof(buf) - 1;
1593 l = snprintf(buf+1, sz, "%s", bv_name(ba->ba_value));
1594 if (l < 0 || (size_t)l > sz) {
1595 warn("string too long %d > %zu", l, sz);
1596 return buf;
1597 }
1598
1599 if (ba->ba_type == B_AT_MAP) {
1600 sz -= l;
1601 l = snprintf(buf+1+l, sz, "[%s]", ba_name(ba->ba_key));
1602 if (l < 0 || (size_t)l > sz) {
1603 warn("string too long %d > %zu", l, sz);
1604 return buf;
1605 }
1606 }
1607
1608 return buf;
1609}
1610
1611/*
1612 * Return the representation of `ba' as long.
1613 */
1614long
1615ba2long(struct bt_arg *ba, struct dt_evt *dtev)
1616{
1617 struct bt_var *bv;
1618 long val;
1619
1620 switch (ba->ba_type) {
9
Control jumps to 'case B_AT_OP_PLUS:' at line 1660
1621 case B_AT_LONG:
1622 val = (long)ba->ba_value;
1623 break;
1624 case B_AT_VAR:
1625 ba = ba_read(ba);
1626 val = (long)ba->ba_value;
1627 break;
1628 case B_AT_MAP:
1629 bv = ba->ba_value;
1630 /* Uninitialized map */
1631 if (bv->bv_value == NULL((void *)0))
1632 return 0;
1633 val = ba2long(map_get((struct map *)bv->bv_value,
1634 ba2str(ba->ba_key, dtev)), dtev);
1635 break;
1636 case B_AT_NIL:
1637 val = 0L;
1638 break;
1639 case B_AT_BI_PID:
1640 val = dtev->dtev_pid;
1641 break;
1642 case B_AT_BI_TID:
1643 val = dtev->dtev_tid;
1644 break;
1645 case B_AT_BI_CPU:
1646 val = dtev->dtev_cpu;
1647 break;
1648 case B_AT_BI_NSECS:
1649 val = builtin_nsecs(dtev);
1650 break;
1651 case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
1652 val = dtev->dtev_args_args.E_entry[ba->ba_type - B_AT_BI_ARG0];
1653 break;
1654 case B_AT_BI_RETVAL:
1655 val = dtev->dtev_retval_args.E_return.__retval[0];
1656 break;
1657 case B_AT_BI_PROBE:
1658 val = dtev->dtev_pbn;
1659 break;
1660 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1661 val = baexpr2long(ba, dtev);
10
Calling 'baexpr2long'
1662 break;
1663 default:
1664 xabort("no long conversion for type %d", ba->ba_type);
1665 }
1666
1667 return val;
1668}
1669
1670/*
1671 * Return the representation of `ba' as string.
1672 */
1673const char *
1674ba2str(struct bt_arg *ba, struct dt_evt *dtev)
1675{
1676 static char buf[STRLEN64];
1677 struct bt_var *bv;
1678 struct dtioc_probe_info *dtpi;
1679 unsigned long idx;
1680 const char *str;
1681
1682 buf[0] = '\0';
1683 switch (ba->ba_type) {
1684 case B_AT_STR:
1685 str = (const char *)ba->ba_value;
1686 break;
1687 case B_AT_LONG:
1688 snprintf(buf, sizeof(buf), "%ld",(long)ba->ba_value);
1689 str = buf;
1690 break;
1691 case B_AT_TUPLE:
1692 snprintf(buf, sizeof(buf), "(%s)", ba2hash(ba->ba_value, dtev));
1693 str = buf;
1694 break;
1695 case B_AT_TMEMBER:
1696 idx = (unsigned long)ba->ba_key;
1697 bv = ba->ba_value;
1698 /* Uninitialized tuple */
1699 if (bv->bv_value == NULL((void *)0)) {
1700 str = buf;
1701 break;
1702 }
1703 ba = bv->bv_value;
1704 assert(ba->ba_type == B_AT_TUPLE)((ba->ba_type == B_AT_TUPLE) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1704, __func__, "ba->ba_type == B_AT_TUPLE"))
;
1705 ba = ba->ba_value;
1706 while (ba != NULL((void *)0) && idx-- > 0) {
1707 ba = SLIST_NEXT(ba, ba_next)((ba)->ba_next.sle_next);
1708 }
1709 str = ba2str(ba, dtev);
1710 break;
1711 case B_AT_NIL:
1712 str = "";
1713 break;
1714 case B_AT_BI_KSTACK:
1715 str = builtin_stack(dtev, 1, 0);
1716 break;
1717 case B_AT_BI_USTACK:
1718 str = builtin_stack(dtev, 0, dt_get_offset(dtev->dtev_pid));
1719 break;
1720 case B_AT_BI_COMM:
1721 str = dtev->dtev_comm;
1722 break;
1723 case B_AT_BI_CPU:
1724 snprintf(buf, sizeof(buf), "%u", dtev->dtev_cpu);
1725 str = buf;
1726 break;
1727 case B_AT_BI_PID:
1728 snprintf(buf, sizeof(buf), "%d", dtev->dtev_pid);
1729 str = buf;
1730 break;
1731 case B_AT_BI_TID:
1732 snprintf(buf, sizeof(buf), "%d", dtev->dtev_tid);
1733 str = buf;
1734 break;
1735 case B_AT_BI_NSECS:
1736 snprintf(buf, sizeof(buf), "%llu", builtin_nsecs(dtev));
1737 str = buf;
1738 break;
1739 case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
1740 str = builtin_arg(dtev, ba->ba_type);
1741 break;
1742 case B_AT_BI_RETVAL:
1743 snprintf(buf, sizeof(buf), "%ld", (long)dtev->dtev_retval_args.E_return.__retval[0]);
1744 str = buf;
1745 break;
1746 case B_AT_BI_PROBE:
1747 if (dtev->dtev_pbn == EVENT_BEGIN0) {
1748 str = "BEGIN";
1749 break;
1750 } else if (dtev->dtev_pbn == EVENT_END(unsigned int)(-1)) {
1751 str = "END";
1752 break;
1753 }
1754 dtpi = &dt_dtpis[dtev->dtev_pbn - 1];
1755 if (dtpi != NULL((void *)0))
1756 snprintf(buf, sizeof(buf), "%s:%s:%s",
1757 dtpi->dtpi_prov, dtpi_func(dtpi), dtpi->dtpi_name);
1758 else
1759 snprintf(buf, sizeof(buf), "%u", dtev->dtev_pbn);
1760 str = buf;
1761 break;
1762 case B_AT_MAP:
1763 bv = ba->ba_value;
1764 /* Uninitialized map */
1765 if (bv->bv_value == NULL((void *)0)) {
1766 str = buf;
1767 break;
1768 }
1769 str = ba2str(map_get((struct map *)bv->bv_value,
1770 ba2str(ba->ba_key, dtev)), dtev);
1771 break;
1772 case B_AT_VAR:
1773 str = ba2str(ba_read(ba), dtev);
1774 break;
1775 case B_AT_FN_STR:
1776 str = (const char*)(fn_str(ba, dtev, buf))->ba_value;
1777 break;
1778 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1779 snprintf(buf, sizeof(buf), "%ld", ba2long(ba, dtev));
1780 str = buf;
1781 break;
1782 case B_AT_MF_COUNT:
1783 case B_AT_MF_MAX:
1784 case B_AT_MF_MIN:
1785 case B_AT_MF_SUM:
1786 assert(0)((0) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1786, __func__, "0"))
;
1787 break;
1788 default:
1789 xabort("no string conversion for type %d", ba->ba_type);
1790 }
1791
1792 return str;
1793}
1794
1795/*
1796 * Return dt(4) flags indicating which data should be recorded by the
1797 * kernel, if any, for a given `ba'.
1798 */
1799int
1800ba2dtflags(struct bt_arg *ba)
1801{
1802 static long recursions;
1803 struct bt_arg *bval;
1804 int flags = 0;
1805
1806 if (++recursions >= __MAXOPERANDS5)
1807 errx(1, "too many operands (>%d) in expression", __MAXOPERANDS5);
1808
1809 do {
1810 if (ba->ba_type == B_AT_MAP)
1811 bval = ba->ba_key;
1812 else
1813 bval = ba;
1814
1815 switch (bval->ba_type) {
1816 case B_AT_STR:
1817 case B_AT_LONG:
1818 case B_AT_TUPLE:
1819 case B_AT_TMEMBER:
1820 case B_AT_VAR:
1821 case B_AT_HIST:
1822 case B_AT_NIL:
1823 break;
1824 case B_AT_BI_KSTACK:
1825 flags |= DTEVT_KSTACK(1 << 2);
1826 break;
1827 case B_AT_BI_USTACK:
1828 flags |= DTEVT_USTACK(1 << 1);
1829 break;
1830 case B_AT_BI_COMM:
1831 flags |= DTEVT_EXECNAME(1 << 0);
1832 break;
1833 case B_AT_BI_CPU:
1834 case B_AT_BI_PID:
1835 case B_AT_BI_TID:
1836 case B_AT_BI_NSECS:
1837 break;
1838 case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
1839 flags |= DTEVT_FUNCARGS(1 << 3);
1840 break;
1841 case B_AT_BI_RETVAL:
1842 case B_AT_BI_PROBE:
1843 break;
1844 case B_AT_MF_COUNT:
1845 case B_AT_MF_MAX:
1846 case B_AT_MF_MIN:
1847 case B_AT_MF_SUM:
1848 case B_AT_FN_STR:
1849 break;
1850 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1851 flags |= ba2dtflags(bval->ba_value);
1852 break;
1853 default:
1854 xabort("invalid argument type %d", bval->ba_type);
1855 }
1856 } while ((ba = SLIST_NEXT(ba, ba_next)((ba)->ba_next.sle_next)) != NULL((void *)0));
1857
1858 --recursions;
1859
1860 return flags;
1861}
1862
1863long
1864bacmp(struct bt_arg *a, struct bt_arg *b)
1865{
1866 long val;
1867
1868 if (a->ba_type != b->ba_type)
1869 return a->ba_type - b->ba_type;
1870
1871 switch (a->ba_type) {
1872 case B_AT_LONG:
1873 return ba2long(a, NULL((void *)0)) - ba2long(b, NULL((void *)0));
1874 case B_AT_STR:
1875 return strcmp(ba2str(a, NULL((void *)0)), ba2str(b, NULL((void *)0)));
1876 case B_AT_TUPLE:
1877 /* Compare two lists of arguments one by one. */
1878 do {
1879 val = bacmp(a, b);
1880 if (val != 0)
1881 break;
1882
1883 a = SLIST_NEXT(a, ba_next)((a)->ba_next.sle_next);
1884 b = SLIST_NEXT(b, ba_next)((b)->ba_next.sle_next);
1885 if (a == NULL((void *)0) && b != NULL((void *)0))
1886 val = -1;
1887 else if (a != NULL((void *)0) && b == NULL((void *)0))
1888 val = 1;
1889 } while (a != NULL((void *)0) && b != NULL((void *)0));
1890
1891 return val;
1892 default:
1893 xabort("no compare support for type %d", a->ba_type);
1894 }
1895}
1896
1897__dead__attribute__((__noreturn__)) void
1898xabort(const char *fmt, ...)
1899{
1900 va_list ap;
1901
1902 va_start(ap, fmt)__builtin_va_start((ap), fmt);
1903 vfprintf(stderr(&__sF[2]), fmt, ap);
1904 va_end(ap)__builtin_va_end((ap));
1905
1906 fprintf(stderr(&__sF[2]), "\n");
1907 abort();
1908}
1909
1910void
1911debug(const char *fmt, ...)
1912{
1913 va_list ap;
1914
1915 if (verbose < 2)
1916 return;
1917
1918 fprintf(stderr(&__sF[2]), "debug: ");
1919
1920 va_start(ap, fmt)__builtin_va_start((ap), fmt);
1921 vfprintf(stderr(&__sF[2]), fmt, ap);
1922 va_end(ap)__builtin_va_end((ap));
1923}
1924
1925void
1926debugx(const char *fmt, ...)
1927{
1928 va_list ap;
1929
1930 if (verbose < 2)
1931 return;
1932
1933 va_start(ap, fmt)__builtin_va_start((ap), fmt);
1934 vfprintf(stderr(&__sF[2]), fmt, ap);
1935 va_end(ap)__builtin_va_end((ap));
1936}
1937
1938void
1939debug_dump_term(struct bt_arg *ba)
1940{
1941 switch (ba->ba_type) {
1942 case B_AT_LONG:
1943 debugx("%s", ba2str(ba, NULL((void *)0)));
1944 break;
1945 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1946 debug_dump_expr(ba);
1947 break;
1948 default:
1949 debugx("%s", ba_name(ba));
1950 }
1951}
1952
1953void
1954debug_dump_expr(struct bt_arg *ba)
1955{
1956 struct bt_arg *lhs, *rhs;
1957
1958 lhs = ba->ba_value;
1959 rhs = SLIST_NEXT(lhs, ba_next)((lhs)->ba_next.sle_next);
1960
1961 /* Left */
1962 debug_dump_term(lhs);
1963
1964 /* Right */
1965 if (rhs != NULL((void *)0)) {
1966 debugx(" %s ", ba_name(ba));
1967 debug_dump_term(rhs);
1968 } else {
1969 if (ba->ba_type != B_AT_OP_NE)
1970 debugx(" %s NULL", ba_name(ba));
1971 }
1972}
1973
1974void
1975debug_dump_filter(struct bt_rule *r)
1976{
1977 struct bt_stmt *bs;
1978
1979 if (verbose < 2)
1980 return;
1981
1982 if (r->br_filter == NULL((void *)0)) {
1983 debugx("\n");
1984 return;
1985 }
1986
1987 bs = r->br_filter->bf_condition;
1988
1989 debugx(" /");
1990 debug_dump_expr(SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first));
1991 debugx("/\n");
1992}
1993
1994const char *
1995debug_probe_name(struct bt_probe *bp)
1996{
1997 static char buf[64];
1998
1999 if (verbose < 2)
2000 return "";
2001
2002 if (bp->bp_type == B_PT_BEGIN)
2003 return "BEGIN";
2004
2005 if (bp->bp_type == B_PT_END)
2006 return "END";
2007
2008 assert(bp->bp_type == B_PT_PROBE)((bp->bp_type == B_PT_PROBE) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 2008, __func__, "bp->bp_type == B_PT_PROBE"))
;
2009
2010 if (bp->bp_rate) {
2011 snprintf(buf, sizeof(buf), "%s:%s:%u", bp->bp_prov,
2012 bp->bp_unitbp_func, bp->bp_rate);
2013 } else {
2014 snprintf(buf, sizeof(buf), "%s:%s:%s", bp->bp_prov,
2015 bp->bp_unitbp_func, bp->bp_name);
2016 }
2017
2018 return buf;
2019}
2020
2021unsigned long
2022dt_get_offset(pid_t pid)
2023{
2024 static struct dtioc_getaux cache[32];
2025 static int next;
2026 struct dtioc_getaux *aux = NULL((void *)0);
2027 int i;
2028
2029 for (i = 0; i < 32; i++) {
2030 if (cache[i].dtga_pid != pid)
2031 continue;
2032 aux = cache + i;
2033 break;
2034 }
2035
2036 if (aux == NULL((void *)0)) {
2037 aux = &cache[next++];
2038 next %= 32;
2039
2040 aux->dtga_pid = pid;
2041 if (ioctl(dtfd, DTIOCGETAUXBASE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct dtioc_getaux) & 0x1fff) << 16) | ((('D')) <<
8) | ((7)))
, aux))
2042 aux->dtga_auxbase = 0;
2043 }
2044
2045 return aux->dtga_auxbase;
2046}