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