xref: /openbsd-src/usr.sbin/btrace/btrace.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: btrace.c,v 1.4 2020/01/28 16:39:51 mpi Exp $ */
2 
3 /*
4  * Copyright (c) 2019 - 2020 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/syscall.h>
22 #include <sys/queue.h>
23 
24 #include <assert.h>
25 #include <err.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <limits.h>
29 #include <locale.h>
30 #include <signal.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37 
38 #include <dev/dt/dtvar.h>
39 
40 #include "btrace.h"
41 #include "bt_parser.h"
42 
43 /*
44  * Maximum number of operands an arithmetic operation can have.  This
45  * is necessary to stop infinite recursion when evaluating expressions.
46  */
47 #define __MAXOPERANDS	5
48 
49 #define __PATH_DEVDT "/dev/dt"
50 
51 __dead void		 usage(void);
52 char			*read_btfile(const char *);
53 
54 /*
55  * Retrieve & parse probe information.
56  */
57 void			 dtpi_cache(int);
58 void			 dtpi_print_list(void);
59 char			*dtpi_func(struct dtioc_probe_info *);
60 int			 dtpi_is_unit(const char *);
61 struct dtioc_probe_info	*dtpi_get_by_value(const char *, const char *,
62 			     const char *);
63 
64 /*
65  * Main loop and rule evaluation.
66  */
67 void			 rules_do(int);
68 void			 rules_setup(int);
69 void			 rules_apply(struct dt_evt *);
70 void			 rules_teardown(int);
71 void			 rule_eval(struct bt_rule *, struct dt_evt *);
72 
73 /*
74  * Language builtins & functions.
75  */
76 uint64_t		 builtin_nsecs(struct dt_evt *);
77 const char		*builtin_kstack(struct dt_evt *);
78 const char		*builtin_arg(struct dt_evt *, enum bt_argtype);
79 void			 stmt_clear(struct bt_stmt *);
80 void			 stmt_delete(struct bt_stmt *, struct dt_evt *);
81 void			 stmt_insert(struct bt_stmt *, struct dt_evt *);
82 void			 stmt_print(struct bt_stmt *, struct dt_evt *);
83 void			 stmt_store(struct bt_stmt *, struct dt_evt *);
84 void			 stmt_time(struct bt_stmt *, struct dt_evt *);
85 void			 stmt_zero(struct bt_stmt *);
86 struct bt_arg		*ba_read(struct bt_arg *);
87 
88 /* FIXME: use a real hash. */
89 #define ba2hash(_b, _e)	ba2str((_b), (_e))
90 
91 /*
92  * Debug routines.
93  */
94 __dead void		 xabort(const char *, ...);
95 void			 debug(const char *, ...);
96 void			 debugx(const char *, ...);
97 const char		*debug_rule_name(struct bt_rule *);
98 void			 debug_dump_filter(struct bt_rule *);
99 void			 debug_dump_rule(struct bt_rule *);
100 
101 struct dtioc_probe_info	*dt_dtpis;	/* array of available probes */
102 size_t			 dt_ndtpi;	/* # of elements in the array */
103 
104 int			 verbose = 0;
105 volatile sig_atomic_t	 quit_pending;
106 
107 static void
108 signal_handler(int sig)
109 {
110 	quit_pending = sig;
111 }
112 
113 
114 int
115 main(int argc, char *argv[])
116 {
117 	int fd = -1, ch, error = 0;
118 	const char *filename = NULL, *btscript = NULL;
119 	int showprobes = 0;
120 
121 	setlocale(LC_ALL, "");
122 
123 #if notyet
124 	if (pledge("stdio rpath", NULL) == -1)
125 		err(1, "pledge");
126 #endif
127 
128 	while ((ch = getopt(argc, argv, "e:lv")) != -1) {
129 		switch (ch) {
130 		case 'e':
131 			btscript = optarg;
132 			break;
133 		case 'l':
134 			showprobes = 1;
135 			break;
136 		case 'v':
137 			verbose++;
138 			break;
139 		default:
140 			usage();
141 		}
142 	}
143 
144 	argc -= optind;
145 	argv += optind;
146 
147 	if (argc > 0) {
148 		if (btscript != NULL)
149 			usage();
150 
151 		filename = argv[0];
152 		btscript = read_btfile(filename);
153 		argc--;
154 		argv++;
155 	}
156 
157 	if (argc != 0 || (btscript == NULL && !showprobes))
158 		usage();
159 
160 	if (btscript != NULL) {
161 		error = btparse(btscript, strlen(btscript), filename, 1);
162 		if (error)
163 			return error;
164 	}
165 
166 	if (showprobes || g_nprobes > 0) {
167 		fd = open(__PATH_DEVDT, O_RDONLY);
168 		if (fd == -1)
169 			err(1, "could not open %s", __PATH_DEVDT);
170 	}
171 
172 	if (showprobes) {
173 		dtpi_cache(fd);
174 		dtpi_print_list();
175 	}
176 
177 	if (!TAILQ_EMPTY(&g_rules))
178 		rules_do(fd);
179 
180 	if (fd != -1)
181 		close(fd);
182 
183 	return error;
184 }
185 
186 __dead void
187 usage(void)
188 {
189 	fprintf(stderr, "usage: %s [-lv] [-e program|file]\n",
190 	    getprogname());
191 	exit(1);
192 }
193 
194 char *
195 read_btfile(const char *filename)
196 {
197 	static char fcontent[BUFSIZ];
198 	long offset;
199 	FILE *fp;
200 
201 	fp = fopen(filename, "r");
202 	if (fp == NULL)
203 		err(1, "can't open '%s'", filename);
204 
205 	if (fread(fcontent, sizeof(fcontent) - 1, 1, fp) == 0 && errno != 0)
206 		err(1, "can't read '%s'", filename);
207 
208 	fseek(fp, 0, SEEK_END);
209 	offset = ftell(fp);
210 	if ((size_t)offset >= sizeof(fcontent))
211 		errx(1, "couldn't read all of '%s'", filename);
212 
213 	fclose(fp);
214 	return fcontent;
215 }
216 
217 void
218 dtpi_cache(int fd)
219 {
220 	struct dtioc_probe dtpr;
221 
222 	if (dt_dtpis != NULL)
223 		return;
224 
225 	memset(&dtpr, 0, sizeof(dtpr));
226 	if (ioctl(fd, DTIOCGPLIST, &dtpr))
227 		err(1, "DTIOCGPLIST");
228 
229 	dt_ndtpi = (dtpr.dtpr_size / sizeof(*dt_dtpis));
230 	dt_dtpis = reallocarray(NULL, dt_ndtpi, sizeof(*dt_dtpis));
231 	if (dt_dtpis == NULL)
232 		err(1, "malloc");
233 
234 	dtpr.dtpr_probes = dt_dtpis;
235 	if (ioctl(fd, DTIOCGPLIST, &dtpr))
236 		err(1, "DTIOCGPLIST");
237 }
238 
239 void
240 dtpi_print_list(void)
241 {
242 	struct dtioc_probe_info *dtpi;
243 	size_t i;
244 
245 	dtpi = dt_dtpis;
246 	for (i = 0; i < dt_ndtpi; i++, dtpi++) {
247 		printf("%s:%s:%s\n", dtpi->dtpi_prov, dtpi_func(dtpi),
248 		    dtpi->dtpi_name);
249 	}
250 }
251 
252 char *
253 dtpi_func(struct dtioc_probe_info *dtpi)
254 {
255 	char *sysnb, func[DTNAMESIZE];
256 	const char *errstr;
257 	int idx;
258 
259 	if (strncmp(dtpi->dtpi_prov, "syscall", DTNAMESIZE))
260 		return dtpi->dtpi_func;
261 
262 	/* Translate syscall names */
263 	strlcpy(func, dtpi->dtpi_func, sizeof(func));
264 	sysnb = func;
265 	if (strsep(&sysnb, "%") == NULL)
266 		return dtpi->dtpi_func;
267 
268 	idx = strtonum(sysnb, 1, SYS_MAXSYSCALL, &errstr);
269 	if (errstr != NULL)
270 		return dtpi->dtpi_func;
271 
272 	return syscallnames[idx];
273 }
274 
275 int
276 dtpi_is_unit(const char *unit)
277 {
278 	return !strncmp("hz", unit, sizeof("hz"));
279 }
280 
281 struct dtioc_probe_info *
282 dtpi_get_by_value(const char *prov, const char *func, const char *name)
283 {
284 	struct dtioc_probe_info *dtpi;
285 	size_t i;
286 
287 	dtpi = dt_dtpis;
288 	for (i = 0; i < dt_ndtpi; i++, dtpi++) {
289 		if (prov != NULL &&
290 		    strncmp(prov, dtpi->dtpi_prov, DTNAMESIZE))
291 			continue;
292 
293 		if (func != NULL) {
294 			if (dtpi_is_unit(func))
295 				return dtpi;
296 
297 			if (strncmp(func, dtpi_func(dtpi), DTNAMESIZE))
298 				continue;
299 		}
300 
301 		if (strncmp(name, dtpi->dtpi_name, DTNAMESIZE))
302 			continue;
303 
304 		debug("matched probe %s:%s:%s\n", dtpi->dtpi_prov,
305 		    dtpi_func(dtpi), dtpi->dtpi_name);
306 		return dtpi;
307 	}
308 
309 	return NULL;
310 }
311 
312 void
313 rules_do(int fd)
314 {
315 	struct sigaction sa;
316 
317 	memset(&sa, 0, sizeof(sa));
318 	sigemptyset(&sa.sa_mask);
319 	sa.sa_flags = 0;
320 	sa.sa_handler = signal_handler;
321 	if (sigaction(SIGINT, &sa, NULL))
322 		err(1, "sigaction");
323 
324 	rules_setup(fd);
325 
326 	while (!quit_pending && g_nprobes > 0) {
327 		static struct dt_evt devtbuf[64];
328 		ssize_t rlen;
329 		size_t i;
330 
331 		rlen = read(fd, devtbuf, sizeof(devtbuf) - 1);
332 		if (rlen == -1) {
333 			if (errno == EINTR && quit_pending)
334 				break;
335 			err(1, "read");
336 		}
337 
338 		if ((rlen % sizeof(struct dt_evt)) != 0)
339 			err(1, "incorrect read");
340 
341 
342 		for (i = 0; i < nitems(devtbuf); i++) {
343 			struct dt_evt *dtev = &devtbuf[i];
344 
345 			if (dtev->dtev_tid == 0)
346 				break;
347 
348 			rules_apply(dtev);
349 		}
350 	}
351 
352 	rules_teardown(fd);
353 
354 	if (verbose && fd != -1) {
355 		struct dtioc_stat dtst;
356 
357 		memset(&dtst, 0, sizeof(dtst));
358 		if (ioctl(fd, DTIOCGSTATS, &dtst))
359 			warn("DTIOCGSTATS");
360 
361 		printf("%llu events read\n", dtst.dtst_readevt);
362 		printf("%llu events dropped\n", dtst.dtst_dropevt);
363 	}
364 }
365 
366 static inline enum dt_operand
367 dop2dt(enum bt_operand op)
368 {
369 	switch (op) {
370 	case B_OP_EQ:	return DT_OP_EQ;
371 	case B_OP_NE:	return DT_OP_NE;
372 	case B_OP_NONE:	return DT_OP_NONE;
373 	default:	break;
374 	}
375 	xabort("unknown operand %d", op);
376 }
377 
378 
379 static inline enum dt_filtervar
380 dvar2dt(enum bt_filtervar var)
381 {
382 	switch (var) {
383 	case B_FV_PID:	return DT_FV_PID;
384 	case B_FV_TID:	return DT_FV_TID;
385 	case B_FV_NONE:	return DT_FV_NONE;
386 	default:	break;
387 	}
388 	xabort("unknown filter %d", var);
389 }
390 
391 
392 void
393 rules_setup(int fd)
394 {
395 	struct dtioc_probe_info *dtpi;
396 	struct dtioc_req *dtrq;
397 	struct bt_rule *r, *rbegin = NULL;
398 	struct bt_probe *bp;
399 	struct bt_stmt *bs;
400 	int dokstack = 0, on = 1;
401 
402 	TAILQ_FOREACH(r, &g_rules, br_next) {
403 		debug_dump_rule(r);
404 
405 		if (r->br_type != B_RT_PROBE) {
406 			if (r->br_type == B_RT_BEGIN)
407 				rbegin = r;
408 			continue;
409 		}
410 
411 		bp = r->br_probe;
412 		dtpi_cache(fd);
413 		dtpi = dtpi_get_by_value(bp->bp_prov, bp->bp_func, bp->bp_name);
414 		if (dtpi == NULL)
415 			errx(1, "probe not found");
416 
417 		dtrq = calloc(1, sizeof(*dtrq));
418 		if (dtrq == NULL)
419 			err(1, "dtrq: 1alloc");
420 
421 		r->br_pbn = dtpi->dtpi_pbn;
422 		dtrq->dtrq_pbn = dtpi->dtpi_pbn;
423 		if (r->br_filter) {
424 			struct bt_filter *df = r->br_filter;
425 
426 			dtrq->dtrq_filter.dtf_operand = dop2dt(df->bf_op);
427 			dtrq->dtrq_filter.dtf_variable = dvar2dt(df->bf_var);
428 			dtrq->dtrq_filter.dtf_value = df->bf_val;
429 		}
430 		dtrq->dtrq_rate = r->br_probe->bp_rate;
431 
432 		SLIST_FOREACH(bs, &r->br_action, bs_next) {
433 			struct bt_arg *ba;
434 
435 			SLIST_FOREACH(ba, &bs->bs_args, ba_next) {
436 				switch (ba->ba_type) {
437 				case B_AT_STR:
438 				case B_AT_LONG:
439 				case B_AT_VAR:
440 					break;
441 				case B_AT_BI_KSTACK:
442 					dtrq->dtrq_evtflags |= DTEVT_KSTACK;
443 					dokstack = 1;
444 					break;
445 				case B_AT_BI_USTACK:
446 					dtrq->dtrq_evtflags |= DTEVT_USTACK;
447 					break;
448 				case B_AT_BI_COMM:
449 					dtrq->dtrq_evtflags |= DTEVT_EXECNAME;
450 					break;
451 				case B_AT_BI_PID:
452 				case B_AT_BI_TID:
453 				case B_AT_BI_NSECS:
454 					break;
455 				case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
456 					dtrq->dtrq_evtflags |= DTEVT_FUNCARGS;
457 					break;
458 				case B_AT_BI_RETVAL:
459 					dtrq->dtrq_evtflags |= DTEVT_RETVAL;
460 					break;
461 				case B_AT_MF_COUNT:
462 				case B_AT_MF_MAX:
463 				case B_AT_MF_MIN:
464 				case B_AT_MF_SUM:
465 				case B_AT_OP_ADD ... B_AT_OP_DIVIDE:
466 					break;
467 				default:
468 					xabort("invalid argument type %d",
469 					    ba->ba_type);
470 				}
471 			}
472 		}
473 
474 		r->br_cookie = dtrq;
475 	}
476 
477 	if (dokstack)
478 		kelf_open();
479 
480 	if (rbegin)
481 		rule_eval(rbegin, NULL);
482 
483 	/* Enable all probes */
484 	TAILQ_FOREACH(r, &g_rules, br_next) {
485 		if (r->br_type != B_RT_PROBE)
486 			continue;
487 
488 		dtrq = r->br_cookie;
489 		if (ioctl(fd, DTIOCPRBENABLE, dtrq))
490 			err(1, "DTIOCPRBENABLE");
491 	}
492 
493 	if (g_nprobes > 0) {
494 		if (ioctl(fd, DTIOCRECORD, &on))
495 			err(1, "DTIOCRECORD");
496 	}
497 }
498 
499 void
500 rules_apply(struct dt_evt *dtev)
501 {
502 	struct bt_rule *r;
503 
504 	TAILQ_FOREACH(r, &g_rules, br_next) {
505 		if (r->br_type != B_RT_PROBE || r->br_pbn != dtev->dtev_pbn)
506 			continue;
507 
508 		rule_eval(r, dtev);
509 	}
510 }
511 
512 void
513 rules_teardown(int fd)
514 {
515 	struct dtioc_req *dtrq;
516 	struct bt_rule *r, *rend = NULL;
517 	int dokstack = 0, off = 0;
518 
519 	if (g_nprobes > 0) {
520 		if (ioctl(fd, DTIOCRECORD, &off))
521 			err(1, "DTIOCRECORD");
522 	}
523 
524 	TAILQ_FOREACH(r, &g_rules, br_next) {
525 		if (r->br_type != B_RT_PROBE) {
526 			if (r->br_type == B_RT_END)
527 				rend = r;
528 			continue;
529 		}
530 
531 		dtrq = r->br_cookie;
532 		if (dtrq->dtrq_evtflags & DTEVT_KSTACK)
533 			dokstack = 1;
534 	}
535 
536 	if (dokstack)
537 		kelf_close();
538 
539 	if (rend)
540 		rule_eval(rend, NULL);
541 }
542 
543 void
544 rule_eval(struct bt_rule *r, struct dt_evt *dtev)
545 {
546 	struct bt_stmt *bs;
547 
548 	debug("eval rule '%s'\n", debug_rule_name(r));
549 
550 	SLIST_FOREACH(bs, &r->br_action, bs_next) {
551 		switch (bs->bs_act) {
552 		case B_AC_STORE:
553 			stmt_store(bs, dtev);
554 			break;
555 		case B_AC_INSERT:
556 			stmt_insert(bs, dtev);
557 			break;
558 		case B_AC_CLEAR:
559 			stmt_clear(bs);
560 			break;
561 		case B_AC_DELETE:
562 			stmt_delete(bs, dtev);
563 			break;
564 		case B_AC_EXIT:
565 			exit(0);
566 			break;
567 		case B_AC_PRINT:
568 			stmt_print(bs, dtev);
569 			break;
570 		case B_AC_PRINTF:
571 			stmt_printf(bs, dtev);
572 			break;
573 		case B_AC_TIME:
574 			stmt_time(bs, dtev);
575 			break;
576 		case B_AC_ZERO:
577 			stmt_zero(bs);
578 			break;
579 		default:
580 			xabort("no handler for action type %d", bs->bs_act);
581 		}
582 	}
583 }
584 
585 time_t
586 builtin_gettime(struct dt_evt *dtev)
587 {
588 	struct timespec ts;
589 
590 	if (dtev == NULL) {
591 		clock_gettime(CLOCK_REALTIME, &ts);
592 		return ts.tv_sec;
593 	}
594 
595 	return dtev->dtev_tsp.tv_sec;
596 }
597 
598 static inline uint64_t
599 TIMESPEC_TO_NSEC(struct timespec *ts)
600 {
601 	return (ts->tv_sec * 1000000000L + ts->tv_nsec);
602 }
603 
604 uint64_t
605 builtin_nsecs(struct dt_evt *dtev)
606 {
607 	uint64_t nsecs;
608 
609 	if (dtev == NULL) {
610 		struct timeval tv;
611 
612 		gettimeofday(&tv, NULL);
613 		nsecs = (tv.tv_sec * 1000000000L + tv.tv_usec * 1000);
614 	} else
615 		nsecs = TIMESPEC_TO_NSEC(&dtev->dtev_tsp);
616 
617 	return nsecs;
618 }
619 
620 #include <machine/vmparam.h>
621 #define	INKERNEL(va)	((va) >= VM_MIN_KERNEL_ADDRESS)
622 
623 const char *
624 builtin_stack(struct dt_evt *dtev, int kernel)
625 {
626 	struct stacktrace *st = &dtev->dtev_kstack;
627 	static char buf[4096];
628 	size_t i;
629 	int n = 0;
630 
631 	if (st->st_count == 0)
632 		return "";
633 
634 	for (i = 0; i < st->st_count; i++) {
635 		if (INKERNEL(st->st_pc[i])) {
636 			if (!kernel)
637 				continue;
638 			n += kelf_snprintsym(buf + n, sizeof(buf) - 1 - n,
639 			    st->st_pc[i]);
640 		} else if (!kernel) {
641 			n += snprintf(buf + n, sizeof(buf) - 1 - n, "0x%lx\n",
642 			    st->st_pc[1]);
643 		}
644 	}
645 
646 	return buf;
647 }
648 
649 const char *
650 builtin_arg(struct dt_evt *dtev, enum bt_argtype dat)
651 {
652 	static char buf[sizeof("18446744073709551615")]; /* UINT64_MAX */
653 
654 	snprintf(buf, sizeof(buf) - 1, "%lu", dtev->dtev_sysargs[dat - B_AT_BI_ARG0]);
655 	return buf;
656 }
657 
658 void
659 stmt_clear(struct bt_stmt *bs)
660 {
661 	struct bt_arg *ba = SLIST_FIRST(&bs->bs_args);
662 	struct bt_var *bv = ba->ba_value;
663 
664 	assert(bs->bs_var == NULL);
665 	assert(ba->ba_type = B_AT_VAR);
666 
667 	map_clear(bv);
668 
669 	debug("map=%p '%s' clear\n", bv->bv_value, bv->bv_name);
670 }
671 
672 /*
673  * Map delete:	 	{ delete(@map[key]); }
674  *
675  * In this case 'map' is represented by `bv' and 'key' by `bkey'.
676  */
677 void
678 stmt_delete(struct bt_stmt *bs, struct dt_evt *dtev)
679 {
680 	struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args);
681 	struct bt_var *bv = bmap->ba_value;
682 
683 	assert(bmap->ba_type == B_AT_MAP);
684 	assert(bs->bs_var == NULL);
685 
686 	bkey = bmap->ba_key;
687 	debug("map=%p '%s' delete key=%p\n", bv->bv_value, bv->bv_name, bkey);
688 
689 	map_delete(bv, ba2hash(bkey, dtev));
690 }
691 
692 /*
693  * Map insert:	 	{ @map[key] = 42; }
694  *
695  * In this case 'map' is represented by `bv', 'key' by `bkey' and
696  * '42' by `bval'.
697  */
698 void
699 stmt_insert(struct bt_stmt *bs, struct dt_evt *dtev)
700 {
701 	struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args);
702 	struct bt_arg *bval = (struct bt_arg *)bs->bs_var;
703 	struct bt_var *bv = bmap->ba_value;
704 
705 	assert(bmap->ba_type == B_AT_MAP);
706 	assert(SLIST_NEXT(bval, ba_next) == NULL);
707 
708 	bkey = bmap->ba_key;
709 	debug("map=%p '%s' insert key=%p bval=%p\n", bv->bv_value, bv->bv_name,
710 	    bkey, bval);
711 
712 	map_insert(bv, ba2hash(bkey, dtev), bval);
713 }
714 
715 /*
716  * Print map entries:	{ print(@map[, 8]); }
717  *
718  * In this case the global variable 'map' is pointed at by `ba'
719  * and '8' is represented by `btop'.
720  */
721 void
722 stmt_print(struct bt_stmt *bs, struct dt_evt *dtev)
723 {
724 	struct bt_arg *btop, *ba = SLIST_FIRST(&bs->bs_args);
725 	struct bt_var *bv = ba->ba_value;
726 	size_t top = SIZE_T_MAX;
727 
728 	assert(bs->bs_var == NULL);
729 	assert(ba->ba_type = B_AT_VAR);
730 
731 	/* Parse optional `top' argument. */
732 	btop = SLIST_NEXT(ba, ba_next);
733 	if (btop != NULL) {
734 		assert(SLIST_NEXT(btop, ba_next) == NULL);
735 		top = ba2long(btop, dtev);
736 	}
737 
738 	map_print(bv, top);
739 
740 	debug("map=%p '%s' print (top=%d)\n", bv->bv_value, bv->bv_name, top);
741 }
742 
743 /*
744  * Variable store: 	{ var = 3; }
745  *
746  * In this case '3' is represented by `ba', the argument of a STORE
747  * action.
748  *
749  * If the argument depends of the value of an event (builtin) or is
750  * the result of an operation, its evaluation is stored in a new `ba'.
751  */
752 void
753 stmt_store(struct bt_stmt *bs, struct dt_evt *dtev)
754 {
755 	struct bt_arg *ba = SLIST_FIRST(&bs->bs_args);
756 	struct bt_var *bv = bs->bs_var;
757 
758 	assert(SLIST_NEXT(ba, ba_next) == NULL);
759 
760 	switch (ba->ba_type) {
761 	case B_AT_LONG:
762 		bv->bv_value = ba;
763 		break;
764 	case B_AT_BI_NSECS:
765 		bv->bv_value = ba_new(builtin_nsecs(dtev), B_AT_LONG);
766 		break;
767 	case B_AT_OP_ADD ... B_AT_OP_DIVIDE:
768 		bv->bv_value = ba_new(ba2long(ba, dtev), B_AT_LONG);
769 		break;
770 	default:
771 		xabort("store not implemented for type %d", ba->ba_type);
772 	}
773 
774 	debug("bv=%p var '%s' store (%p) \n", bv, bv->bv_name, bv->bv_value);
775 }
776 
777 /*
778  * Print time: 		{ time("%H:%M:%S"); }
779  */
780 void
781 stmt_time(struct bt_stmt *bs, struct dt_evt *dtev)
782 {
783 	struct bt_arg *ba = SLIST_FIRST(&bs->bs_args);
784 	time_t time;
785 	struct tm *tm;
786 	char buf[64];
787 
788 	assert(bs->bs_var == NULL);
789 	assert(ba->ba_type = B_AT_STR);
790 	assert(strlen(ba2str(ba, dtev)) < (sizeof(buf) - 1));
791 
792 	time = builtin_gettime(dtev);
793 	tm = localtime(&time);
794 	strftime(buf, sizeof(buf), ba2str(ba, dtev), tm);
795 	printf("%s", buf);
796 }
797 
798 void
799 stmt_zero(struct bt_stmt *bs)
800 {
801 	struct bt_arg *ba = SLIST_FIRST(&bs->bs_args);
802 	struct bt_var *bv = ba->ba_value;
803 
804 	assert(bs->bs_var == NULL);
805 	assert(ba->ba_type = B_AT_VAR);
806 
807 	map_zero(bv);
808 
809 	debug("map=%p '%s' zero\n", bv->bv_value, bv->bv_name);
810 }
811 
812 struct bt_arg *
813 ba_read(struct bt_arg *ba)
814 {
815 	struct bt_var *bv = ba->ba_value;
816 
817 	assert(ba->ba_type == B_AT_VAR);
818 
819 	debug("bv=%p read '%s' (%p)\n", bv, bv->bv_name, bv->bv_value);
820 
821 	return bv->bv_value;
822 }
823 
824 /*
825  * Helper to evaluate the operation encoded in `ba' and return its
826  * result.
827  */
828 static inline long
829 baexpr2long(struct bt_arg *ba, struct dt_evt *dtev)
830 {
831 	static long recursions;
832 	struct bt_arg *a, *b;
833 	long first, second, result;
834 
835 	if (++recursions >= __MAXOPERANDS)
836 		errx(1, "too many operands (>%d) in expression", __MAXOPERANDS);
837 
838 	a = ba->ba_value;
839 	b = SLIST_NEXT(a, ba_next);
840 
841 	assert(SLIST_NEXT(b, ba_next) == NULL);
842 
843 	first = ba2long(a, dtev);
844 	second = ba2long(b, dtev);
845 
846 	switch (ba->ba_type) {
847 	case B_AT_OP_ADD:
848 		result = first + second;
849 		break;
850 	case B_AT_OP_MINUS:
851 		result = first - second;
852 		break;
853 	case B_AT_OP_MULT:
854 		result = first * second;
855 		break;
856 	case B_AT_OP_DIVIDE:
857 		result = first / second;
858 		break;
859 	default:
860 		xabort("unsuported operation %d", ba->ba_type);
861 	}
862 
863 	debug("ba=%p (%ld op %ld) = %ld\n", ba, first, second, result);
864 
865 	--recursions;
866 
867 	return result;
868 }
869 
870 /*
871  * Return the representation of `ba' as long.
872  */
873 long
874 ba2long(struct bt_arg *ba, struct dt_evt *dtev)
875 {
876 	long val;
877 
878 	switch (ba->ba_type) {
879 	case B_AT_LONG:
880 		val = (long)ba->ba_value;
881 		break;
882 	case B_AT_VAR:
883 		ba = ba_read(ba);
884 		val = (long)ba->ba_value;
885 		break;
886 	case B_AT_BI_NSECS:
887 		val = builtin_nsecs(dtev);
888 		break;
889 	case B_AT_OP_ADD ... B_AT_OP_DIVIDE:
890 		val = baexpr2long(ba, dtev);
891 		break;
892 	default:
893 		xabort("no long conversion for type %d", ba->ba_type);
894 	}
895 
896 	debug("ba=%p long='%ld'\n", ba, val);
897 
898 	return  val;
899 }
900 
901 /*
902  * Return the representation of `ba' as string.
903  */
904 const char *
905 ba2str(struct bt_arg *ba, struct dt_evt *dtev)
906 {
907 	static char buf[sizeof("18446744073709551615")]; /* UINT64_MAX */
908 	const char *str;
909 
910 	switch (ba->ba_type) {
911 	case B_AT_STR:
912 		str = (const char *)ba->ba_value;
913 		break;
914 	case B_AT_LONG:
915 		snprintf(buf, sizeof(buf) - 1, "%ld",(long)ba->ba_value);
916 		str = buf;
917 		break;
918 	case B_AT_BI_KSTACK:
919 		str = builtin_stack(dtev, 1);
920 		break;
921 	case B_AT_BI_USTACK:
922 		str = builtin_stack(dtev, 0);
923 		break;
924 	case B_AT_BI_COMM:
925 		str = dtev->dtev_comm;
926 		break;
927 	case B_AT_BI_PID:
928 		snprintf(buf, sizeof(buf) - 1, "%d", dtev->dtev_pid);
929 		str = buf;
930 		break;
931 	case B_AT_BI_TID:
932 		snprintf(buf, sizeof(buf) - 1, "%d", dtev->dtev_tid);
933 		str = buf;
934 		break;
935 	case B_AT_BI_NSECS:
936 		snprintf(buf, sizeof(buf) - 1, "%llu", builtin_nsecs(dtev));
937 		str = buf;
938 		break;
939 	case B_AT_BI_ARG0 ... B_AT_BI_ARG9:
940 		str = builtin_arg(dtev, ba->ba_type);
941 		break;
942 	case B_AT_BI_RETVAL:
943 		snprintf(buf, sizeof(buf) - 1, "%ld", (long)dtev->dtev_sysretval);
944 		str = buf;
945 		break;
946 	case B_AT_MAP:
947 		str = ba2str(map_get(ba->ba_value, ba2str(ba->ba_key, dtev)), dtev);
948 		break;
949 	case B_AT_VAR:
950 		str = ba2str(ba_read(ba), dtev);
951 		break;
952 	case B_AT_OP_ADD ... B_AT_OP_DIVIDE:
953 		snprintf(buf, sizeof(buf) - 1, "%ld", ba2long(ba, dtev));
954 		str = buf;
955 		break;
956 	case B_AT_MF_COUNT:
957 	case B_AT_MF_MAX:
958 	case B_AT_MF_MIN:
959 	case B_AT_MF_SUM:
960 		assert(0);
961 		break;
962 	default:
963 		xabort("no string conversion for type %d", ba->ba_type);
964 	}
965 
966 	debug("ba=%p str='%s'\n", ba, str);
967 
968 	return str;
969 }
970 
971 long
972 bacmp(struct bt_arg *a, struct bt_arg *b)
973 {
974 	assert(a->ba_type == b->ba_type);
975 	assert(a->ba_type == B_AT_LONG);
976 
977 	return ba2long(a, NULL) - ba2long(b, NULL);
978 }
979 
980 __dead void
981 xabort(const char *fmt, ...)
982 {
983 	va_list ap;
984 
985 	va_start(ap, fmt);
986 	vfprintf(stderr, fmt, ap);
987 	va_end(ap);
988 
989 	fprintf(stderr, "\n");
990 	abort();
991 }
992 
993 void
994 debug(const char *fmt, ...)
995 {
996 	va_list ap;
997 
998 	if (verbose < 2)
999 		return;
1000 
1001 	fprintf(stderr, "debug: ");
1002 
1003 	va_start(ap, fmt);
1004 	vfprintf(stderr, fmt, ap);
1005 	va_end(ap);
1006 }
1007 
1008 void
1009 debugx(const char *fmt, ...)
1010 {
1011 	va_list ap;
1012 
1013 	if (verbose < 2)
1014 		return;
1015 
1016 	va_start(ap, fmt);
1017 	vfprintf(stderr, fmt, ap);
1018 	va_end(ap);
1019 }
1020 
1021 static inline const char *
1022 debug_getfiltervar(struct bt_filter *df)
1023 {
1024 	switch (df->bf_var) {
1025 	case B_FV_PID:	return "pid";
1026 	case B_FV_TID:	return "tid";
1027 	case B_FV_NONE:	return "";
1028 	default:
1029 		xabort("invalid filtervar %d", df->bf_var);
1030 	}
1031 
1032 
1033 }
1034 
1035 static inline const char *
1036 debug_getfilterop(struct bt_filter *df)
1037 {
1038 	switch (df->bf_op) {
1039 	case B_OP_EQ:	return "==";
1040 	case B_OP_NE:	return "!=";
1041 	case B_OP_NONE:	return "";
1042 	default:
1043 		xabort("invalid operand %d", df->bf_op);
1044 	}
1045 }
1046 
1047 void
1048 debug_dump_filter(struct bt_rule *r)
1049 {
1050 	if (r->br_filter) {
1051 		debugx(" / %s %s %u /", debug_getfiltervar(r->br_filter),
1052 		    debug_getfilterop(r->br_filter), r->br_filter->bf_val);
1053 	}
1054 	debugx("\n");
1055 }
1056 
1057 const char *
1058 debug_rule_name(struct bt_rule *r)
1059 {
1060 	struct bt_probe *bp = r->br_probe;
1061 	static char buf[64];
1062 
1063 	if (r->br_type == B_RT_BEGIN)
1064 		return "BEGIN";
1065 
1066 	if (r->br_type == B_RT_END)
1067 		return "END";
1068 
1069 	assert(r->br_type == B_RT_PROBE);
1070 
1071 	if (r->br_probe->bp_rate) {
1072 		snprintf(buf, sizeof(buf) - 1, "%s:%s:%u", bp->bp_prov,
1073 		    bp->bp_unit, bp->bp_rate);
1074 	} else {
1075 		snprintf(buf, sizeof(buf) - 1, "%s:%s:%s", bp->bp_prov,
1076 		    bp->bp_unit, bp->bp_name);
1077 	}
1078 
1079 	return buf;
1080 }
1081 
1082 void
1083 debug_dump_rule(struct bt_rule *r)
1084 {
1085 	debug("parsed probe '%s'", debug_rule_name(r));
1086 	debug_dump_filter(r);
1087 }
1088