1 /* $OpenBSD: btrace.c,v 1.26 2020/12/07 18:28:09 bluhm 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], *bp; 639 size_t i; 640 int sz; 641 642 if (!kernel || st->st_count == 0) 643 return ""; 644 645 buf[0] = '\0'; 646 bp = buf; 647 sz = sizeof(buf); 648 for (i = 0; i < st->st_count; i++) { 649 int l; 650 651 l = kelf_snprintsym(bp, sz - 1, st->st_pc[i]); 652 if (l < 0) 653 break; 654 if (l >= sz - 1) { 655 bp += sz - 1; 656 sz = 1; 657 break; 658 } 659 bp += l; 660 sz -= l; 661 } 662 snprintf(bp, sz, "\n"); 663 664 return buf; 665 } 666 667 const char * 668 builtin_arg(struct dt_evt *dtev, enum bt_argtype dat) 669 { 670 static char buf[sizeof("18446744073709551615")]; /* UINT64_MAX */ 671 672 snprintf(buf, sizeof(buf), "%lu", 673 dtev->dtev_sysargs[dat - B_AT_BI_ARG0]); 674 675 return buf; 676 } 677 678 /* 679 * Increment a bucket: { @h = hist(v); } or { @h = lhist(v, min, max, step); } 680 * 681 * In this case 'h' is represented by `bv' and '(min, max, step)' by `brange'. 682 */ 683 void 684 stmt_bucketize(struct bt_stmt *bs, struct dt_evt *dtev) 685 { 686 struct bt_arg *brange, *bhist = SLIST_FIRST(&bs->bs_args); 687 struct bt_arg *bval = (struct bt_arg *)bs->bs_var; 688 struct bt_var *bv = bhist->ba_value; 689 const char *bucket; 690 long step = 0; 691 692 assert(bhist->ba_type == B_AT_HIST); 693 assert(SLIST_NEXT(bval, ba_next) == NULL); 694 695 brange = bhist->ba_key; 696 bucket = ba2bucket(bval, brange, dtev, &step); 697 if (bucket == NULL) { 698 debug("hist=%p '%s' value=%lu out of range\n", bv->bv_value, 699 bv_name(bv), ba2long(bval, dtev)); 700 return; 701 } 702 debug("hist=%p '%s' increment bucket=%s\n", bv->bv_value, 703 bv_name(bv), bucket); 704 705 bv->bv_value = (struct bt_arg *) 706 hist_increment((struct hist *)bv->bv_value, bucket, step); 707 } 708 709 710 /* 711 * Empty a map: { clear(@map); } 712 */ 713 void 714 stmt_clear(struct bt_stmt *bs) 715 { 716 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args); 717 struct bt_var *bv = ba->ba_value; 718 719 assert(bs->bs_var == NULL); 720 assert(ba->ba_type == B_AT_VAR); 721 722 map_clear((struct map *)bv->bv_value); 723 bv->bv_value = NULL; 724 725 debug("map=%p '%s' clear\n", bv->bv_value, bv_name(bv)); 726 } 727 728 /* 729 * Map delete: { delete(@map[key]); } 730 * 731 * In this case 'map' is represented by `bv' and 'key' by `bkey'. 732 */ 733 void 734 stmt_delete(struct bt_stmt *bs, struct dt_evt *dtev) 735 { 736 struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args); 737 struct bt_var *bv = bmap->ba_value; 738 const char *hash; 739 740 assert(bmap->ba_type == B_AT_MAP); 741 assert(bs->bs_var == NULL); 742 743 bkey = bmap->ba_key; 744 hash = ba2hash(bkey, dtev); 745 debug("map=%p '%s' delete key=%p '%s'\n", bv->bv_value, bv_name(bv), 746 bkey, hash); 747 748 map_delete((struct map *)bv->bv_value, hash); 749 } 750 751 /* 752 * Map insert: { @map[key] = 42; } 753 * 754 * In this case 'map' is represented by `bv', 'key' by `bkey' and 755 * '42' by `bval'. 756 */ 757 void 758 stmt_insert(struct bt_stmt *bs, struct dt_evt *dtev) 759 { 760 struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args); 761 struct bt_arg *bval = (struct bt_arg *)bs->bs_var; 762 struct bt_var *bv = bmap->ba_value; 763 const char *hash; 764 765 assert(bmap->ba_type == B_AT_MAP); 766 assert(SLIST_NEXT(bval, ba_next) == NULL); 767 768 bkey = bmap->ba_key; 769 hash = ba2hash(bkey, dtev); 770 debug("map=%p '%s' insert key=%p '%s' bval=%p\n", bv->bv_value, 771 bv_name(bv), bkey, hash, bval); 772 773 bv->bv_value = (struct bt_arg *)map_insert((struct map *)bv->bv_value, 774 hash, bval, dtev); 775 } 776 777 /* 778 * Print map entries: { print(@map[, 8]); } 779 * 780 * In this case the global variable 'map' is pointed at by `ba' 781 * and '8' is represented by `btop'. 782 */ 783 void 784 stmt_print(struct bt_stmt *bs, struct dt_evt *dtev) 785 { 786 struct bt_arg *btop, *ba = SLIST_FIRST(&bs->bs_args); 787 struct bt_var *bv = ba->ba_value; 788 size_t top = SIZE_T_MAX; 789 790 assert(bs->bs_var == NULL); 791 assert(ba->ba_type == B_AT_VAR); 792 793 /* Parse optional `top' argument. */ 794 btop = SLIST_NEXT(ba, ba_next); 795 if (btop != NULL) { 796 assert(SLIST_NEXT(btop, ba_next) == NULL); 797 top = ba2long(btop, dtev); 798 } 799 debug("map=%p '%s' print (top=%d)\n", bv->bv_value, bv_name(bv), top); 800 801 map_print((struct map *)bv->bv_value, top, bv_name(bv)); 802 } 803 804 /* 805 * Variable store: { var = 3; } 806 * 807 * In this case '3' is represented by `ba', the argument of a STORE 808 * action. 809 * 810 * If the argument depends of the value of an event (builtin) or is 811 * the result of an operation, its evaluation is stored in a new `ba'. 812 */ 813 void 814 stmt_store(struct bt_stmt *bs, struct dt_evt *dtev) 815 { 816 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args); 817 struct bt_var *bv = bs->bs_var; 818 819 assert(SLIST_NEXT(ba, ba_next) == NULL); 820 821 switch (ba->ba_type) { 822 case B_AT_LONG: 823 bv->bv_value = ba; 824 break; 825 case B_AT_BI_NSECS: 826 bv->bv_value = ba_new(builtin_nsecs(dtev), B_AT_LONG); 827 break; 828 case B_AT_OP_ADD ... B_AT_OP_OR: 829 bv->bv_value = ba_new(ba2long(ba, dtev), B_AT_LONG); 830 break; 831 default: 832 xabort("store not implemented for type %d", ba->ba_type); 833 } 834 835 debug("bv=%p var '%s' store (%p) \n", bv, bv_name(bv), bv->bv_value); 836 } 837 838 /* 839 * Print time: { time("%H:%M:%S"); } 840 */ 841 void 842 stmt_time(struct bt_stmt *bs, struct dt_evt *dtev) 843 { 844 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args); 845 time_t time; 846 struct tm *tm; 847 char buf[64]; 848 849 assert(bs->bs_var == NULL); 850 assert(ba->ba_type == B_AT_STR); 851 assert(strlen(ba2str(ba, dtev)) < (sizeof(buf) - 1)); 852 853 time = builtin_gettime(dtev); 854 tm = localtime(&time); 855 strftime(buf, sizeof(buf), ba2str(ba, dtev), tm); 856 printf("%s", buf); 857 } 858 859 /* 860 * Set entries to 0: { zero(@map); } 861 */ 862 void 863 stmt_zero(struct bt_stmt *bs) 864 { 865 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args); 866 struct bt_var *bv = ba->ba_value; 867 868 assert(bs->bs_var == NULL); 869 assert(ba->ba_type == B_AT_VAR); 870 871 map_zero((struct map *)bv->bv_value); 872 873 debug("map=%p '%s' zero\n", bv->bv_value, bv_name(bv)); 874 } 875 876 struct bt_arg * 877 ba_read(struct bt_arg *ba) 878 { 879 struct bt_var *bv = ba->ba_value; 880 881 assert(ba->ba_type == B_AT_VAR); 882 883 debug("bv=%p read '%s' (%p)\n", bv, bv_name(bv), bv->bv_value); 884 885 return bv->bv_value; 886 } 887 888 const char * 889 ba2hash(struct bt_arg *ba, struct dt_evt *dtev) 890 { 891 static char buf[KLEN]; 892 char *hash; 893 int l, len; 894 895 buf[0] = '\0'; 896 l = snprintf(buf, sizeof(buf), "%s", ba2str(ba, dtev)); 897 if (l < 0 || (size_t)l > sizeof(buf)) { 898 warn("string too long %d > %lu", l, sizeof(buf)); 899 return buf; 900 } 901 902 len = 0; 903 while ((ba = SLIST_NEXT(ba, ba_next)) != NULL) { 904 len += l; 905 hash = buf + len; 906 907 l = snprintf(hash, sizeof(buf) - len, ", %s", ba2str(ba, dtev)); 908 if (l < 0 || (size_t)l > (sizeof(buf) - len)) { 909 warn("hash too long %d > %lu", l + len, sizeof(buf)); 910 break; 911 } 912 } 913 914 return buf; 915 } 916 917 static unsigned long 918 next_pow2(unsigned long x) 919 { 920 size_t i; 921 922 x--; 923 for (i = 0; i < (sizeof(x) * 8) - 1; i++) 924 x |= (x >> 1); 925 926 return x + 1; 927 } 928 929 /* 930 * Return the ceiling value the interval holding `ba' or NULL if it is 931 * out of the (min, max) values. 932 */ 933 const char * 934 ba2bucket(struct bt_arg *ba, struct bt_arg *brange, struct dt_evt *dtev, 935 long *pstep) 936 { 937 static char buf[KLEN]; 938 long val, bucket; 939 int l; 940 941 val = ba2long(ba, dtev); 942 if (brange == NULL) 943 bucket = next_pow2(val); 944 else { 945 long min, max, step; 946 947 assert(brange->ba_type == B_AT_LONG); 948 min = ba2long(brange, NULL); 949 950 brange = SLIST_NEXT(brange, ba_next); 951 assert(brange->ba_type == B_AT_LONG); 952 max = ba2long(brange, NULL); 953 954 if ((val < min) || (val > max)) 955 return NULL; 956 957 brange = SLIST_NEXT(brange, ba_next); 958 assert(brange->ba_type == B_AT_LONG); 959 step = ba2long(brange, NULL); 960 961 bucket = ((val / step) + 1) * step; 962 *pstep = step; 963 } 964 965 buf[0] = '\0'; 966 l = snprintf(buf, sizeof(buf), "%lu", bucket); 967 if (l < 0 || (size_t)l > sizeof(buf)) { 968 warn("string too long %d > %lu", l, sizeof(buf)); 969 return buf; 970 } 971 972 return buf; 973 } 974 975 /* 976 * Helper to evaluate the operation encoded in `ba' and return its 977 * result. 978 */ 979 static inline long 980 baexpr2long(struct bt_arg *ba, struct dt_evt *dtev) 981 { 982 static long recursions; 983 struct bt_arg *a, *b; 984 long first, second, result; 985 986 if (++recursions >= __MAXOPERANDS) 987 errx(1, "too many operands (>%d) in expression", __MAXOPERANDS); 988 989 a = ba->ba_value; 990 b = SLIST_NEXT(a, ba_next); 991 992 assert(SLIST_NEXT(b, ba_next) == NULL); 993 994 first = ba2long(a, dtev); 995 second = ba2long(b, dtev); 996 997 switch (ba->ba_type) { 998 case B_AT_OP_ADD: 999 result = first + second; 1000 break; 1001 case B_AT_OP_MINUS: 1002 result = first - second; 1003 break; 1004 case B_AT_OP_MULT: 1005 result = first * second; 1006 break; 1007 case B_AT_OP_DIVIDE: 1008 result = first / second; 1009 break; 1010 case B_AT_OP_AND: 1011 result = first & second; 1012 break; 1013 case B_AT_OP_OR: 1014 result = first | second; 1015 break; 1016 default: 1017 xabort("unsuported operation %d", ba->ba_type); 1018 } 1019 1020 debug("ba=%p (%ld op %ld) = %ld\n", ba, first, second, result); 1021 1022 --recursions; 1023 1024 return result; 1025 } 1026 1027 /* 1028 * Return the representation of `ba' as long. 1029 */ 1030 long 1031 ba2long(struct bt_arg *ba, struct dt_evt *dtev) 1032 { 1033 long val; 1034 1035 switch (ba->ba_type) { 1036 case B_AT_LONG: 1037 val = (long)ba->ba_value; 1038 break; 1039 case B_AT_VAR: 1040 ba = ba_read(ba); 1041 val = (long)ba->ba_value; 1042 break; 1043 case B_AT_BI_NSECS: 1044 val = builtin_nsecs(dtev); 1045 break; 1046 case B_AT_BI_RETVAL: 1047 val = dtev->dtev_sysretval[0]; 1048 break; 1049 case B_AT_OP_ADD ... B_AT_OP_OR: 1050 val = baexpr2long(ba, dtev); 1051 break; 1052 default: 1053 xabort("no long conversion for type %d", ba->ba_type); 1054 } 1055 1056 return val; 1057 } 1058 1059 /* 1060 * Return the representation of `ba' as string. 1061 */ 1062 const char * 1063 ba2str(struct bt_arg *ba, struct dt_evt *dtev) 1064 { 1065 static char buf[sizeof("18446744073709551615")]; /* UINT64_MAX */ 1066 struct bt_var *bv; 1067 const char *str; 1068 1069 buf[0] = '\0'; 1070 switch (ba->ba_type) { 1071 case B_AT_STR: 1072 str = (const char *)ba->ba_value; 1073 break; 1074 case B_AT_LONG: 1075 snprintf(buf, sizeof(buf), "%ld",(long)ba->ba_value); 1076 str = buf; 1077 break; 1078 case B_AT_BI_KSTACK: 1079 str = builtin_stack(dtev, 1); 1080 break; 1081 case B_AT_BI_USTACK: 1082 str = builtin_stack(dtev, 0); 1083 break; 1084 case B_AT_BI_COMM: 1085 str = dtev->dtev_comm; 1086 break; 1087 case B_AT_BI_CPU: 1088 snprintf(buf, sizeof(buf), "%u", dtev->dtev_cpu); 1089 str = buf; 1090 break; 1091 case B_AT_BI_PID: 1092 snprintf(buf, sizeof(buf), "%d", dtev->dtev_pid); 1093 str = buf; 1094 break; 1095 case B_AT_BI_TID: 1096 snprintf(buf, sizeof(buf), "%d", dtev->dtev_tid); 1097 str = buf; 1098 break; 1099 case B_AT_BI_NSECS: 1100 snprintf(buf, sizeof(buf), "%llu", builtin_nsecs(dtev)); 1101 str = buf; 1102 break; 1103 case B_AT_BI_ARG0 ... B_AT_BI_ARG9: 1104 str = builtin_arg(dtev, ba->ba_type); 1105 break; 1106 case B_AT_BI_RETVAL: 1107 snprintf(buf, sizeof(buf), "%ld", (long)dtev->dtev_sysretval[0]); 1108 str = buf; 1109 break; 1110 case B_AT_MAP: 1111 bv = ba->ba_value; 1112 str = ba2str(map_get((struct map *)bv->bv_value, 1113 ba2str(ba->ba_key, dtev)), dtev); 1114 break; 1115 case B_AT_VAR: 1116 str = ba2str(ba_read(ba), dtev); 1117 break; 1118 case B_AT_OP_ADD ... B_AT_OP_OR: 1119 snprintf(buf, sizeof(buf), "%ld", ba2long(ba, dtev)); 1120 str = buf; 1121 break; 1122 case B_AT_MF_COUNT: 1123 case B_AT_MF_MAX: 1124 case B_AT_MF_MIN: 1125 case B_AT_MF_SUM: 1126 assert(0); 1127 break; 1128 default: 1129 xabort("no string conversion for type %d", ba->ba_type); 1130 } 1131 1132 return str; 1133 } 1134 1135 /* 1136 * Return dt(4) flags indicating which data should be recorded by the 1137 * kernel, if any, for a given `ba'. 1138 */ 1139 int 1140 ba2dtflags(struct bt_arg *ba) 1141 { 1142 int flags = 0; 1143 1144 if (ba->ba_type == B_AT_MAP) 1145 ba = ba->ba_key; 1146 1147 do { 1148 switch (ba->ba_type) { 1149 case B_AT_STR: 1150 case B_AT_LONG: 1151 case B_AT_VAR: 1152 case B_AT_HIST: 1153 break; 1154 case B_AT_BI_KSTACK: 1155 flags |= DTEVT_KSTACK; 1156 break; 1157 case B_AT_BI_USTACK: 1158 flags |= DTEVT_USTACK; 1159 break; 1160 case B_AT_BI_COMM: 1161 flags |= DTEVT_EXECNAME; 1162 break; 1163 case B_AT_BI_CPU: 1164 case B_AT_BI_PID: 1165 case B_AT_BI_TID: 1166 case B_AT_BI_NSECS: 1167 break; 1168 case B_AT_BI_ARG0 ... B_AT_BI_ARG9: 1169 flags |= DTEVT_FUNCARGS; 1170 break; 1171 case B_AT_BI_RETVAL: 1172 break; 1173 case B_AT_MF_COUNT: 1174 case B_AT_MF_MAX: 1175 case B_AT_MF_MIN: 1176 case B_AT_MF_SUM: 1177 case B_AT_OP_ADD ... B_AT_OP_OR: 1178 break; 1179 default: 1180 xabort("invalid argument type %d", ba->ba_type); 1181 } 1182 } while ((ba = SLIST_NEXT(ba, ba_next)) != NULL); 1183 1184 return flags; 1185 } 1186 1187 long 1188 bacmp(struct bt_arg *a, struct bt_arg *b) 1189 { 1190 assert(a->ba_type == b->ba_type); 1191 assert(a->ba_type == B_AT_LONG); 1192 1193 return ba2long(a, NULL) - ba2long(b, NULL); 1194 } 1195 1196 __dead void 1197 xabort(const char *fmt, ...) 1198 { 1199 va_list ap; 1200 1201 va_start(ap, fmt); 1202 vfprintf(stderr, fmt, ap); 1203 va_end(ap); 1204 1205 fprintf(stderr, "\n"); 1206 abort(); 1207 } 1208 1209 void 1210 debug(const char *fmt, ...) 1211 { 1212 va_list ap; 1213 1214 if (verbose < 2) 1215 return; 1216 1217 fprintf(stderr, "debug: "); 1218 1219 va_start(ap, fmt); 1220 vfprintf(stderr, fmt, ap); 1221 va_end(ap); 1222 } 1223 1224 void 1225 debugx(const char *fmt, ...) 1226 { 1227 va_list ap; 1228 1229 if (verbose < 2) 1230 return; 1231 1232 va_start(ap, fmt); 1233 vfprintf(stderr, fmt, ap); 1234 va_end(ap); 1235 } 1236 1237 static inline const char * 1238 debug_getfiltervar(struct bt_filter *df) 1239 { 1240 switch (df->bf_var) { 1241 case B_FV_PID: return "pid"; 1242 case B_FV_TID: return "tid"; 1243 case B_FV_NONE: return ""; 1244 default: 1245 xabort("invalid filtervar %d", df->bf_var); 1246 } 1247 1248 1249 } 1250 1251 static inline const char * 1252 debug_getfilterop(struct bt_filter *df) 1253 { 1254 switch (df->bf_op) { 1255 case B_OP_EQ: return "=="; 1256 case B_OP_NE: return "!="; 1257 case B_OP_NONE: return ""; 1258 default: 1259 xabort("invalid operand %d", df->bf_op); 1260 } 1261 } 1262 1263 void 1264 debug_dump_filter(struct bt_rule *r) 1265 { 1266 if (r->br_filter) { 1267 debugx(" / %s %s %u /", debug_getfiltervar(r->br_filter), 1268 debug_getfilterop(r->br_filter), r->br_filter->bf_val); 1269 } 1270 debugx("\n"); 1271 } 1272 1273 const char * 1274 debug_rule_name(struct bt_rule *r) 1275 { 1276 struct bt_probe *bp = r->br_probe; 1277 static char buf[64]; 1278 1279 if (r->br_type == B_RT_BEGIN) 1280 return "BEGIN"; 1281 1282 if (r->br_type == B_RT_END) 1283 return "END"; 1284 1285 assert(r->br_type == B_RT_PROBE); 1286 1287 if (r->br_probe->bp_rate) { 1288 snprintf(buf, sizeof(buf), "%s:%s:%u", bp->bp_prov, 1289 bp->bp_unit, bp->bp_rate); 1290 } else { 1291 snprintf(buf, sizeof(buf), "%s:%s:%s", bp->bp_prov, 1292 bp->bp_unit, bp->bp_name); 1293 } 1294 1295 return buf; 1296 } 1297 1298 void 1299 debug_dump_rule(struct bt_rule *r) 1300 { 1301 debug("parsed probe '%s'", debug_rule_name(r)); 1302 debug_dump_filter(r); 1303 } 1304