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