Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name btrace.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -D PTRACE -D KTRACE -D ACCOUNTING -D NFSCLIENT -D SYSVSHM -D SYSVSEM -D SYSVMSG -I /usr/src/usr.sbin/btrace -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/btrace/btrace.c
1/* $OpenBSD: btrace.c,v 1.61 2021/12/07 22:17:03 guenther Exp $ */
2
3/*
4 * Copyright (c) 2019 - 2021 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/exec_elf.h>
21#include <sys/stat.h>
22#include <sys/syscall.h>
23#include <sys/queue.h>
24
25#include <assert.h>
26#include <err.h>
27#include <errno(*__errno()).h>
28#include <fcntl.h>
29#include <limits.h>
30#include <locale.h>
31#include <paths.h>
32#include <signal.h>
33#include <stdarg.h>
34#include <stdbool.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <time.h>
39#include <unistd.h>
40
41#include <dev/dt/dtvar.h>
42
43#include "btrace.h"
44#include "bt_parser.h"
45
46#define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
47#define MAXIMUM(a, b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b))
48
49/*
50 * Maximum number of operands an arithmetic operation can have. This
51 * is necessary to stop infinite recursion when evaluating expressions.
52 */
53#define __MAXOPERANDS5 5
54
55#define __PATH_DEVDT"/dev/dt" "/dev/dt"
56
57__dead__attribute__((__noreturn__)) void usage(void);
58char *read_btfile(const char *, size_t *);
59
60/*
61 * Retrieve & parse probe information.
62 */
63void dtpi_cache(int);
64void dtpi_print_list(void);
65const char *dtpi_func(struct dtioc_probe_info *);
66int dtpi_is_unit(const char *);
67struct dtioc_probe_info *dtpi_get_by_value(const char *, const char *,
68 const char *);
69
70/*
71 * Main loop and rule evaluation.
72 */
73void rules_do(int);
74void rules_setup(int);
75void rules_apply(struct dt_evt *);
76void rules_teardown(int);
77void rule_eval(struct bt_rule *, struct dt_evt *);
78void rule_printmaps(struct bt_rule *);
79
80/*
81 * Language builtins & functions.
82 */
83uint64_t builtin_nsecs(struct dt_evt *);
84const char *builtin_kstack(struct dt_evt *);
85const char *builtin_arg(struct dt_evt *, enum bt_argtype);
86struct bt_arg *fn_str(struct bt_arg *, struct dt_evt *, char *);
87void stmt_eval(struct bt_stmt *, struct dt_evt *);
88void stmt_bucketize(struct bt_stmt *, struct dt_evt *);
89void stmt_clear(struct bt_stmt *);
90void stmt_delete(struct bt_stmt *, struct dt_evt *);
91void stmt_insert(struct bt_stmt *, struct dt_evt *);
92void stmt_print(struct bt_stmt *, struct dt_evt *);
93void stmt_store(struct bt_stmt *, struct dt_evt *);
94bool_Bool stmt_test(struct bt_stmt *, struct dt_evt *);
95void stmt_time(struct bt_stmt *, struct dt_evt *);
96void stmt_zero(struct bt_stmt *);
97struct bt_arg *ba_read(struct bt_arg *);
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 */
117
118struct dt_evt bt_devt; /* fake event for BEGIN/END */
119uint64_t bt_filtered; /* # of events filtered out */
120
121char **vargs;
122int nargs = 0;
123int verbose = 0;
124volatile sig_atomic_t quit_pending;
125
126static void
127signal_handler(int sig)
128{
129 quit_pending = sig;
130}
131
132
133int
134main(int argc, char *argv[])
135{
136 int fd = -1, ch, error = 0;
137 const char *filename = NULL((void *)0), *btscript = NULL((void *)0);
138 int showprobes = 0, noaction = 0;
139 size_t btslen = 0;
140
141 setlocale(LC_ALL0, "");
142
143 while ((ch = getopt(argc, argv, "e:lnp:v")) != -1) {
144 switch (ch) {
145 case 'e':
146 btscript = optarg;
147 btslen = strlen(btscript);
148 break;
149 case 'l':
150 showprobes = 1;
151 break;
152 case 'n':
153 noaction = 1;
154 break;
155 case 'v':
156 verbose++;
157 break;
158 default:
159 usage();
160 }
161 }
162
163 argc -= optind;
164 argv += optind;
165
166 if (argc > 0 && btscript == NULL((void *)0))
167 filename = argv[0];
168
169 /* Cannot pledge due to special ioctl()s */
170 if (unveil(__PATH_DEVDT"/dev/dt", "r") == -1)
171 err(1, "unveil %s", __PATH_DEVDT"/dev/dt");
172 if (unveil(_PATH_KSYMS"/dev/ksyms", "r") == -1)
173 err(1, "unveil %s", _PATH_KSYMS"/dev/ksyms");
174 if (filename != NULL((void *)0)) {
175 if (unveil(filename, "r") == -1)
176 err(1, "unveil %s", filename);
177 }
178 if (unveil(NULL((void *)0), NULL((void *)0)) == -1)
179 err(1, "unveil");
180
181 if (filename != NULL((void *)0)) {
182 btscript = read_btfile(filename, &btslen);
183 argc--;
184 argv++;
185 }
186
187 nargs = argc;
188 vargs = argv;
189
190 if (btscript == NULL((void *)0) && !showprobes)
191 usage();
192
193 if (btscript != NULL((void *)0)) {
194 error = btparse(btscript, btslen, filename, 1);
195 if (error)
196 return error;
197 }
198
199 if (noaction)
200 return error;
201
202 if (showprobes || g_nprobes > 0) {
203 fd = open(__PATH_DEVDT"/dev/dt", O_RDONLY0x0000);
204 if (fd == -1)
205 err(1, "could not open %s", __PATH_DEVDT"/dev/dt");
206 }
207
208 if (showprobes) {
209 dtpi_cache(fd);
210 dtpi_print_list();
211 }
212
213 if (!TAILQ_EMPTY(&g_rules)(((&g_rules)->tqh_first) == ((void *)0)))
214 rules_do(fd);
215
216 if (fd != -1)
217 close(fd);
218
219 return error;
220}
221
222__dead__attribute__((__noreturn__)) void
223usage(void)
224{
225 fprintf(stderr(&__sF[2]), "usage: %s [-lnv] [-e program | file] [argument ...]\n",
226 getprogname());
227 exit(1);
228}
229
230char *
231read_btfile(const char *filename, size_t *len)
232{
233 FILE *fp;
234 char *fcontent;
235 struct stat st;
236 size_t fsize;
237
238 if (stat(filename, &st))
239 err(1, "can't stat '%s'", filename);
240
241 fsize = st.st_size;
242 fcontent = malloc(fsize + 1);
243 if (fcontent == NULL((void *)0))
244 err(1, "malloc");
245
246 fp = fopen(filename, "r");
247 if (fp == NULL((void *)0))
248 err(1, "can't open '%s'", filename);
249
250 if (fread(fcontent, 1, fsize, fp) != fsize)
251 err(1, "can't read '%s'", filename);
252 fcontent[fsize] = '\0';
253
254 fclose(fp);
255 *len = fsize;
256 return fcontent;
257}
258
259static int
260dtpi_cmp(const void *a, const void *b)
261{
262 const struct dtioc_probe_info *ai = a, *bi = b;
263
264 if (ai->dtpi_pbn > bi->dtpi_pbn)
265 return 1;
266 if (ai->dtpi_pbn < bi->dtpi_pbn)
267 return -1;
268 return 0;
269}
270
271void
272dtpi_cache(int fd)
273{
274 struct dtioc_probe dtpr;
275
276 if (dt_dtpis != NULL((void *)0))
277 return;
278
279 memset(&dtpr, 0, sizeof(dtpr));
280 if (ioctl(fd, DTIOCGPLIST(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct dtioc_probe) & 0x1fff) << 16) | ((('D')) <<
8) | ((1)))
, &dtpr))
281 err(1, "DTIOCGPLIST");
282
283 dt_ndtpi = (dtpr.dtpr_size / sizeof(*dt_dtpis));
284 dt_dtpis = reallocarray(NULL((void *)0), dt_ndtpi, sizeof(*dt_dtpis));
285 if (dt_dtpis == NULL((void *)0))
286 err(1, "malloc");
287
288 dtpr.dtpr_probes = dt_dtpis;
289 if (ioctl(fd, DTIOCGPLIST(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct dtioc_probe) & 0x1fff) << 16) | ((('D')) <<
8) | ((1)))
, &dtpr))
290 err(1, "DTIOCGPLIST");
291
292 qsort(dt_dtpis, dt_ndtpi, sizeof(*dt_dtpis), dtpi_cmp);
293}
294
295void
296dtpi_print_list(void)
297{
298 struct dtioc_probe_info *dtpi;
299 size_t i;
300
301 dtpi = dt_dtpis;
302 for (i = 0; i < dt_ndtpi; i++, dtpi++) {
303 printf("%s:%s:%s\n", dtpi->dtpi_prov, dtpi_func(dtpi),
304 dtpi->dtpi_name);
305 }
306}
307
308const char *
309dtpi_func(struct dtioc_probe_info *dtpi)
310{
311 char *sysnb, func[DTNAMESIZE16];
312 const char *errstr;
313 int idx;
314
315 if (strncmp(dtpi->dtpi_prov, "syscall", DTNAMESIZE16))
316 return dtpi->dtpi_func;
317
318 /* Translate syscall names */
319 strlcpy(func, dtpi->dtpi_func, sizeof(func));
320 sysnb = func;
321 if (strsep(&sysnb, "%") == NULL((void *)0))
322 return dtpi->dtpi_func;
323
324 idx = strtonum(sysnb, 1, SYS_MAXSYSCALL331, &errstr);
325 if (errstr != NULL((void *)0))
326 return dtpi->dtpi_func;
327
328 return syscallnames[idx];
329}
330
331int
332dtpi_is_unit(const char *unit)
333{
334 return !strncmp("hz", unit, sizeof("hz"));
335}
336
337struct dtioc_probe_info *
338dtpi_get_by_value(const char *prov, const char *func, const char *name)
339{
340 struct dtioc_probe_info *dtpi;
341 size_t i;
342
343 dtpi = dt_dtpis;
344 for (i = 0; i < dt_ndtpi; i++, dtpi++) {
345 if (prov != NULL((void *)0) &&
346 strncmp(prov, dtpi->dtpi_prov, DTNAMESIZE16))
347 continue;
348
349 if (func != NULL((void *)0)) {
350 if (dtpi_is_unit(func))
351 return dtpi;
352
353 if (strncmp(func, dtpi_func(dtpi), DTNAMESIZE16))
354 continue;
355 }
356
357 if (strncmp(name, dtpi->dtpi_name, DTNAMESIZE16))
358 continue;
359
360 debug("matched probe %s:%s:%s\n", dtpi->dtpi_prov,
361 dtpi_func(dtpi), dtpi->dtpi_name);
362 return dtpi;
363 }
364
365 return NULL((void *)0);
366}
367
368static struct dtioc_probe_info *
369dtpi_get_by_id(unsigned int pbn)
370{
371 struct dtioc_probe_info d;
372
373 d.dtpi_pbn = pbn;
374 return bsearch(&d, dt_dtpis, dt_ndtpi, sizeof(*dt_dtpis), dtpi_cmp);
375}
376
377void
378rules_do(int fd)
379{
380 struct sigaction sa;
381
382 memset(&sa, 0, sizeof(sa));
383 sigemptyset(&sa.sa_mask);
384 sa.sa_flags = 0;
385 sa.sa_handler__sigaction_u.__sa_handler = signal_handler;
386 if (sigaction(SIGINT2, &sa, NULL((void *)0)))
387 err(1, "sigaction");
388
389 rules_setup(fd);
390
391 while (!quit_pending && g_nprobes > 0) {
392 static struct dt_evt devtbuf[64];
393 ssize_t rlen;
394 size_t i;
395
396 rlen = read(fd, devtbuf, sizeof(devtbuf) - 1);
397 if (rlen == -1) {
398 if (errno(*__errno()) == EINTR4 && quit_pending) {
399 printf("\n");
400 break;
401 }
402 err(1, "read");
403 }
404
405 if ((rlen % sizeof(struct dt_evt)) != 0)
406 err(1, "incorrect read");
407
408 for (i = 0; i < rlen / sizeof(struct dt_evt); i++)
409 rules_apply(&devtbuf[i]);
410 }
411
412 rules_teardown(fd);
413
414 if (verbose && fd != -1) {
415 struct dtioc_stat dtst;
416
417 memset(&dtst, 0, sizeof(dtst));
418 if (ioctl(fd, DTIOCGSTATS((unsigned long)0x40000000 | ((sizeof(struct dtioc_stat) &
0x1fff) << 16) | ((('D')) << 8) | ((2)))
, &dtst))
419 warn("DTIOCGSTATS");
420
421 printf("%llu events read\n", dtst.dtst_readevt);
422 printf("%llu events dropped\n", dtst.dtst_dropevt);
423 printf("%llu events filtered\n", bt_filtered);
424 }
425}
426
427void
428rules_setup(int fd)
429{
430 struct dtioc_probe_info *dtpi;
431 struct dtioc_req *dtrq;
432 struct bt_rule *r, *rbegin = NULL((void *)0);
433 struct bt_probe *bp;
434 struct bt_stmt *bs;
435 int dokstack = 0, on = 1;
436 uint64_t evtflags;
437
438 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
{
439 evtflags = 0;
440 SLIST_FOREACH(bs, &r->br_action, bs_next)for((bs) = ((&r->br_action)->slh_first); (bs) != ((
void *)0); (bs) = ((bs)->bs_next.sle_next))
{
441 struct bt_arg *ba;
442
443 SLIST_FOREACH(ba, &bs->bs_args, ba_next)for((ba) = ((&bs->bs_args)->slh_first); (ba) != ((void
*)0); (ba) = ((ba)->ba_next.sle_next))
444 evtflags |= ba2dtflags(ba);
445
446 /* Also check the value for map/hist insertion */
447 switch (bs->bs_act) {
448 case B_AC_BUCKETIZE:
449 case B_AC_INSERT:
450 ba = (struct bt_arg *)bs->bs_var;
451 evtflags |= ba2dtflags(ba);
452 break;
453 default:
454 break;
455 }
456 }
457
458 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
459 debug("parsed probe '%s'", debug_probe_name(bp));
460 debug_dump_filter(r);
461
462 if (bp->bp_type != B_PT_PROBE) {
463 if (bp->bp_type == B_PT_BEGIN)
464 rbegin = r;
465 continue;
466 }
467
468 dtpi_cache(fd);
469 dtpi = dtpi_get_by_value(bp->bp_prov, bp->bp_func,
470 bp->bp_name);
471 if (dtpi == NULL((void *)0)) {
472 errx(1, "probe '%s:%s:%s' not found",
473 bp->bp_prov, bp->bp_func, bp->bp_name);
474 }
475
476 dtrq = calloc(1, sizeof(*dtrq));
477 if (dtrq == NULL((void *)0))
478 err(1, "dtrq: 1alloc");
479
480 bp->bp_pbn = dtpi->dtpi_pbn;
481 dtrq->dtrq_pbn = dtpi->dtpi_pbn;
482 dtrq->dtrq_rate = bp->bp_rate;
483 dtrq->dtrq_evtflags = evtflags;
484 if (dtrq->dtrq_evtflags & DTEVT_KSTACK(1 << 2))
485 dokstack = 1;
486 bp->bp_cookie = dtrq;
487 }
488 }
489
490 if (dokstack)
491 kelf_open();
492
493 /* Initialize "fake" event for BEGIN/END */
494 bt_devt.dtev_pbn = -1;
495 memcpy(&bt_devt.dtev_comm, getprogname(), sizeof(bt_devt.dtev_comm));
496 bt_devt.dtev_pid = getpid();
497 bt_devt.dtev_tid = getthrid();
498 clock_gettime(CLOCK_REALTIME0, &bt_devt.dtev_tsp);
499
500 if (rbegin)
501 rule_eval(rbegin, &bt_devt);
502
503 /* Enable all probes */
504 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
{
505 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
506 if (bp->bp_type != B_PT_PROBE)
507 continue;
508
509 dtrq = bp->bp_cookie;
510 if (ioctl(fd, DTIOCPRBENABLE((unsigned long)0x80000000 | ((sizeof(struct dtioc_req) &
0x1fff) << 16) | ((('D')) << 8) | ((4)))
, dtrq))
511 err(1, "DTIOCPRBENABLE");
512 }
513 }
514
515 if (g_nprobes > 0) {
516 if (ioctl(fd, DTIOCRECORD((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('D')) << 8) | ((3)))
, &on))
517 err(1, "DTIOCRECORD");
518 }
519}
520
521void
522rules_apply(struct dt_evt *dtev)
523{
524 struct bt_rule *r;
525 struct bt_probe *bp;
526
527 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
{
528 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
529 if (bp->bp_type != B_PT_PROBE ||
530 bp->bp_pbn != dtev->dtev_pbn)
531 continue;
532
533 rule_eval(r, dtev);
534 }
535 }
536}
537
538void
539rules_teardown(int fd)
540{
541 struct dtioc_req *dtrq;
542 struct bt_probe *bp;
543 struct bt_rule *r, *rend = NULL((void *)0);
544 int dokstack = 0, off = 0;
545
546 if (g_nprobes > 0) {
547 if (ioctl(fd, DTIOCRECORD((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('D')) << 8) | ((3)))
, &off))
548 err(1, "DTIOCRECORD");
549 }
550
551 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
{
552 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
553 if (bp->bp_type != B_PT_PROBE) {
554 if (bp->bp_type == B_PT_END)
555 rend = r;
556 continue;
557 }
558
559 dtrq = bp->bp_cookie;
560 if (ioctl(fd, DTIOCPRBDISABLE((unsigned long)0x80000000 | ((sizeof(struct dtioc_req) &
0x1fff) << 16) | ((('D')) << 8) | ((5)))
, dtrq))
561 err(1, "DTIOCPRBDISABLE");
562 if (dtrq->dtrq_evtflags & DTEVT_KSTACK(1 << 2))
563 dokstack = 1;
564 }
565 }
566
567 if (dokstack)
568 kelf_close();
569
570 /* Update "fake" event for BEGIN/END */
571 clock_gettime(CLOCK_REALTIME0, &bt_devt.dtev_tsp);
572
573 if (rend)
574 rule_eval(rend, &bt_devt);
575
576 /* Print non-empty map & hist */
577 TAILQ_FOREACH(r, &g_rules, br_next)for((r) = ((&g_rules)->tqh_first); (r) != ((void *)0);
(r) = ((r)->br_next.tqe_next))
578 rule_printmaps(r);
579}
580
581void
582rule_eval(struct bt_rule *r, struct dt_evt *dtev)
583{
584 struct bt_stmt *bs;
585 struct bt_probe *bp;
586
587 SLIST_FOREACH(bp, &r->br_probes, bp_next)for((bp) = ((&r->br_probes)->slh_first); (bp) != ((
void *)0); (bp) = ((bp)->bp_next.sle_next))
{
588 debug("eval rule '%s'", debug_probe_name(bp));
589 debug_dump_filter(r);
590 }
591
592 if (r->br_filter != NULL((void *)0) && r->br_filter->bf_condition != NULL((void *)0)) {
593 if (stmt_test(r->br_filter->bf_condition, dtev) == false0) {
594 bt_filtered++;
595 return;
596 }
597 }
598
599 SLIST_FOREACH(bs, &r->br_action, bs_next)for((bs) = ((&r->br_action)->slh_first); (bs) != ((
void *)0); (bs) = ((bs)->bs_next.sle_next))
{
600 if ((bs->bs_act == B_AC_TEST) && stmt_test(bs, dtev) == true1)
601 stmt_eval((struct bt_stmt *)bs->bs_var, dtev);
602
603 stmt_eval(bs, dtev);
604 }
605}
606
607void
608rule_printmaps(struct bt_rule *r)
609{
610 struct bt_stmt *bs;
611
612 SLIST_FOREACH(bs, &r->br_action, bs_next)for((bs) = ((&r->br_action)->slh_first); (bs) != ((
void *)0); (bs) = ((bs)->bs_next.sle_next))
{
613 struct bt_arg *ba;
614
615 SLIST_FOREACH(ba, &bs->bs_args, ba_next)for((ba) = ((&bs->bs_args)->slh_first); (ba) != ((void
*)0); (ba) = ((ba)->ba_next.sle_next))
{
616 struct bt_var *bv = ba->ba_value;
617 struct map *map;
618
619 if (ba->ba_type != B_AT_MAP && ba->ba_type != B_AT_HIST)
620 continue;
621
622 map = (struct map *)bv->bv_value;
623 if (map == NULL((void *)0))
624 continue;
625
626 if (ba->ba_type == B_AT_MAP)
627 map_print(map, SIZE_T_MAX(9223372036854775807L *2UL+1UL), bv_name(bv));
628 else
629 hist_print((struct hist *)map, bv_name(bv));
630 map_clear(map);
631 bv->bv_value = NULL((void *)0);
632 }
633 }
634}
635
636time_t
637builtin_gettime(struct dt_evt *dtev)
638{
639 struct timespec ts;
640
641 if (dtev == NULL((void *)0)) {
642 clock_gettime(CLOCK_REALTIME0, &ts);
643 return ts.tv_sec;
644 }
645
646 return dtev->dtev_tsp.tv_sec;
647}
648
649static inline uint64_t
650TIMESPEC_TO_NSEC(struct timespec *ts)
651{
652 return (ts->tv_sec * 1000000000L + ts->tv_nsec);
653}
654
655uint64_t
656builtin_nsecs(struct dt_evt *dtev)
657{
658 struct timespec ts;
659
660 if (dtev == NULL((void *)0)) {
661 clock_gettime(CLOCK_REALTIME0, &ts);
662 return TIMESPEC_TO_NSEC(&ts);
663 }
664
665 return TIMESPEC_TO_NSEC(&dtev->dtev_tsp);
666}
667
668const char *
669builtin_stack(struct dt_evt *dtev, int kernel)
670{
671 struct stacktrace *st = &dtev->dtev_kstack;
672 static char buf[4096], *bp;
673 size_t i;
674 int sz;
675
676 if (!kernel)
677 return "";
678 if (st->st_count == 0)
679 return "\nuserland\n";
680
681 buf[0] = '\0';
682 bp = buf;
683 sz = sizeof(buf);
684 for (i = 0; i < st->st_count; i++) {
685 int l;
686
687 l = kelf_snprintsym(bp, sz - 1, st->st_pc[i]);
688 if (l < 0)
689 break;
690 if (l >= sz - 1) {
691 bp += sz - 1;
692 sz = 1;
693 break;
694 }
695 bp += l;
696 sz -= l;
697 }
698 snprintf(bp, sz, "\nkernel\n");
699
700 return buf;
701}
702
703const char *
704builtin_arg(struct dt_evt *dtev, enum bt_argtype dat)
705{
706 static char buf[sizeof("18446744073709551615")]; /* UINT64_MAX */
707
708 snprintf(buf, sizeof(buf), "%lu",
709 dtev->dtev_args_args.E_entry[dat - B_AT_BI_ARG0]);
710
711 return buf;
712}
713
714void
715stmt_eval(struct bt_stmt *bs, struct dt_evt *dtev)
716{
717 switch (bs->bs_act) {
718 case B_AC_BUCKETIZE:
719 stmt_bucketize(bs, dtev);
720 break;
721 case B_AC_CLEAR:
722 stmt_clear(bs);
723 break;
724 case B_AC_DELETE:
725 stmt_delete(bs, dtev);
726 break;
727 case B_AC_EXIT:
728 exit(0);
729 break;
730 case B_AC_INSERT:
731 stmt_insert(bs, dtev);
732 break;
733 case B_AC_PRINT:
734 stmt_print(bs, dtev);
735 break;
736 case B_AC_PRINTF:
737 stmt_printf(bs, dtev);
738 break;
739 case B_AC_STORE:
740 stmt_store(bs, dtev);
741 break;
742 case B_AC_TEST:
743 /* done before */
744 break;
745 case B_AC_TIME:
746 stmt_time(bs, dtev);
747 break;
748 case B_AC_ZERO:
749 stmt_zero(bs);
750 break;
751 default:
752 xabort("no handler for action type %d", bs->bs_act);
753 }
754}
755
756/*
757 * Increment a bucket: { @h = hist(v); } or { @h = lhist(v, min, max, step); }
758 *
759 * In this case 'h' is represented by `bv' and '(min, max, step)' by `brange'.
760 */
761void
762stmt_bucketize(struct bt_stmt *bs, struct dt_evt *dtev)
763{
764 struct bt_arg *brange, *bhist = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
765 struct bt_arg *bval = (struct bt_arg *)bs->bs_var;
766 struct bt_var *bv = bhist->ba_value;
767 const char *bucket;
768 long step = 0;
769
770 assert(bhist->ba_type == B_AT_HIST)((bhist->ba_type == B_AT_HIST) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 770, __func__, "bhist->ba_type == B_AT_HIST"))
;
771 assert(SLIST_NEXT(bval, ba_next) == NULL)((((bval)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 771, __func__, "SLIST_NEXT(bval, ba_next) == NULL"
))
;
772
773 brange = bhist->ba_key;
774 bucket = ba2bucket(bval, brange, dtev, &step);
775 if (bucket == NULL((void *)0)) {
776 debug("hist=%p '%s' value=%lu out of range\n", bv->bv_value,
777 bv_name(bv), ba2long(bval, dtev));
778 return;
779 }
780 debug("hist=%p '%s' increment bucket '%s'\n", bv->bv_value,
781 bv_name(bv), bucket);
782
783 bv->bv_value = (struct bt_arg *)
784 hist_increment((struct hist *)bv->bv_value, bucket, step);
785 bv->bv_type = B_VT_HIST;
786}
787
788
789/*
790 * Empty a map: { clear(@map); }
791 */
792void
793stmt_clear(struct bt_stmt *bs)
794{
795 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
796 struct bt_var *bv = ba->ba_value;
797 struct map *map;
798
799 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 799, __func__, "bs->bs_var == NULL"))
;
800 assert(ba->ba_type == B_AT_VAR)((ba->ba_type == B_AT_VAR) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 800, __func__, "ba->ba_type == B_AT_VAR"))
;
801
802 map = (struct map *)bv->bv_value;
803 if (map == NULL((void *)0))
804 return;
805
806 if (bv->bv_type != B_VT_MAP && bv->bv_type != B_VT_HIST)
807 errx(1, "invalid variable type for clear(%s)", ba_name(ba));
808
809 map_clear(map);
810 bv->bv_value = NULL((void *)0);
811
812 debug("map=%p '%s' clear\n", map, bv_name(bv));
813}
814
815/*
816 * Map delete: { delete(@map[key]); }
817 *
818 * In this case 'map' is represented by `bv' and 'key' by `bkey'.
819 */
820void
821stmt_delete(struct bt_stmt *bs, struct dt_evt *dtev)
822{
823 struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
824 struct bt_var *bv = bmap->ba_value;
825 struct map *map;
826 const char *hash;
827
828 assert(bmap->ba_type == B_AT_MAP)((bmap->ba_type == B_AT_MAP) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 828, __func__, "bmap->ba_type == B_AT_MAP"))
;
829 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 829, __func__, "bs->bs_var == NULL"))
;
830
831 map = (struct map *)bv->bv_value;
832 if (map == NULL((void *)0))
833 return;
834
835 bkey = bmap->ba_key;
836 hash = ba2hash(bkey, dtev);
837 debug("map=%p '%s' delete key=%p '%s'\n", map, bv_name(bv), bkey, hash);
838
839 map_delete(map, hash);
840}
841
842/*
843 * Map insert: { @map[key] = 42; }
844 *
845 * In this case 'map' is represented by `bv', 'key' by `bkey' and
846 * '42' by `bval'.
847 */
848void
849stmt_insert(struct bt_stmt *bs, struct dt_evt *dtev)
850{
851 struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
852 struct bt_arg *bval = (struct bt_arg *)bs->bs_var;
853 struct bt_var *bv = bmap->ba_value;
854 struct map *map;
855 const char *hash;
856
857 assert(bmap->ba_type == B_AT_MAP)((bmap->ba_type == B_AT_MAP) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 857, __func__, "bmap->ba_type == B_AT_MAP"))
;
858 assert(SLIST_NEXT(bval, ba_next) == NULL)((((bval)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 858, __func__, "SLIST_NEXT(bval, ba_next) == NULL"
))
;
859
860 bkey = bmap->ba_key;
861 hash = ba2hash(bkey, dtev);
862
863 /* map is NULL before first insert or after clear() */
864 map = (struct map *)bv->bv_value;
865 map = map_insert(map, hash, bval, dtev);
866
867 debug("map=%p '%s' insert key=%p '%s' bval=%p\n", map,
868 bv_name(bv), bkey, hash, bval);
869
870 bv->bv_value = (struct bt_arg *)map;
871 bv->bv_type = B_VT_MAP;
872}
873
874/*
875 * Print variables: { print(890); print(@map[, 8]); print(comm); }
876 *
877 * In this case the global variable 'map' is pointed at by `ba'
878 * and '8' is represented by `btop'.
879 */
880void
881stmt_print(struct bt_stmt *bs, struct dt_evt *dtev)
882{
883 struct bt_arg *btop, *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
884 struct bt_var *bv = ba->ba_value;
885 struct map *map;
886 size_t top = SIZE_T_MAX(9223372036854775807L *2UL+1UL);
887
888 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 888, __func__, "bs->bs_var == NULL"))
;
889
890 /* Parse optional `top' argument. */
891 btop = SLIST_NEXT(ba, ba_next)((ba)->ba_next.sle_next);
892 if (btop != NULL((void *)0)) {
893 assert(SLIST_NEXT(btop, ba_next) == NULL)((((btop)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 893, __func__, "SLIST_NEXT(btop, ba_next) == NULL"
))
;
894 top = ba2long(btop, dtev);
895 }
896
897 /* Static argument. */
898 if (ba->ba_type != B_AT_VAR) {
899 assert(btop == NULL)((btop == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 899, __func__, "btop == NULL"))
;
900 printf("%s\n", ba2str(ba, dtev));
901 return;
902 }
903
904 map = (struct map *)bv->bv_value;
905 if (map == NULL((void *)0))
906 return;
907
908 debug("map=%p '%s' print (top=%d)\n", bv->bv_value, bv_name(bv), top);
909
910 if (bv->bv_type == B_VT_MAP)
911 map_print(map, top, bv_name(bv));
912 else if (bv->bv_type == B_VT_HIST)
913 hist_print((struct hist *)map, bv_name(bv));
914 else
915 printf("%s\n", ba2str(ba, dtev));
916}
917
918/*
919 * Variable store: { @var = 3; }
920 *
921 * In this case '3' is represented by `ba', the argument of a STORE
922 * action.
923 *
924 * If the argument depends of the value of an event (builtin) or is
925 * the result of an operation, its evaluation is stored in a new `ba'.
926 */
927void
928stmt_store(struct bt_stmt *bs, struct dt_evt *dtev)
929{
930 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
931 struct bt_var *bv = bs->bs_var;
932
933 assert(SLIST_NEXT(ba, ba_next) == NULL)((((ba)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 933, __func__, "SLIST_NEXT(ba, ba_next) == NULL"
))
;
1
Assuming field 'sle_next' is equal to null
2
'?' condition is true
934
935 switch (ba->ba_type) {
3
Control jumps to 'case B_AT_OP_PLUS:' at line 948
936 case B_AT_STR:
937 bv->bv_value = ba;
938 bv->bv_type = B_VT_STR;
939 break;
940 case B_AT_LONG:
941 bv->bv_value = ba;
942 bv->bv_type = B_VT_LONG;
943 break;
944 case B_AT_BI_NSECS:
945 bv->bv_value = ba_new(builtin_nsecs(dtev), B_AT_LONG)ba_new0((void *)(builtin_nsecs(dtev)), (B_AT_LONG));
946 bv->bv_type = B_VT_LONG;
947 break;
948 case B_AT_OP_PLUS ... B_AT_OP_LOR:
949 bv->bv_value = ba_new(ba2long(ba, dtev), B_AT_LONG)ba_new0((void *)(ba2long(ba, dtev)), (B_AT_LONG));
4
Calling 'ba2long'
950 bv->bv_type = B_VT_LONG;
951 break;
952 case B_AT_FN_STR:
953 bv->bv_value = ba_new(ba2str(ba, dtev), B_AT_STR)ba_new0((void *)(ba2str(ba, dtev)), (B_AT_STR));
954 bv->bv_type = B_VT_STR;
955 break;
956 default:
957 xabort("store not implemented for type %d", ba->ba_type);
958 }
959
960 debug("bv=%p var '%s' store (%p)\n", bv, bv_name(bv), bv->bv_value);
961}
962
963/*
964 * String conversion { str($1); string($1, 3); }
965 *
966 * Since fn_str is currently only called in ba2str, *buf should be a pointer
967 * to the static buffer provided by ba2str.
968 */
969struct bt_arg *
970fn_str(struct bt_arg *ba, struct dt_evt *dtev, char *buf)
971{
972 struct bt_arg *arg, *index;
973 ssize_t len = STRLEN64;
974
975 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"
, 975, __func__, "ba->ba_type == B_AT_FN_STR"))
;
976
977 arg = (struct bt_arg*)ba->ba_value;
978 assert(arg != NULL)((arg != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 978, __func__, "arg != NULL"))
;
979
980 index = SLIST_NEXT(arg, ba_next)((arg)->ba_next.sle_next);
981 if (index != NULL((void *)0)) {
982 /* Should have only 1 optional argument. */
983 assert(SLIST_NEXT(index, ba_next) == NULL)((((index)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 983, __func__, "SLIST_NEXT(index, ba_next) == NULL"
))
;
984 len = MINIMUM(ba2long(index, dtev) + 1, STRLEN)(((ba2long(index, dtev) + 1) < (64)) ? (ba2long(index, dtev
) + 1) : (64))
;
985 }
986
987 /* All negative lengths behave the same as a zero length. */
988 if (len < 1)
989 return ba_new("", B_AT_STR)ba_new0((void *)(""), (B_AT_STR));
990
991 strlcpy(buf, ba2str(arg, dtev), len);
992 return ba_new(buf, B_AT_STR)ba_new0((void *)(buf), (B_AT_STR));
993}
994
995/*
996 * Expression test: { if (expr) stmt; }
997 */
998bool_Bool
999stmt_test(struct bt_stmt *bs, struct dt_evt *dtev)
1000{
1001 struct bt_arg *ba;
1002
1003 if (bs == NULL((void *)0))
1004 return true1;
1005
1006 ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
1007
1008 return baexpr2long(ba, dtev) != 0;
1009}
1010
1011/*
1012 * Print time: { time("%H:%M:%S"); }
1013 */
1014void
1015stmt_time(struct bt_stmt *bs, struct dt_evt *dtev)
1016{
1017 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
1018 time_t time;
1019 struct tm *tm;
1020 char buf[64];
1021
1022 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1022, __func__, "bs->bs_var == NULL"))
;
1023 assert(ba->ba_type == B_AT_STR)((ba->ba_type == B_AT_STR) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1023, __func__, "ba->ba_type == B_AT_STR"))
;
1024 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", 1024, __func__
, "strlen(ba2str(ba, dtev)) < (sizeof(buf) - 1)"))
;
1025
1026 time = builtin_gettime(dtev);
1027 tm = localtime(&time);
1028 strftime(buf, sizeof(buf), ba2str(ba, dtev), tm);
1029 printf("%s", buf);
1030}
1031
1032/*
1033 * Set entries to 0: { zero(@map); }
1034 */
1035void
1036stmt_zero(struct bt_stmt *bs)
1037{
1038 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first);
1039 struct bt_var *bv = ba->ba_value;
1040 struct map *map;
1041
1042 assert(bs->bs_var == NULL)((bs->bs_var == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1042, __func__, "bs->bs_var == NULL"))
;
1043 assert(ba->ba_type == B_AT_VAR)((ba->ba_type == B_AT_VAR) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1043, __func__, "ba->ba_type == B_AT_VAR"))
;
1044
1045 map = (struct map *)bv->bv_value;
1046 if (map == NULL((void *)0))
1047 return;
1048
1049 if (bv->bv_type != B_VT_MAP && bv->bv_type != B_VT_HIST)
1050 errx(1, "invalid variable type for zero(%s)", ba_name(ba));
1051
1052 map_zero(map);
1053
1054 debug("map=%p '%s' zero\n", map, bv_name(bv));
1055}
1056
1057struct bt_arg *
1058ba_read(struct bt_arg *ba)
1059{
1060 struct bt_var *bv = ba->ba_value;
1061
1062 assert(ba->ba_type == B_AT_VAR)((ba->ba_type == B_AT_VAR) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1062, __func__, "ba->ba_type == B_AT_VAR"))
;
1063
1064 debug("bv=%p read '%s' (%p)\n", bv, bv_name(bv), bv->bv_value);
1065
1066 /* Handle map/hist access after clear(). */
1067 if (bv->bv_value == NULL((void *)0))
1068 return &g_nullba;
1069
1070 return bv->bv_value;
1071}
1072
1073const char *
1074ba2hash(struct bt_arg *ba, struct dt_evt *dtev)
1075{
1076 static char buf[KLEN512];
1077 char *hash;
1078 int l, len;
1079
1080 buf[0] = '\0';
1081 l = snprintf(buf, sizeof(buf), "%s", ba2str(ba, dtev));
1082 if (l < 0 || (size_t)l > sizeof(buf)) {
1083 warn("string too long %d > %lu", l, sizeof(buf));
1084 return buf;
1085 }
1086
1087 len = 0;
1088 while ((ba = SLIST_NEXT(ba, ba_next)((ba)->ba_next.sle_next)) != NULL((void *)0)) {
1089 len += l;
1090 hash = buf + len;
1091
1092 l = snprintf(hash, sizeof(buf) - len, ", %s", ba2str(ba, dtev));
1093 if (l < 0 || (size_t)l > (sizeof(buf) - len)) {
1094 warn("hash too long %d > %lu", l + len, sizeof(buf));
1095 break;
1096 }
1097 }
1098
1099 return buf;
1100}
1101
1102static unsigned long
1103next_pow2(unsigned long x)
1104{
1105 size_t i;
1106
1107 x--;
1108 for (i = 0; i < (sizeof(x) * 8) - 1; i++)
1109 x |= (x >> 1);
1110
1111 return x + 1;
1112}
1113
1114/*
1115 * Return the ceiling value the interval holding `ba' or NULL if it is
1116 * out of the (min, max) values.
1117 */
1118const char *
1119ba2bucket(struct bt_arg *ba, struct bt_arg *brange, struct dt_evt *dtev,
1120 long *pstep)
1121{
1122 static char buf[KLEN512];
1123 long val, bucket;
1124 int l;
1125
1126 val = ba2long(ba, dtev);
1127 if (brange == NULL((void *)0))
1128 bucket = next_pow2(val);
1129 else {
1130 long min, max, step;
1131
1132 assert(brange->ba_type == B_AT_LONG)((brange->ba_type == B_AT_LONG) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1132, __func__, "brange->ba_type == B_AT_LONG"))
;
1133 min = ba2long(brange, NULL((void *)0));
1134
1135 brange = SLIST_NEXT(brange, ba_next)((brange)->ba_next.sle_next);
1136 assert(brange->ba_type == B_AT_LONG)((brange->ba_type == B_AT_LONG) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1136, __func__, "brange->ba_type == B_AT_LONG"))
;
1137 max = ba2long(brange, NULL((void *)0));
1138
1139 if ((val < min) || (val > max))
1140 return NULL((void *)0);
1141
1142 brange = SLIST_NEXT(brange, ba_next)((brange)->ba_next.sle_next);
1143 assert(brange->ba_type == B_AT_LONG)((brange->ba_type == B_AT_LONG) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1143, __func__, "brange->ba_type == B_AT_LONG"))
;
1144 step = ba2long(brange, NULL((void *)0));
1145
1146 bucket = ((val / step) + 1) * step;
1147 *pstep = step;
1148 }
1149
1150 buf[0] = '\0';
1151 l = snprintf(buf, sizeof(buf), "%lu", bucket);
1152 if (l < 0 || (size_t)l > sizeof(buf)) {
1153 warn("string too long %d > %lu", l, sizeof(buf));
1154 return buf;
1155 }
1156
1157 return buf;
1158}
1159
1160/*
1161 * Evaluate the operation encoded in `ba' and return its result.
1162 */
1163long
1164baexpr2long(struct bt_arg *ba, struct dt_evt *dtev)
1165{
1166 static long recursions;
1167 struct bt_arg *lhs, *rhs;
1168 long lval, rval, result;
1169
1170 if (++recursions >= __MAXOPERANDS5)
7
Taking false branch
1171 errx(1, "too many operands (>%d) in expression", __MAXOPERANDS5);
1172
1173 lhs = ba->ba_value;
1174 rhs = SLIST_NEXT(lhs, ba_next)((lhs)->ba_next.sle_next);
1175
1176 lval = ba2long(lhs, dtev);
1177 if (rhs == NULL((void *)0)) {
8
Assuming 'rhs' is equal to NULL
9
Taking true branch
1178 rval = 0;
10
The value 0 is assigned to 'rval'
1179 } else {
1180 assert(SLIST_NEXT(rhs, ba_next) == NULL)((((rhs)->ba_next.sle_next) == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/btrace/btrace.c", 1180, __func__, "SLIST_NEXT(rhs, ba_next) == NULL"
))
;
1181 rval = ba2long(rhs, dtev);
1182 }
1183
1184 switch (ba->ba_type) {
11
Control jumps to 'case B_AT_OP_DIVIDE:' at line 1194
1185 case B_AT_OP_PLUS:
1186 result = lval + rval;
1187 break;
1188 case B_AT_OP_MINUS:
1189 result = lval - rval;
1190 break;
1191 case B_AT_OP_MULT:
1192 result = lval * rval;
1193 break;
1194 case B_AT_OP_DIVIDE:
1195 result = lval / rval;
12
Division by zero
1196 break;
1197 case B_AT_OP_BAND:
1198 result = lval & rval;
1199 break;
1200 case B_AT_OP_XOR:
1201 result = lval ^ rval;
1202 break;
1203 case B_AT_OP_BOR:
1204 result = lval | rval;
1205 break;
1206 case B_AT_OP_EQ:
1207 result = (lval == rval);
1208 break;
1209 case B_AT_OP_NE:
1210 result = (lval != rval);
1211 break;
1212 case B_AT_OP_LE:
1213 result = (lval <= rval);
1214 break;
1215 case B_AT_OP_LT:
1216 result = (lval < rval);
1217 break;
1218 case B_AT_OP_GE:
1219 result = (lval >= rval);
1220 break;
1221 case B_AT_OP_GT:
1222 result = (lval > rval);
1223 break;
1224 case B_AT_OP_LAND:
1225 result = (lval && rval);
1226 break;
1227 case B_AT_OP_LOR:
1228 result = (lval || rval);
1229 break;
1230 default:
1231 xabort("unsuported operation %d", ba->ba_type);
1232 }
1233
1234 debug("ba=%p eval '%ld %s %ld = %d'\n", ba, lval, ba_name(ba),
1235 rval, result);
1236
1237 --recursions;
1238
1239 return result;
1240}
1241
1242const char *
1243ba_name(struct bt_arg *ba)
1244{
1245 switch (ba->ba_type) {
1246 case B_AT_NIL:
1247 return "0";
1248 case B_AT_VAR:
1249 case B_AT_MAP:
1250 break;
1251 case B_AT_BI_PID:
1252 return "pid";
1253 case B_AT_BI_TID:
1254 return "tid";
1255 case B_AT_BI_COMM:
1256 return "comm";
1257 case B_AT_BI_CPU:
1258 return "cpu";
1259 case B_AT_BI_NSECS:
1260 return "nsecs";
1261 case B_AT_BI_KSTACK:
1262 return "kstack";
1263 case B_AT_BI_USTACK:
1264 return "ustack";
1265 case B_AT_BI_ARG0:
1266 return "arg0";
1267 case B_AT_BI_ARG1:
1268 return "arg1";
1269 case B_AT_BI_ARG2:
1270 return "arg2";
1271 case B_AT_BI_ARG3:
1272 return "arg3";
1273 case B_AT_BI_ARG4:
1274 return "arg4";
1275 case B_AT_BI_ARG5:
1276 return "arg5";
1277 case B_AT_BI_ARG6:
1278 return "arg6";
1279 case B_AT_BI_ARG7:
1280 return "arg7";
1281 case B_AT_BI_ARG8:
1282 return "arg8";
1283 case B_AT_BI_ARG9:
1284 return "arg9";
1285 case B_AT_BI_ARGS:
1286 return "args";
1287 case B_AT_BI_RETVAL:
1288 return "retval";
1289 case B_AT_BI_PROBE:
1290 return "probe";
1291 case B_AT_FN_STR:
1292 return "str";
1293 case B_AT_OP_PLUS:
1294 return "+";
1295 case B_AT_OP_MINUS:
1296 return "-";
1297 case B_AT_OP_MULT:
1298 return "*";
1299 case B_AT_OP_DIVIDE:
1300 return "/";
1301 case B_AT_OP_BAND:
1302 return "&";
1303 case B_AT_OP_XOR:
1304 return "^";
1305 case B_AT_OP_BOR:
1306 return "|";
1307 case B_AT_OP_EQ:
1308 return "==";
1309 case B_AT_OP_NE:
1310 return "!=";
1311 case B_AT_OP_LE:
1312 return "<=";
1313 case B_AT_OP_LT:
1314 return "<";
1315 case B_AT_OP_GE:
1316 return ">=";
1317 case B_AT_OP_GT:
1318 return ">";
1319 case B_AT_OP_LAND:
1320 return "&&";
1321 case B_AT_OP_LOR:
1322 return "||";
1323 default:
1324 xabort("unsuported type %d", ba->ba_type);
1325 }
1326
1327 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) ?
(void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c", 1327
, __func__, "ba->ba_type == B_AT_VAR || ba->ba_type == B_AT_MAP"
))
;
1328
1329 static char buf[64];
1330 size_t sz;
1331 int l;
1332
1333 buf[0] = '@';
1334 buf[1] = '\0';
1335 sz = sizeof(buf) - 1;
1336 l = snprintf(buf+1, sz, "%s", bv_name(ba->ba_value));
1337 if (l < 0 || (size_t)l > sz) {
1338 warn("string too long %d > %zu", l, sz);
1339 return buf;
1340 }
1341
1342 if (ba->ba_type == B_AT_MAP) {
1343 sz -= l;
1344 l = snprintf(buf+1+l, sz, "[%s]", ba_name(ba->ba_key));
1345 if (l < 0 || (size_t)l > sz) {
1346 warn("string too long %d > %zu", l, sz);
1347 return buf;
1348 }
1349 }
1350
1351 return buf;
1352}
1353
1354/*
1355 * Return the representation of `ba' as long.
1356 */
1357long
1358ba2long(struct bt_arg *ba, struct dt_evt *dtev)
1359{
1360 struct bt_var *bv;
1361 long val;
1362
1363 switch (ba->ba_type) {
5
Control jumps to 'case B_AT_OP_PLUS:' at line 1403
1364 case B_AT_LONG:
1365 val = (long)ba->ba_value;
1366 break;
1367 case B_AT_VAR:
1368 ba = ba_read(ba);
1369 val = (long)ba->ba_value;
1370 break;
1371 case B_AT_MAP:
1372 bv = ba->ba_value;
1373 /* Unitialized map */
1374 if (bv->bv_value == NULL((void *)0))
1375 return 0;
1376 val = ba2long(map_get((struct map *)bv->bv_value,
1377 ba2str(ba->ba_key, dtev)), dtev);
1378 break;
1379 case B_AT_NIL:
1380 val = 0L;
1381 break;
1382 case B_AT_BI_PID:
1383 val = dtev->dtev_pid;
1384 break;
1385 case B_AT_BI_TID:
1386 val = dtev->dtev_tid;
1387 break;
1388 case B_AT_BI_CPU:
1389 val = dtev->dtev_cpu;
1390 break;
1391 case B_AT_BI_NSECS:
1392 val = builtin_nsecs(dtev);
1393 break;
1394 case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
1395 val = dtev->dtev_args_args.E_entry[ba->ba_type - B_AT_BI_ARG0];
1396 break;
1397 case B_AT_BI_RETVAL:
1398 val = dtev->dtev_retval_args.E_return.__retval[0];
1399 break;
1400 case B_AT_BI_PROBE:
1401 val = dtev->dtev_pbn;
1402 break;
1403 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1404 val = baexpr2long(ba, dtev);
6
Calling 'baexpr2long'
1405 break;
1406 default:
1407 xabort("no long conversion for type %d", ba->ba_type);
1408 }
1409
1410 return val;
1411}
1412
1413/*
1414 * Return the representation of `ba' as string.
1415 */
1416const char *
1417ba2str(struct bt_arg *ba, struct dt_evt *dtev)
1418{
1419 static char buf[STRLEN64];
1420 struct bt_var *bv;
1421 struct dtioc_probe_info *dtpi;
1422 const char *str;
1423
1424 buf[0] = '\0';
1425 switch (ba->ba_type) {
1426 case B_AT_STR:
1427 str = (const char *)ba->ba_value;
1428 break;
1429 case B_AT_LONG:
1430 snprintf(buf, sizeof(buf), "%ld",(long)ba->ba_value);
1431 str = buf;
1432 break;
1433 case B_AT_NIL:
1434 str = "";
1435 break;
1436 case B_AT_BI_KSTACK:
1437 str = builtin_stack(dtev, 1);
1438 break;
1439 case B_AT_BI_USTACK:
1440 str = builtin_stack(dtev, 0);
1441 break;
1442 case B_AT_BI_COMM:
1443 str = dtev->dtev_comm;
1444 break;
1445 case B_AT_BI_CPU:
1446 snprintf(buf, sizeof(buf), "%u", dtev->dtev_cpu);
1447 str = buf;
1448 break;
1449 case B_AT_BI_PID:
1450 snprintf(buf, sizeof(buf), "%d", dtev->dtev_pid);
1451 str = buf;
1452 break;
1453 case B_AT_BI_TID:
1454 snprintf(buf, sizeof(buf), "%d", dtev->dtev_tid);
1455 str = buf;
1456 break;
1457 case B_AT_BI_NSECS:
1458 snprintf(buf, sizeof(buf), "%llu", builtin_nsecs(dtev));
1459 str = buf;
1460 break;
1461 case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
1462 str = builtin_arg(dtev, ba->ba_type);
1463 break;
1464 case B_AT_BI_RETVAL:
1465 snprintf(buf, sizeof(buf), "%ld", (long)dtev->dtev_retval_args.E_return.__retval[0]);
1466 str = buf;
1467 break;
1468 case B_AT_BI_PROBE:
1469 dtpi = dtpi_get_by_id(dtev->dtev_pbn);
1470 if (dtpi != NULL((void *)0))
1471 snprintf(buf, sizeof(buf), "%s:%s:%s",
1472 dtpi->dtpi_prov, dtpi_func(dtpi), dtpi->dtpi_name);
1473 else
1474 snprintf(buf, sizeof(buf), "%u", dtev->dtev_pbn);
1475 str = buf;
1476 break;
1477 case B_AT_MAP:
1478 bv = ba->ba_value;
1479 /* Unitialized map */
1480 if (bv->bv_value == NULL((void *)0)) {
1481 str = buf;
1482 break;
1483 }
1484 str = ba2str(map_get((struct map *)bv->bv_value,
1485 ba2str(ba->ba_key, dtev)), dtev);
1486 break;
1487 case B_AT_VAR:
1488 str = ba2str(ba_read(ba), dtev);
1489 break;
1490 case B_AT_FN_STR:
1491 str = (const char*)(fn_str(ba, dtev, buf))->ba_value;
1492 break;
1493 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1494 snprintf(buf, sizeof(buf), "%ld", ba2long(ba, dtev));
1495 str = buf;
1496 break;
1497 case B_AT_MF_COUNT:
1498 case B_AT_MF_MAX:
1499 case B_AT_MF_MIN:
1500 case B_AT_MF_SUM:
1501 assert(0)((0) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1501, __func__, "0"))
;
1502 break;
1503 default:
1504 xabort("no string conversion for type %d", ba->ba_type);
1505 }
1506
1507 return str;
1508}
1509
1510/*
1511 * Return dt(4) flags indicating which data should be recorded by the
1512 * kernel, if any, for a given `ba'.
1513 */
1514int
1515ba2dtflags(struct bt_arg *ba)
1516{
1517 struct bt_arg *bval;
1518 int flags = 0;
1519
1520 do {
1521 if (ba->ba_type == B_AT_MAP)
1522 bval = ba->ba_key;
1523 else
1524 bval = ba;
1525
1526 switch (bval->ba_type) {
1527 case B_AT_STR:
1528 case B_AT_LONG:
1529 case B_AT_VAR:
1530 case B_AT_HIST:
1531 case B_AT_NIL:
1532 break;
1533 case B_AT_BI_KSTACK:
1534 flags |= DTEVT_KSTACK(1 << 2);
1535 break;
1536 case B_AT_BI_USTACK:
1537 flags |= DTEVT_USTACK(1 << 1);
1538 break;
1539 case B_AT_BI_COMM:
1540 flags |= DTEVT_EXECNAME(1 << 0);
1541 break;
1542 case B_AT_BI_CPU:
1543 case B_AT_BI_PID:
1544 case B_AT_BI_TID:
1545 case B_AT_BI_NSECS:
1546 break;
1547 case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
1548 flags |= DTEVT_FUNCARGS(1 << 3);
1549 break;
1550 case B_AT_BI_RETVAL:
1551 case B_AT_BI_PROBE:
1552 break;
1553 case B_AT_MF_COUNT:
1554 case B_AT_MF_MAX:
1555 case B_AT_MF_MIN:
1556 case B_AT_MF_SUM:
1557 case B_AT_FN_STR:
1558 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1559 break;
1560 default:
1561 xabort("invalid argument type %d", bval->ba_type);
1562 }
1563 } while ((ba = SLIST_NEXT(ba, ba_next)((ba)->ba_next.sle_next)) != NULL((void *)0));
1564
1565 return flags;
1566}
1567
1568long
1569bacmp(struct bt_arg *a, struct bt_arg *b)
1570{
1571 assert(a->ba_type == b->ba_type)((a->ba_type == b->ba_type) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1571, __func__, "a->ba_type == b->ba_type"))
;
1572 assert(a->ba_type == B_AT_LONG)((a->ba_type == B_AT_LONG) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1572, __func__, "a->ba_type == B_AT_LONG"))
;
1573
1574 return ba2long(a, NULL((void *)0)) - ba2long(b, NULL((void *)0));
1575}
1576
1577__dead__attribute__((__noreturn__)) void
1578xabort(const char *fmt, ...)
1579{
1580 va_list ap;
1581
1582 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1583 vfprintf(stderr(&__sF[2]), fmt, ap);
1584 va_end(ap)__builtin_va_end(ap);
1585
1586 fprintf(stderr(&__sF[2]), "\n");
1587 abort();
1588}
1589
1590void
1591debug(const char *fmt, ...)
1592{
1593 va_list ap;
1594
1595 if (verbose < 2)
1596 return;
1597
1598 fprintf(stderr(&__sF[2]), "debug: ");
1599
1600 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1601 vfprintf(stderr(&__sF[2]), fmt, ap);
1602 va_end(ap)__builtin_va_end(ap);
1603}
1604
1605void
1606debugx(const char *fmt, ...)
1607{
1608 va_list ap;
1609
1610 if (verbose < 2)
1611 return;
1612
1613 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1614 vfprintf(stderr(&__sF[2]), fmt, ap);
1615 va_end(ap)__builtin_va_end(ap);
1616}
1617
1618void
1619debug_dump_term(struct bt_arg *ba)
1620{
1621 switch (ba->ba_type) {
1622 case B_AT_LONG:
1623 debugx("%s", ba2str(ba, NULL((void *)0)));
1624 break;
1625 case B_AT_OP_PLUS ... B_AT_OP_LOR:
1626 debug_dump_expr(ba);
1627 break;
1628 default:
1629 debugx("%s", ba_name(ba));
1630 }
1631}
1632
1633void
1634debug_dump_expr(struct bt_arg *ba)
1635{
1636 struct bt_arg *lhs, *rhs;
1637
1638 lhs = ba->ba_value;
1639 rhs = SLIST_NEXT(lhs, ba_next)((lhs)->ba_next.sle_next);
1640
1641 /* Left */
1642 debug_dump_term(lhs);
1643
1644 /* Right */
1645 if (rhs != NULL((void *)0)) {
1646 debugx(" %s ", ba_name(ba));
1647 debug_dump_term(rhs);
1648 } else {
1649 if (ba->ba_type != B_AT_OP_NE)
1650 debugx(" %s NULL", ba_name(ba));
1651 }
1652}
1653
1654void
1655debug_dump_filter(struct bt_rule *r)
1656{
1657 struct bt_stmt *bs;
1658
1659 if (verbose < 2)
1660 return;
1661
1662 if (r->br_filter == NULL((void *)0)) {
1663 debugx("\n");
1664 return;
1665 }
1666
1667 bs = r->br_filter->bf_condition;
1668
1669 debugx(" /");
1670 debug_dump_expr(SLIST_FIRST(&bs->bs_args)((&bs->bs_args)->slh_first));
1671 debugx("/\n");
1672}
1673
1674const char *
1675debug_probe_name(struct bt_probe *bp)
1676{
1677 static char buf[64];
1678
1679 if (verbose < 2)
1680 return "";
1681
1682 if (bp->bp_type == B_PT_BEGIN)
1683 return "BEGIN";
1684
1685 if (bp->bp_type == B_PT_END)
1686 return "END";
1687
1688 assert(bp->bp_type == B_PT_PROBE)((bp->bp_type == B_PT_PROBE) ? (void)0 : __assert2("/usr/src/usr.sbin/btrace/btrace.c"
, 1688, __func__, "bp->bp_type == B_PT_PROBE"))
;
1689
1690 if (bp->bp_rate) {
1691 snprintf(buf, sizeof(buf), "%s:%s:%u", bp->bp_prov,
1692 bp->bp_unitbp_func, bp->bp_rate);
1693 } else {
1694 snprintf(buf, sizeof(buf), "%s:%s:%s", bp->bp_prov,
1695 bp->bp_unitbp_func, bp->bp_name);
1696 }
1697
1698 return buf;
1699}