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