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