xref: /openbsd-src/usr.sbin/btrace/btrace.c (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
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.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 
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 == EINTR && 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, &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 
427 void
428 rules_setup(int fd)
429 {
430 	struct dtioc_probe_info *dtpi;
431 	struct dtioc_req *dtrq;
432 	struct bt_rule *r, *rbegin = NULL;
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) {
439 		evtflags = 0;
440 		SLIST_FOREACH(bs, &r->br_action, bs_next) {
441 			struct bt_arg *ba;
442 
443 			SLIST_FOREACH(ba, &bs->bs_args, ba_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) {
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) {
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)
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)
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_REALTIME, &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) {
505 		SLIST_FOREACH(bp, &r->br_probes, bp_next) {
506 			if (bp->bp_type != B_PT_PROBE)
507 				continue;
508 
509 			dtrq = bp->bp_cookie;
510 			if (ioctl(fd, DTIOCPRBENABLE, dtrq))
511 				err(1, "DTIOCPRBENABLE");
512 		}
513 	}
514 
515 	if (g_nprobes > 0) {
516 		if (ioctl(fd, DTIOCRECORD, &on))
517 			err(1, "DTIOCRECORD");
518 	}
519 }
520 
521 void
522 rules_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) {
528 		SLIST_FOREACH(bp, &r->br_probes, bp_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 
538 void
539 rules_teardown(int fd)
540 {
541 	struct dtioc_req *dtrq;
542 	struct bt_probe *bp;
543 	struct bt_rule *r, *rend = NULL;
544 	int dokstack = 0, off = 0;
545 
546 	if (g_nprobes > 0) {
547 		if (ioctl(fd, DTIOCRECORD, &off))
548 			err(1, "DTIOCRECORD");
549 	}
550 
551 	TAILQ_FOREACH(r, &g_rules, br_next) {
552 		SLIST_FOREACH(bp, &r->br_probes, bp_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, dtrq))
561 				err(1, "DTIOCPRBDISABLE");
562 			if (dtrq->dtrq_evtflags & DTEVT_KSTACK)
563 				dokstack = 1;
564 		}
565 	}
566 
567 	if (dokstack)
568 		kelf_close();
569 
570 	/* Update "fake" event for BEGIN/END */
571 	clock_gettime(CLOCK_REALTIME, &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)
578 		rule_printmaps(r);
579 }
580 
581 void
582 rule_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) {
588 		debug("eval rule '%s'", debug_probe_name(bp));
589 		debug_dump_filter(r);
590 	}
591 
592 	if (r->br_filter != NULL && r->br_filter->bf_condition != NULL) {
593 		if (stmt_test(r->br_filter->bf_condition, dtev) == false) {
594 			bt_filtered++;
595 			return;
596 		}
597 	}
598 
599 	SLIST_FOREACH(bs, &r->br_action, bs_next) {
600 		if ((bs->bs_act == B_AC_TEST) && stmt_test(bs, dtev) == true)
601 			stmt_eval((struct bt_stmt *)bs->bs_var, dtev);
602 
603 		stmt_eval(bs, dtev);
604 	}
605 }
606 
607 void
608 rule_printmaps(struct bt_rule *r)
609 {
610 	struct bt_stmt *bs;
611 
612 	SLIST_FOREACH(bs, &r->br_action, bs_next) {
613 		struct bt_arg *ba;
614 
615 		SLIST_FOREACH(ba, &bs->bs_args, ba_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)
624 				continue;
625 
626 			if (ba->ba_type == B_AT_MAP)
627 				map_print(map, SIZE_T_MAX, bv_name(bv));
628 			else
629 				hist_print((struct hist *)map, bv_name(bv));
630 			map_clear(map);
631 			bv->bv_value = NULL;
632 		}
633 	}
634 }
635 
636 time_t
637 builtin_gettime(struct dt_evt *dtev)
638 {
639 	struct timespec ts;
640 
641 	if (dtev == NULL) {
642 		clock_gettime(CLOCK_REALTIME, &ts);
643 		return ts.tv_sec;
644 	}
645 
646 	return dtev->dtev_tsp.tv_sec;
647 }
648 
649 static inline uint64_t
650 TIMESPEC_TO_NSEC(struct timespec *ts)
651 {
652 	return (ts->tv_sec * 1000000000L + ts->tv_nsec);
653 }
654 
655 uint64_t
656 builtin_nsecs(struct dt_evt *dtev)
657 {
658 	struct timespec ts;
659 
660 	if (dtev == NULL) {
661 		clock_gettime(CLOCK_REALTIME, &ts);
662 		return TIMESPEC_TO_NSEC(&ts);
663 	}
664 
665 	return TIMESPEC_TO_NSEC(&dtev->dtev_tsp);
666 }
667 
668 const char *
669 builtin_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 
703 const char *
704 builtin_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[dat - B_AT_BI_ARG0]);
710 
711 	return buf;
712 }
713 
714 void
715 stmt_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  */
761 void
762 stmt_bucketize(struct bt_stmt *bs, struct dt_evt *dtev)
763 {
764 	struct bt_arg *brange, *bhist = SLIST_FIRST(&bs->bs_args);
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);
771 	assert(SLIST_NEXT(bval, ba_next) == NULL);
772 
773 	brange = bhist->ba_key;
774 	bucket = ba2bucket(bval, brange, dtev, &step);
775 	if (bucket == NULL) {
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  */
792 void
793 stmt_clear(struct bt_stmt *bs)
794 {
795 	struct bt_arg *ba = SLIST_FIRST(&bs->bs_args);
796 	struct bt_var *bv = ba->ba_value;
797 	struct map *map;
798 
799 	assert(bs->bs_var == NULL);
800 	assert(ba->ba_type == B_AT_VAR);
801 
802 	map = (struct map *)bv->bv_value;
803 	if (map == NULL)
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;
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  */
820 void
821 stmt_delete(struct bt_stmt *bs, struct dt_evt *dtev)
822 {
823 	struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args);
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);
829 	assert(bs->bs_var == NULL);
830 
831 	map = (struct map *)bv->bv_value;
832 	if (map == NULL)
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  */
848 void
849 stmt_insert(struct bt_stmt *bs, struct dt_evt *dtev)
850 {
851 	struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args);
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);
858 	assert(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  */
880 void
881 stmt_print(struct bt_stmt *bs, struct dt_evt *dtev)
882 {
883 	struct bt_arg *btop, *ba = SLIST_FIRST(&bs->bs_args);
884 	struct bt_var *bv = ba->ba_value;
885 	struct map *map;
886 	size_t top = SIZE_T_MAX;
887 
888 	assert(bs->bs_var == NULL);
889 
890 	/* Parse optional `top' argument. */
891 	btop = SLIST_NEXT(ba, ba_next);
892 	if (btop != NULL) {
893 		assert(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);
900 		printf("%s\n", ba2str(ba, dtev));
901 		return;
902 	}
903 
904 	map = (struct map *)bv->bv_value;
905 	if (map == NULL)
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  */
927 void
928 stmt_store(struct bt_stmt *bs, struct dt_evt *dtev)
929 {
930 	struct bt_arg *ba = SLIST_FIRST(&bs->bs_args);
931 	struct bt_var *bv = bs->bs_var;
932 
933 	assert(SLIST_NEXT(ba, ba_next) == NULL);
934 
935 	switch (ba->ba_type) {
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);
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);
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);
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  */
969 struct bt_arg *
970 fn_str(struct bt_arg *ba, struct dt_evt *dtev, char *buf)
971 {
972 	struct bt_arg *arg, *index;
973 	ssize_t len = STRLEN;
974 
975 	assert(ba->ba_type == B_AT_FN_STR);
976 
977 	arg = (struct bt_arg*)ba->ba_value;
978 	assert(arg != NULL);
979 
980 	index = SLIST_NEXT(arg, ba_next);
981 	if (index != NULL) {
982 		/* Should have only 1 optional argument. */
983 		assert(SLIST_NEXT(index, ba_next) == NULL);
984 		len = MINIMUM(ba2long(index, dtev) + 1, STRLEN);
985 	}
986 
987 	/* All negative lengths behave the same as a zero length. */
988 	if (len < 1)
989 		return ba_new("", B_AT_STR);
990 
991 	strlcpy(buf, ba2str(arg, dtev), len);
992 	return ba_new(buf, B_AT_STR);
993 }
994 
995 /*
996  * Expression test:	{ if (expr) stmt; }
997  */
998 bool
999 stmt_test(struct bt_stmt *bs, struct dt_evt *dtev)
1000 {
1001 	struct bt_arg *ba;
1002 
1003 	if (bs == NULL)
1004 		return true;
1005 
1006 	ba = SLIST_FIRST(&bs->bs_args);
1007 
1008 	return baexpr2long(ba, dtev) != 0;
1009 }
1010 
1011 /*
1012  * Print time: 		{ time("%H:%M:%S"); }
1013  */
1014 void
1015 stmt_time(struct bt_stmt *bs, struct dt_evt *dtev)
1016 {
1017 	struct bt_arg *ba = SLIST_FIRST(&bs->bs_args);
1018 	time_t time;
1019 	struct tm *tm;
1020 	char buf[64];
1021 
1022 	assert(bs->bs_var == NULL);
1023 	assert(ba->ba_type == B_AT_STR);
1024 	assert(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  */
1035 void
1036 stmt_zero(struct bt_stmt *bs)
1037 {
1038 	struct bt_arg *ba = SLIST_FIRST(&bs->bs_args);
1039 	struct bt_var *bv = ba->ba_value;
1040 	struct map *map;
1041 
1042 	assert(bs->bs_var == NULL);
1043 	assert(ba->ba_type == B_AT_VAR);
1044 
1045 	map = (struct map *)bv->bv_value;
1046 	if (map == NULL)
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 
1057 struct bt_arg *
1058 ba_read(struct bt_arg *ba)
1059 {
1060 	struct bt_var *bv = ba->ba_value;
1061 
1062 	assert(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)
1068 		return &g_nullba;
1069 
1070 	return bv->bv_value;
1071 }
1072 
1073 const char *
1074 ba2hash(struct bt_arg *ba, struct dt_evt *dtev)
1075 {
1076 	static char buf[KLEN];
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)) != NULL) {
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 
1102 static unsigned long
1103 next_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  */
1118 const char *
1119 ba2bucket(struct bt_arg *ba, struct bt_arg *brange, struct dt_evt *dtev,
1120     long *pstep)
1121 {
1122 	static char buf[KLEN];
1123 	long val, bucket;
1124 	int l;
1125 
1126 	val = ba2long(ba, dtev);
1127 	if (brange == NULL)
1128 		bucket = next_pow2(val);
1129 	else {
1130 		long min, max, step;
1131 
1132 		assert(brange->ba_type == B_AT_LONG);
1133 		min = ba2long(brange, NULL);
1134 
1135 		brange = SLIST_NEXT(brange, ba_next);
1136 		assert(brange->ba_type == B_AT_LONG);
1137 		max = ba2long(brange, NULL);
1138 
1139 		if ((val < min) || (val > max))
1140 			return NULL;
1141 
1142 		brange = SLIST_NEXT(brange, ba_next);
1143 		assert(brange->ba_type == B_AT_LONG);
1144 		step = ba2long(brange, NULL);
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  */
1163 long
1164 baexpr2long(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 >= __MAXOPERANDS)
1171 		errx(1, "too many operands (>%d) in expression", __MAXOPERANDS);
1172 
1173 	lhs = ba->ba_value;
1174 	rhs = SLIST_NEXT(lhs, ba_next);
1175 
1176 	lval = ba2long(lhs, dtev);
1177 	if (rhs == NULL) {
1178 		rval = 0;
1179 	} else {
1180 		assert(SLIST_NEXT(rhs, ba_next) == NULL);
1181 		rval = ba2long(rhs, dtev);
1182 	}
1183 
1184 	switch (ba->ba_type) {
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;
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 
1242 const char *
1243 ba_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);
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  */
1357 long
1358 ba2long(struct bt_arg *ba, struct dt_evt *dtev)
1359 {
1360 	struct bt_var *bv;
1361 	long val;
1362 
1363 	switch (ba->ba_type) {
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)
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[ba->ba_type - B_AT_BI_ARG0];
1396 		break;
1397 	case B_AT_BI_RETVAL:
1398 		val = dtev->dtev_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);
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  */
1416 const char *
1417 ba2str(struct bt_arg *ba, struct dt_evt *dtev)
1418 {
1419 	static char buf[STRLEN];
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[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)
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) {
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);
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  */
1514 int
1515 ba2dtflags(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;
1535 			break;
1536 		case B_AT_BI_USTACK:
1537 			flags |= DTEVT_USTACK;
1538 			break;
1539 		case B_AT_BI_COMM:
1540 			flags |= DTEVT_EXECNAME;
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;
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)) != NULL);
1564 
1565 	return flags;
1566 }
1567 
1568 long
1569 bacmp(struct bt_arg *a, struct bt_arg *b)
1570 {
1571 	assert(a->ba_type == b->ba_type);
1572 	assert(a->ba_type == B_AT_LONG);
1573 
1574 	return ba2long(a, NULL) - ba2long(b, NULL);
1575 }
1576 
1577 __dead void
1578 xabort(const char *fmt, ...)
1579 {
1580 	va_list ap;
1581 
1582 	va_start(ap, fmt);
1583 	vfprintf(stderr, fmt, ap);
1584 	va_end(ap);
1585 
1586 	fprintf(stderr, "\n");
1587 	abort();
1588 }
1589 
1590 void
1591 debug(const char *fmt, ...)
1592 {
1593 	va_list ap;
1594 
1595 	if (verbose < 2)
1596 		return;
1597 
1598 	fprintf(stderr, "debug: ");
1599 
1600 	va_start(ap, fmt);
1601 	vfprintf(stderr, fmt, ap);
1602 	va_end(ap);
1603 }
1604 
1605 void
1606 debugx(const char *fmt, ...)
1607 {
1608 	va_list ap;
1609 
1610 	if (verbose < 2)
1611 		return;
1612 
1613 	va_start(ap, fmt);
1614 	vfprintf(stderr, fmt, ap);
1615 	va_end(ap);
1616 }
1617 
1618 void
1619 debug_dump_term(struct bt_arg *ba)
1620 {
1621 	switch (ba->ba_type) {
1622 	case B_AT_LONG:
1623 		debugx("%s", ba2str(ba, NULL));
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 
1633 void
1634 debug_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);
1640 
1641 	/* Left */
1642 	debug_dump_term(lhs);
1643 
1644 	/* Right */
1645 	if (rhs != NULL) {
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 
1654 void
1655 debug_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) {
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));
1671 	debugx("/\n");
1672 }
1673 
1674 const char *
1675 debug_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);
1689 
1690 	if (bp->bp_rate) {
1691 		snprintf(buf, sizeof(buf), "%s:%s:%u", bp->bp_prov,
1692 		    bp->bp_unit, bp->bp_rate);
1693 	} else {
1694 		snprintf(buf, sizeof(buf), "%s:%s:%s", bp->bp_prov,
1695 		    bp->bp_unit, bp->bp_name);
1696 	}
1697 
1698 	return buf;
1699 }
1700