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