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