1 /* $OpenBSD: btrace.c,v 1.69 2023/03/10 23:02:30 bluhm Exp $ */ 2 3 /* 4 * Copyright (c) 2019 - 2021 Martin Pieuchot <mpi@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/ioctl.h> 20 #include <sys/exec_elf.h> 21 #include <sys/stat.h> 22 #include <sys/syscall.h> 23 #include <sys/queue.h> 24 25 #include <assert.h> 26 #include <err.h> 27 #include <errno.h> 28 #include <fcntl.h> 29 #include <limits.h> 30 #include <locale.h> 31 #include <paths.h> 32 #include <signal.h> 33 #include <stdarg.h> 34 #include <stdbool.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <time.h> 39 #include <unistd.h> 40 41 #include <dev/dt/dtvar.h> 42 43 #include "btrace.h" 44 #include "bt_parser.h" 45 46 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 47 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) 48 49 /* 50 * Maximum number of operands an arithmetic operation can have. This 51 * is necessary to stop infinite recursion when evaluating expressions. 52 */ 53 #define __MAXOPERANDS 5 54 55 #define __PATH_DEVDT "/dev/dt" 56 57 __dead void usage(void); 58 char *read_btfile(const char *, size_t *); 59 60 /* 61 * Retrieve & parse probe information. 62 */ 63 void dtpi_cache(int); 64 void dtpi_print_list(int); 65 const char *dtpi_func(struct dtioc_probe_info *); 66 int dtpi_is_unit(const char *); 67 struct dtioc_probe_info *dtpi_get_by_value(const char *, const char *, 68 const char *); 69 70 /* 71 * Main loop and rule evaluation. 72 */ 73 void rules_do(int); 74 void rules_setup(int); 75 void rules_apply(int, struct dt_evt *); 76 void rules_teardown(int); 77 void rule_eval(struct bt_rule *, struct dt_evt *); 78 void rule_printmaps(struct bt_rule *); 79 80 /* 81 * Language builtins & functions. 82 */ 83 uint64_t builtin_nsecs(struct dt_evt *); 84 const char *builtin_kstack(struct dt_evt *); 85 const char *builtin_arg(struct dt_evt *, enum bt_argtype); 86 struct bt_arg *fn_str(struct bt_arg *, struct dt_evt *, char *); 87 void stmt_eval(struct bt_stmt *, struct dt_evt *); 88 void stmt_bucketize(struct bt_stmt *, struct dt_evt *); 89 void stmt_clear(struct bt_stmt *); 90 void stmt_delete(struct bt_stmt *, struct dt_evt *); 91 void stmt_insert(struct bt_stmt *, struct dt_evt *); 92 void stmt_print(struct bt_stmt *, struct dt_evt *); 93 void stmt_store(struct bt_stmt *, struct dt_evt *); 94 bool stmt_test(struct bt_stmt *, struct dt_evt *); 95 void stmt_time(struct bt_stmt *, struct dt_evt *); 96 void stmt_zero(struct bt_stmt *); 97 struct bt_arg *ba_read(struct bt_arg *); 98 const char *ba2hash(struct bt_arg *, struct dt_evt *); 99 long baexpr2long(struct bt_arg *, struct dt_evt *); 100 const char *ba2bucket(struct bt_arg *, struct bt_arg *, 101 struct dt_evt *, long *); 102 int ba2dtflags(struct bt_arg *); 103 104 /* 105 * Debug routines. 106 */ 107 __dead void xabort(const char *, ...); 108 void debug(const char *, ...); 109 void debugx(const char *, ...); 110 const char *debug_probe_name(struct bt_probe *); 111 void debug_dump_term(struct bt_arg *); 112 void debug_dump_expr(struct bt_arg *); 113 void debug_dump_filter(struct bt_rule *); 114 115 struct dtioc_probe_info *dt_dtpis; /* array of available probes */ 116 size_t dt_ndtpi; /* # of elements in the array */ 117 struct dtioc_arg_info **dt_args; /* array of probe arguments */ 118 119 struct dt_evt bt_devt; /* fake event for BEGIN/END */ 120 uint64_t bt_filtered; /* # of events filtered out */ 121 122 char **vargs; 123 int nargs = 0; 124 int verbose = 0; 125 volatile sig_atomic_t quit_pending; 126 127 static void 128 signal_handler(int sig) 129 { 130 quit_pending = sig; 131 } 132 133 134 int 135 main(int argc, char *argv[]) 136 { 137 int fd = -1, ch, error = 0; 138 const char *filename = NULL, *btscript = NULL; 139 int showprobes = 0, noaction = 0; 140 size_t btslen = 0; 141 142 setlocale(LC_ALL, ""); 143 144 while ((ch = getopt(argc, argv, "e:lnp:v")) != -1) { 145 switch (ch) { 146 case 'e': 147 btscript = optarg; 148 btslen = strlen(btscript); 149 break; 150 case 'l': 151 showprobes = 1; 152 break; 153 case 'n': 154 noaction = 1; 155 break; 156 case 'v': 157 verbose++; 158 break; 159 default: 160 usage(); 161 } 162 } 163 164 argc -= optind; 165 argv += optind; 166 167 if (argc > 0 && btscript == NULL) 168 filename = argv[0]; 169 170 /* Cannot pledge due to special ioctl()s */ 171 if (unveil(__PATH_DEVDT, "r") == -1) 172 err(1, "unveil %s", __PATH_DEVDT); 173 if (unveil(_PATH_KSYMS, "r") == -1) 174 err(1, "unveil %s", _PATH_KSYMS); 175 if (filename != NULL) { 176 if (unveil(filename, "r") == -1) 177 err(1, "unveil %s", filename); 178 } 179 if (unveil(NULL, NULL) == -1) 180 err(1, "unveil"); 181 182 if (filename != NULL) { 183 btscript = read_btfile(filename, &btslen); 184 argc--; 185 argv++; 186 } 187 188 nargs = argc; 189 vargs = argv; 190 191 if (btscript == NULL && !showprobes) 192 usage(); 193 194 if (btscript != NULL) { 195 error = btparse(btscript, btslen, filename, 1); 196 if (error) 197 return error; 198 } 199 200 if (noaction) 201 return error; 202 203 if (showprobes || g_nprobes > 0) { 204 fd = open(__PATH_DEVDT, O_RDONLY); 205 if (fd == -1) 206 err(1, "could not open %s", __PATH_DEVDT); 207 } 208 209 if (showprobes) { 210 dtpi_cache(fd); 211 dtpi_print_list(fd); 212 } 213 214 if (!TAILQ_EMPTY(&g_rules)) 215 rules_do(fd); 216 217 if (fd != -1) 218 close(fd); 219 220 return error; 221 } 222 223 __dead void 224 usage(void) 225 { 226 fprintf(stderr, "usage: %s [-lnv] [-e program | file] [argument ...]\n", 227 getprogname()); 228 exit(1); 229 } 230 231 char * 232 read_btfile(const char *filename, size_t *len) 233 { 234 FILE *fp; 235 char *fcontent; 236 struct stat st; 237 size_t fsize; 238 239 if (stat(filename, &st)) 240 err(1, "can't stat '%s'", filename); 241 242 fsize = st.st_size; 243 fcontent = malloc(fsize + 1); 244 if (fcontent == NULL) 245 err(1, "malloc"); 246 247 fp = fopen(filename, "r"); 248 if (fp == NULL) 249 err(1, "can't open '%s'", filename); 250 251 if (fread(fcontent, 1, fsize, fp) != fsize) 252 err(1, "can't read '%s'", filename); 253 fcontent[fsize] = '\0'; 254 255 fclose(fp); 256 *len = fsize; 257 return fcontent; 258 } 259 260 void 261 dtpi_cache(int fd) 262 { 263 struct dtioc_probe dtpr; 264 265 if (dt_dtpis != NULL) 266 return; 267 268 memset(&dtpr, 0, sizeof(dtpr)); 269 if (ioctl(fd, DTIOCGPLIST, &dtpr)) 270 err(1, "DTIOCGPLIST"); 271 272 dt_ndtpi = dtpr.dtpr_size / sizeof(*dt_dtpis); 273 dt_dtpis = reallocarray(NULL, dt_ndtpi, sizeof(*dt_dtpis)); 274 if (dt_dtpis == NULL) 275 err(1, NULL); 276 277 dtpr.dtpr_probes = dt_dtpis; 278 if (ioctl(fd, DTIOCGPLIST, &dtpr)) 279 err(1, "DTIOCGPLIST"); 280 } 281 282 void 283 dtai_cache(int fd, struct dtioc_probe_info *dtpi) 284 { 285 struct dtioc_arg dtar; 286 287 if (dt_args == NULL) { 288 dt_args = calloc(dt_ndtpi, sizeof(*dt_args)); 289 if (dt_args == NULL) 290 err(1, NULL); 291 } 292 293 if (dt_args[dtpi->dtpi_pbn - 1] != NULL) 294 return; 295 296 dt_args[dtpi->dtpi_pbn - 1] = reallocarray(NULL, dtpi->dtpi_nargs, 297 sizeof(**dt_args)); 298 if (dt_args[dtpi->dtpi_pbn - 1] == NULL) 299 err(1, NULL); 300 301 dtar.dtar_pbn = dtpi->dtpi_pbn; 302 dtar.dtar_size = dtpi->dtpi_nargs * sizeof(**dt_args); 303 dtar.dtar_args = dt_args[dtpi->dtpi_pbn - 1]; 304 if (ioctl(fd, DTIOCGARGS, &dtar)) 305 err(1, "DTIOCGARGS"); 306 } 307 308 void 309 dtpi_print_list(int fd) 310 { 311 struct dtioc_probe_info *dtpi; 312 struct dtioc_arg_info *dtai; 313 size_t i, j; 314 315 dtpi = dt_dtpis; 316 for (i = 0; i < dt_ndtpi; i++, dtpi++) { 317 printf("%s:%s:%s", dtpi->dtpi_prov, dtpi_func(dtpi), 318 dtpi->dtpi_name); 319 if (strncmp(dtpi->dtpi_prov, "tracepoint", DTNAMESIZE) == 0) { 320 dtai_cache(fd, dtpi); 321 dtai = dt_args[dtpi->dtpi_pbn - 1]; 322 printf("("); 323 for (j = 0; j < dtpi->dtpi_nargs; j++, dtai++) { 324 if (j > 0) 325 printf(", "); 326 printf("%s", dtai->dtai_argtype); 327 } 328 printf(")"); 329 } 330 printf("\n"); 331 } 332 } 333 334 const char * 335 dtpi_func(struct dtioc_probe_info *dtpi) 336 { 337 char *sysnb, func[DTNAMESIZE]; 338 const char *errstr; 339 int idx; 340 341 if (strncmp(dtpi->dtpi_prov, "syscall", DTNAMESIZE)) 342 return dtpi->dtpi_func; 343 344 /* Translate syscall names */ 345 strlcpy(func, dtpi->dtpi_func, sizeof(func)); 346 sysnb = func; 347 if (strsep(&sysnb, "%") == NULL) 348 return dtpi->dtpi_func; 349 350 idx = strtonum(sysnb, 1, SYS_MAXSYSCALL, &errstr); 351 if (errstr != NULL) 352 return dtpi->dtpi_func; 353 354 return syscallnames[idx]; 355 } 356 357 int 358 dtpi_is_unit(const char *unit) 359 { 360 return !strncmp("hz", unit, sizeof("hz")); 361 } 362 363 struct dtioc_probe_info * 364 dtpi_get_by_value(const char *prov, const char *func, const char *name) 365 { 366 struct dtioc_probe_info *dtpi; 367 size_t i; 368 369 dtpi = dt_dtpis; 370 for (i = 0; i < dt_ndtpi; i++, dtpi++) { 371 if (prov != NULL && 372 strncmp(prov, dtpi->dtpi_prov, DTNAMESIZE)) 373 continue; 374 375 if (func != NULL) { 376 if (dtpi_is_unit(func)) 377 return dtpi; 378 379 if (strncmp(func, dtpi_func(dtpi), DTNAMESIZE)) 380 continue; 381 } 382 383 if (strncmp(name, dtpi->dtpi_name, DTNAMESIZE)) 384 continue; 385 386 debug("matched probe %s:%s:%s\n", dtpi->dtpi_prov, 387 dtpi_func(dtpi), dtpi->dtpi_name); 388 return dtpi; 389 } 390 391 return NULL; 392 } 393 394 void 395 rules_do(int fd) 396 { 397 struct sigaction sa; 398 399 memset(&sa, 0, sizeof(sa)); 400 sigemptyset(&sa.sa_mask); 401 sa.sa_flags = 0; 402 sa.sa_handler = signal_handler; 403 if (sigaction(SIGINT, &sa, NULL)) 404 err(1, "sigaction"); 405 if (sigaction(SIGTERM, &sa, NULL)) 406 err(1, "sigaction"); 407 408 rules_setup(fd); 409 410 while (!quit_pending && g_nprobes > 0) { 411 static struct dt_evt devtbuf[64]; 412 ssize_t rlen; 413 size_t i; 414 415 rlen = read(fd, devtbuf, sizeof(devtbuf) - 1); 416 if (rlen == -1) { 417 if (errno == EINTR && quit_pending) { 418 printf("\n"); 419 break; 420 } 421 err(1, "read"); 422 } 423 424 if ((rlen % sizeof(struct dt_evt)) != 0) 425 err(1, "incorrect read"); 426 427 for (i = 0; i < rlen / sizeof(struct dt_evt); i++) 428 rules_apply(fd, &devtbuf[i]); 429 } 430 431 rules_teardown(fd); 432 433 if (verbose && fd != -1) { 434 struct dtioc_stat dtst; 435 436 memset(&dtst, 0, sizeof(dtst)); 437 if (ioctl(fd, DTIOCGSTATS, &dtst)) 438 warn("DTIOCGSTATS"); 439 440 printf("%llu events read\n", dtst.dtst_readevt); 441 printf("%llu events dropped\n", dtst.dtst_dropevt); 442 printf("%llu events filtered\n", bt_filtered); 443 } 444 } 445 446 void 447 rules_setup(int fd) 448 { 449 struct dtioc_probe_info *dtpi; 450 struct dtioc_req *dtrq; 451 struct bt_rule *r, *rbegin = NULL; 452 struct bt_probe *bp; 453 struct bt_stmt *bs; 454 struct bt_arg *ba; 455 int dokstack = 0, on = 1; 456 uint64_t evtflags; 457 458 TAILQ_FOREACH(r, &g_rules, br_next) { 459 evtflags = 0; 460 461 if (r->br_filter != NULL && 462 r->br_filter->bf_condition != NULL) { 463 464 bs = r->br_filter->bf_condition; 465 ba = SLIST_FIRST(&bs->bs_args); 466 467 evtflags |= ba2dtflags(ba); 468 } 469 470 SLIST_FOREACH(bs, &r->br_action, bs_next) { 471 SLIST_FOREACH(ba, &bs->bs_args, ba_next) 472 evtflags |= ba2dtflags(ba); 473 474 /* Also check the value for map/hist insertion */ 475 switch (bs->bs_act) { 476 case B_AC_BUCKETIZE: 477 case B_AC_INSERT: 478 ba = (struct bt_arg *)bs->bs_var; 479 evtflags |= ba2dtflags(ba); 480 break; 481 default: 482 break; 483 } 484 } 485 486 SLIST_FOREACH(bp, &r->br_probes, bp_next) { 487 debug("parsed probe '%s'", debug_probe_name(bp)); 488 debug_dump_filter(r); 489 490 if (bp->bp_type != B_PT_PROBE) { 491 if (bp->bp_type == B_PT_BEGIN) 492 rbegin = r; 493 continue; 494 } 495 496 dtpi_cache(fd); 497 dtpi = dtpi_get_by_value(bp->bp_prov, bp->bp_func, 498 bp->bp_name); 499 if (dtpi == NULL) { 500 errx(1, "probe '%s:%s:%s' not found", 501 bp->bp_prov, bp->bp_func, bp->bp_name); 502 } 503 504 dtrq = calloc(1, sizeof(*dtrq)); 505 if (dtrq == NULL) 506 err(1, "dtrq: 1alloc"); 507 508 bp->bp_pbn = dtpi->dtpi_pbn; 509 dtrq->dtrq_pbn = dtpi->dtpi_pbn; 510 dtrq->dtrq_rate = bp->bp_rate; 511 dtrq->dtrq_evtflags = evtflags; 512 if (dtrq->dtrq_evtflags & DTEVT_KSTACK) 513 dokstack = 1; 514 bp->bp_cookie = dtrq; 515 } 516 } 517 518 if (dokstack) 519 kelf_open(); 520 521 /* Initialize "fake" event for BEGIN/END */ 522 bt_devt.dtev_pbn = -1; 523 strlcpy(bt_devt.dtev_comm, getprogname(), sizeof(bt_devt.dtev_comm)); 524 bt_devt.dtev_pid = getpid(); 525 bt_devt.dtev_tid = getthrid(); 526 clock_gettime(CLOCK_REALTIME, &bt_devt.dtev_tsp); 527 528 if (rbegin) 529 rule_eval(rbegin, &bt_devt); 530 531 /* Enable all probes */ 532 TAILQ_FOREACH(r, &g_rules, br_next) { 533 SLIST_FOREACH(bp, &r->br_probes, bp_next) { 534 if (bp->bp_type != B_PT_PROBE) 535 continue; 536 537 dtrq = bp->bp_cookie; 538 if (ioctl(fd, DTIOCPRBENABLE, dtrq)) 539 err(1, "DTIOCPRBENABLE"); 540 } 541 } 542 543 if (g_nprobes > 0) { 544 if (ioctl(fd, DTIOCRECORD, &on)) 545 err(1, "DTIOCRECORD"); 546 } 547 } 548 549 void 550 rules_apply(int fd, struct dt_evt *dtev) 551 { 552 struct bt_rule *r; 553 struct bt_probe *bp; 554 555 TAILQ_FOREACH(r, &g_rules, br_next) { 556 SLIST_FOREACH(bp, &r->br_probes, bp_next) { 557 if (bp->bp_type != B_PT_PROBE || 558 bp->bp_pbn != dtev->dtev_pbn) 559 continue; 560 561 dtai_cache(fd, &dt_dtpis[dtev->dtev_pbn - 1]); 562 rule_eval(r, dtev); 563 } 564 } 565 } 566 567 void 568 rules_teardown(int fd) 569 { 570 struct dtioc_req *dtrq; 571 struct bt_probe *bp; 572 struct bt_rule *r, *rend = NULL; 573 int dokstack = 0, off = 0; 574 575 if (g_nprobes > 0) { 576 if (ioctl(fd, DTIOCRECORD, &off)) 577 err(1, "DTIOCRECORD"); 578 } 579 580 TAILQ_FOREACH(r, &g_rules, br_next) { 581 SLIST_FOREACH(bp, &r->br_probes, bp_next) { 582 if (bp->bp_type != B_PT_PROBE) { 583 if (bp->bp_type == B_PT_END) 584 rend = r; 585 continue; 586 } 587 588 dtrq = bp->bp_cookie; 589 if (ioctl(fd, DTIOCPRBDISABLE, dtrq)) 590 err(1, "DTIOCPRBDISABLE"); 591 if (dtrq->dtrq_evtflags & DTEVT_KSTACK) 592 dokstack = 1; 593 } 594 } 595 596 if (dokstack) 597 kelf_close(); 598 599 /* Update "fake" event for BEGIN/END */ 600 clock_gettime(CLOCK_REALTIME, &bt_devt.dtev_tsp); 601 602 if (rend) 603 rule_eval(rend, &bt_devt); 604 605 /* Print non-empty map & hist */ 606 TAILQ_FOREACH(r, &g_rules, br_next) 607 rule_printmaps(r); 608 } 609 610 void 611 rule_eval(struct bt_rule *r, struct dt_evt *dtev) 612 { 613 struct bt_stmt *bs; 614 struct bt_probe *bp; 615 616 SLIST_FOREACH(bp, &r->br_probes, bp_next) { 617 debug("eval rule '%s'", debug_probe_name(bp)); 618 debug_dump_filter(r); 619 } 620 621 if (r->br_filter != NULL && r->br_filter->bf_condition != NULL) { 622 if (stmt_test(r->br_filter->bf_condition, dtev) == false) { 623 bt_filtered++; 624 return; 625 } 626 } 627 628 SLIST_FOREACH(bs, &r->br_action, bs_next) { 629 if ((bs->bs_act == B_AC_TEST) && stmt_test(bs, dtev) == true) { 630 struct bt_stmt *bbs = (struct bt_stmt *)bs->bs_var; 631 632 while (bbs != NULL) { 633 stmt_eval(bbs, dtev); 634 bbs = SLIST_NEXT(bbs, bs_next); 635 } 636 637 continue; 638 } 639 640 stmt_eval(bs, dtev); 641 } 642 } 643 644 void 645 rule_printmaps(struct bt_rule *r) 646 { 647 struct bt_stmt *bs; 648 649 SLIST_FOREACH(bs, &r->br_action, bs_next) { 650 struct bt_arg *ba; 651 652 SLIST_FOREACH(ba, &bs->bs_args, ba_next) { 653 struct bt_var *bv = ba->ba_value; 654 struct map *map; 655 656 if (ba->ba_type != B_AT_MAP && ba->ba_type != B_AT_HIST) 657 continue; 658 659 map = (struct map *)bv->bv_value; 660 if (map == NULL) 661 continue; 662 663 if (ba->ba_type == B_AT_MAP) 664 map_print(map, SIZE_T_MAX, bv_name(bv)); 665 else 666 hist_print((struct hist *)map, bv_name(bv)); 667 map_clear(map); 668 bv->bv_value = NULL; 669 } 670 } 671 } 672 673 time_t 674 builtin_gettime(struct dt_evt *dtev) 675 { 676 struct timespec ts; 677 678 if (dtev == NULL) { 679 clock_gettime(CLOCK_REALTIME, &ts); 680 return ts.tv_sec; 681 } 682 683 return dtev->dtev_tsp.tv_sec; 684 } 685 686 static inline uint64_t 687 TIMESPEC_TO_NSEC(struct timespec *ts) 688 { 689 return (ts->tv_sec * 1000000000L + ts->tv_nsec); 690 } 691 692 uint64_t 693 builtin_nsecs(struct dt_evt *dtev) 694 { 695 struct timespec ts; 696 697 if (dtev == NULL) { 698 clock_gettime(CLOCK_REALTIME, &ts); 699 return TIMESPEC_TO_NSEC(&ts); 700 } 701 702 return TIMESPEC_TO_NSEC(&dtev->dtev_tsp); 703 } 704 705 const char * 706 builtin_stack(struct dt_evt *dtev, int kernel) 707 { 708 struct stacktrace *st = &dtev->dtev_kstack; 709 static char buf[4096], *bp; 710 size_t i; 711 int sz; 712 713 if (!kernel) 714 return ""; 715 if (st->st_count == 0) 716 return "\nuserland\n"; 717 718 buf[0] = '\0'; 719 bp = buf; 720 sz = sizeof(buf); 721 for (i = 0; i < st->st_count; i++) { 722 int l; 723 724 l = kelf_snprintsym(bp, sz - 1, st->st_pc[i]); 725 if (l < 0) 726 break; 727 if (l >= sz - 1) { 728 bp += sz - 1; 729 sz = 1; 730 break; 731 } 732 bp += l; 733 sz -= l; 734 } 735 snprintf(bp, sz, "\nkernel\n"); 736 737 return buf; 738 } 739 740 const char * 741 builtin_arg(struct dt_evt *dtev, enum bt_argtype dat) 742 { 743 static char buf[sizeof("18446744073709551615")]; /* UINT64_MAX */ 744 unsigned int argn; 745 struct dtioc_arg_info *dtai; 746 const char *argtype, *fmt; 747 long value; 748 749 dtai = dt_args[dtev->dtev_pbn - 1]; 750 argn = dat - B_AT_BI_ARG0; 751 argtype = dtai[argn].dtai_argtype; 752 753 if (strncmp(argtype, "int", DTNAMESIZE) == 0) { 754 fmt = "%d"; 755 value = (int)dtev->dtev_args[argn]; 756 } else { 757 fmt = "%lu"; 758 value = dtev->dtev_args[argn]; 759 } 760 761 snprintf(buf, sizeof(buf), fmt, dtev->dtev_args[argn]); 762 763 return buf; 764 } 765 766 void 767 stmt_eval(struct bt_stmt *bs, struct dt_evt *dtev) 768 { 769 switch (bs->bs_act) { 770 case B_AC_BUCKETIZE: 771 stmt_bucketize(bs, dtev); 772 break; 773 case B_AC_CLEAR: 774 stmt_clear(bs); 775 break; 776 case B_AC_DELETE: 777 stmt_delete(bs, dtev); 778 break; 779 case B_AC_EXIT: 780 exit(0); 781 break; 782 case B_AC_INSERT: 783 stmt_insert(bs, dtev); 784 break; 785 case B_AC_PRINT: 786 stmt_print(bs, dtev); 787 break; 788 case B_AC_PRINTF: 789 stmt_printf(bs, dtev); 790 break; 791 case B_AC_STORE: 792 stmt_store(bs, dtev); 793 break; 794 case B_AC_TEST: 795 /* done before */ 796 break; 797 case B_AC_TIME: 798 stmt_time(bs, dtev); 799 break; 800 case B_AC_ZERO: 801 stmt_zero(bs); 802 break; 803 default: 804 xabort("no handler for action type %d", bs->bs_act); 805 } 806 } 807 808 /* 809 * Increment a bucket: { @h = hist(v); } or { @h = lhist(v, min, max, step); } 810 * 811 * In this case 'h' is represented by `bv' and '(min, max, step)' by `brange'. 812 */ 813 void 814 stmt_bucketize(struct bt_stmt *bs, struct dt_evt *dtev) 815 { 816 struct bt_arg *brange, *bhist = SLIST_FIRST(&bs->bs_args); 817 struct bt_arg *bval = (struct bt_arg *)bs->bs_var; 818 struct bt_var *bv = bhist->ba_value; 819 const char *bucket; 820 long step = 0; 821 822 assert(bhist->ba_type == B_AT_HIST); 823 assert(SLIST_NEXT(bval, ba_next) == NULL); 824 825 brange = bhist->ba_key; 826 bucket = ba2bucket(bval, brange, dtev, &step); 827 if (bucket == NULL) { 828 debug("hist=%p '%s' value=%lu out of range\n", bv->bv_value, 829 bv_name(bv), ba2long(bval, dtev)); 830 return; 831 } 832 debug("hist=%p '%s' increment bucket '%s'\n", bv->bv_value, 833 bv_name(bv), bucket); 834 835 bv->bv_value = (struct bt_arg *) 836 hist_increment((struct hist *)bv->bv_value, bucket, step); 837 bv->bv_type = B_VT_HIST; 838 } 839 840 841 /* 842 * Empty a map: { clear(@map); } 843 */ 844 void 845 stmt_clear(struct bt_stmt *bs) 846 { 847 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args); 848 struct bt_var *bv = ba->ba_value; 849 struct map *map; 850 851 assert(bs->bs_var == NULL); 852 assert(ba->ba_type == B_AT_VAR); 853 854 map = (struct map *)bv->bv_value; 855 if (map == NULL) 856 return; 857 858 if (bv->bv_type != B_VT_MAP && bv->bv_type != B_VT_HIST) 859 errx(1, "invalid variable type for clear(%s)", ba_name(ba)); 860 861 map_clear(map); 862 bv->bv_value = NULL; 863 864 debug("map=%p '%s' clear\n", map, bv_name(bv)); 865 } 866 867 /* 868 * Map delete: { delete(@map[key]); } 869 * 870 * In this case 'map' is represented by `bv' and 'key' by `bkey'. 871 */ 872 void 873 stmt_delete(struct bt_stmt *bs, struct dt_evt *dtev) 874 { 875 struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args); 876 struct bt_var *bv = bmap->ba_value; 877 struct map *map; 878 const char *hash; 879 880 assert(bmap->ba_type == B_AT_MAP); 881 assert(bs->bs_var == NULL); 882 883 map = (struct map *)bv->bv_value; 884 if (map == NULL) 885 return; 886 887 bkey = bmap->ba_key; 888 hash = ba2hash(bkey, dtev); 889 debug("map=%p '%s' delete key=%p '%s'\n", map, bv_name(bv), bkey, hash); 890 891 map_delete(map, hash); 892 } 893 894 /* 895 * Map insert: { @map[key] = 42; } 896 * 897 * In this case 'map' is represented by `bv', 'key' by `bkey' and 898 * '42' by `bval'. 899 */ 900 void 901 stmt_insert(struct bt_stmt *bs, struct dt_evt *dtev) 902 { 903 struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args); 904 struct bt_arg *bval = (struct bt_arg *)bs->bs_var; 905 struct bt_var *bv = bmap->ba_value; 906 struct map *map; 907 const char *hash; 908 909 assert(bmap->ba_type == B_AT_MAP); 910 assert(SLIST_NEXT(bval, ba_next) == NULL); 911 912 bkey = bmap->ba_key; 913 hash = ba2hash(bkey, dtev); 914 915 /* map is NULL before first insert or after clear() */ 916 map = (struct map *)bv->bv_value; 917 map = map_insert(map, hash, bval, dtev); 918 919 debug("map=%p '%s' insert key=%p '%s' bval=%p\n", map, 920 bv_name(bv), bkey, hash, bval); 921 922 bv->bv_value = (struct bt_arg *)map; 923 bv->bv_type = B_VT_MAP; 924 } 925 926 /* 927 * Print variables: { print(890); print(@map[, 8]); print(comm); } 928 * 929 * In this case the global variable 'map' is pointed at by `ba' 930 * and '8' is represented by `btop'. 931 */ 932 void 933 stmt_print(struct bt_stmt *bs, struct dt_evt *dtev) 934 { 935 struct bt_arg *btop, *ba = SLIST_FIRST(&bs->bs_args); 936 struct bt_var *bv = ba->ba_value; 937 struct map *map; 938 size_t top = SIZE_T_MAX; 939 940 assert(bs->bs_var == NULL); 941 942 /* Parse optional `top' argument. */ 943 btop = SLIST_NEXT(ba, ba_next); 944 if (btop != NULL) { 945 assert(SLIST_NEXT(btop, ba_next) == NULL); 946 top = ba2long(btop, dtev); 947 } 948 949 /* Static argument. */ 950 if (ba->ba_type != B_AT_VAR) { 951 assert(btop == NULL); 952 printf("%s\n", ba2str(ba, dtev)); 953 return; 954 } 955 956 map = (struct map *)bv->bv_value; 957 if (map == NULL) 958 return; 959 960 debug("map=%p '%s' print (top=%d)\n", bv->bv_value, bv_name(bv), top); 961 962 if (bv->bv_type == B_VT_MAP) 963 map_print(map, top, bv_name(bv)); 964 else if (bv->bv_type == B_VT_HIST) 965 hist_print((struct hist *)map, bv_name(bv)); 966 else 967 printf("%s\n", ba2str(ba, dtev)); 968 } 969 970 /* 971 * Variable store: { @var = 3; } 972 * 973 * In this case '3' is represented by `ba', the argument of a STORE 974 * action. 975 * 976 * If the argument depends of the value of an event (builtin) or is 977 * the result of an operation, its evaluation is stored in a new `ba'. 978 */ 979 void 980 stmt_store(struct bt_stmt *bs, struct dt_evt *dtev) 981 { 982 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args); 983 struct bt_var *bv = bs->bs_var; 984 985 assert(SLIST_NEXT(ba, ba_next) == NULL); 986 987 switch (ba->ba_type) { 988 case B_AT_STR: 989 bv->bv_value = ba; 990 bv->bv_type = B_VT_STR; 991 break; 992 case B_AT_LONG: 993 bv->bv_value = ba; 994 bv->bv_type = B_VT_LONG; 995 break; 996 case B_AT_BI_NSECS: 997 bv->bv_value = ba_new(builtin_nsecs(dtev), B_AT_LONG); 998 bv->bv_type = B_VT_LONG; 999 break; 1000 case B_AT_BI_ARG0 ... B_AT_BI_ARG9: 1001 /* FALLTHROUGH */ 1002 case B_AT_OP_PLUS ... B_AT_OP_LOR: 1003 bv->bv_value = ba_new(ba2long(ba, dtev), B_AT_LONG); 1004 bv->bv_type = B_VT_LONG; 1005 break; 1006 case B_AT_FN_STR: 1007 bv->bv_value = ba_new(ba2str(ba, dtev), B_AT_STR); 1008 bv->bv_type = B_VT_STR; 1009 break; 1010 default: 1011 xabort("store not implemented for type %d", ba->ba_type); 1012 } 1013 1014 debug("bv=%p var '%s' store (%p)\n", bv, bv_name(bv), bv->bv_value); 1015 } 1016 1017 /* 1018 * String conversion { str($1); string($1, 3); } 1019 * 1020 * Since fn_str is currently only called in ba2str, *buf should be a pointer 1021 * to the static buffer provided by ba2str. 1022 */ 1023 struct bt_arg * 1024 fn_str(struct bt_arg *ba, struct dt_evt *dtev, char *buf) 1025 { 1026 struct bt_arg *arg, *index; 1027 ssize_t len = STRLEN; 1028 1029 assert(ba->ba_type == B_AT_FN_STR); 1030 1031 arg = (struct bt_arg*)ba->ba_value; 1032 assert(arg != NULL); 1033 1034 index = SLIST_NEXT(arg, ba_next); 1035 if (index != NULL) { 1036 /* Should have only 1 optional argument. */ 1037 assert(SLIST_NEXT(index, ba_next) == NULL); 1038 len = MINIMUM(ba2long(index, dtev) + 1, STRLEN); 1039 } 1040 1041 /* All negative lengths behave the same as a zero length. */ 1042 if (len < 1) 1043 return ba_new("", B_AT_STR); 1044 1045 strlcpy(buf, ba2str(arg, dtev), len); 1046 return ba_new(buf, B_AT_STR); 1047 } 1048 1049 /* 1050 * Expression test: { if (expr) stmt; } 1051 */ 1052 bool 1053 stmt_test(struct bt_stmt *bs, struct dt_evt *dtev) 1054 { 1055 struct bt_arg *ba; 1056 1057 if (bs == NULL) 1058 return true; 1059 1060 ba = SLIST_FIRST(&bs->bs_args); 1061 1062 return baexpr2long(ba, dtev) != 0; 1063 } 1064 1065 /* 1066 * Print time: { time("%H:%M:%S"); } 1067 */ 1068 void 1069 stmt_time(struct bt_stmt *bs, struct dt_evt *dtev) 1070 { 1071 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args); 1072 time_t time; 1073 struct tm *tm; 1074 char buf[64]; 1075 1076 assert(bs->bs_var == NULL); 1077 assert(ba->ba_type == B_AT_STR); 1078 assert(strlen(ba2str(ba, dtev)) < (sizeof(buf) - 1)); 1079 1080 time = builtin_gettime(dtev); 1081 tm = localtime(&time); 1082 strftime(buf, sizeof(buf), ba2str(ba, dtev), tm); 1083 printf("%s", buf); 1084 } 1085 1086 /* 1087 * Set entries to 0: { zero(@map); } 1088 */ 1089 void 1090 stmt_zero(struct bt_stmt *bs) 1091 { 1092 struct bt_arg *ba = SLIST_FIRST(&bs->bs_args); 1093 struct bt_var *bv = ba->ba_value; 1094 struct map *map; 1095 1096 assert(bs->bs_var == NULL); 1097 assert(ba->ba_type == B_AT_VAR); 1098 1099 map = (struct map *)bv->bv_value; 1100 if (map == NULL) 1101 return; 1102 1103 if (bv->bv_type != B_VT_MAP && bv->bv_type != B_VT_HIST) 1104 errx(1, "invalid variable type for zero(%s)", ba_name(ba)); 1105 1106 map_zero(map); 1107 1108 debug("map=%p '%s' zero\n", map, bv_name(bv)); 1109 } 1110 1111 struct bt_arg * 1112 ba_read(struct bt_arg *ba) 1113 { 1114 struct bt_var *bv = ba->ba_value; 1115 1116 assert(ba->ba_type == B_AT_VAR); 1117 1118 debug("bv=%p read '%s' (%p)\n", bv, bv_name(bv), bv->bv_value); 1119 1120 /* Handle map/hist access after clear(). */ 1121 if (bv->bv_value == NULL) 1122 return &g_nullba; 1123 1124 return bv->bv_value; 1125 } 1126 1127 const char * 1128 ba2hash(struct bt_arg *ba, struct dt_evt *dtev) 1129 { 1130 static char buf[KLEN]; 1131 char *hash; 1132 int l, len; 1133 1134 buf[0] = '\0'; 1135 l = snprintf(buf, sizeof(buf), "%s", ba2str(ba, dtev)); 1136 if (l < 0 || (size_t)l > sizeof(buf)) { 1137 warn("string too long %d > %lu", l, sizeof(buf)); 1138 return buf; 1139 } 1140 1141 len = 0; 1142 while ((ba = SLIST_NEXT(ba, ba_next)) != NULL) { 1143 len += l; 1144 hash = buf + len; 1145 1146 l = snprintf(hash, sizeof(buf) - len, ", %s", ba2str(ba, dtev)); 1147 if (l < 0 || (size_t)l > (sizeof(buf) - len)) { 1148 warn("hash too long %d > %lu", l + len, sizeof(buf)); 1149 break; 1150 } 1151 } 1152 1153 return buf; 1154 } 1155 1156 static unsigned long 1157 next_pow2(unsigned long x) 1158 { 1159 size_t i; 1160 1161 x--; 1162 for (i = 0; i < (sizeof(x) * 8) - 1; i++) 1163 x |= (x >> 1); 1164 1165 return x + 1; 1166 } 1167 1168 /* 1169 * Return the ceiling value the interval holding `ba' or NULL if it is 1170 * out of the (min, max) values. 1171 */ 1172 const char * 1173 ba2bucket(struct bt_arg *ba, struct bt_arg *brange, struct dt_evt *dtev, 1174 long *pstep) 1175 { 1176 static char buf[KLEN]; 1177 long val, bucket; 1178 int l; 1179 1180 val = ba2long(ba, dtev); 1181 if (brange == NULL) 1182 bucket = next_pow2(val); 1183 else { 1184 long min, max, step; 1185 1186 assert(brange->ba_type == B_AT_LONG); 1187 min = ba2long(brange, NULL); 1188 1189 brange = SLIST_NEXT(brange, ba_next); 1190 assert(brange->ba_type == B_AT_LONG); 1191 max = ba2long(brange, NULL); 1192 1193 if ((val < min) || (val > max)) 1194 return NULL; 1195 1196 brange = SLIST_NEXT(brange, ba_next); 1197 assert(brange->ba_type == B_AT_LONG); 1198 step = ba2long(brange, NULL); 1199 1200 bucket = ((val / step) + 1) * step; 1201 *pstep = step; 1202 } 1203 1204 buf[0] = '\0'; 1205 l = snprintf(buf, sizeof(buf), "%lu", bucket); 1206 if (l < 0 || (size_t)l > sizeof(buf)) { 1207 warn("string too long %d > %lu", l, sizeof(buf)); 1208 return buf; 1209 } 1210 1211 return buf; 1212 } 1213 1214 /* 1215 * Evaluate the operation encoded in `ba' and return its result. 1216 */ 1217 long 1218 baexpr2long(struct bt_arg *ba, struct dt_evt *dtev) 1219 { 1220 static long recursions; 1221 struct bt_arg *lhs, *rhs; 1222 long lval, rval, result; 1223 1224 if (++recursions >= __MAXOPERANDS) 1225 errx(1, "too many operands (>%d) in expression", __MAXOPERANDS); 1226 1227 lhs = ba->ba_value; 1228 rhs = SLIST_NEXT(lhs, ba_next); 1229 1230 /* 1231 * String comparison also use '==' and '!='. 1232 */ 1233 if (lhs->ba_type == B_AT_STR || 1234 (rhs != NULL && rhs->ba_type == B_AT_STR)) { 1235 char lstr[STRLEN], rstr[STRLEN]; 1236 1237 strlcpy(lstr, ba2str(lhs, dtev), sizeof(lstr)); 1238 strlcpy(rstr, ba2str(rhs, dtev), sizeof(rstr)); 1239 1240 result = strncmp(lstr, rstr, STRLEN) == 0; 1241 1242 switch (ba->ba_type) { 1243 case B_AT_OP_EQ: 1244 break; 1245 case B_AT_OP_NE: 1246 result = !result; 1247 break; 1248 default: 1249 warnx("operation '%d' unsupported on strings", 1250 ba->ba_type); 1251 result = 1; 1252 } 1253 1254 debug("ba=%p eval '(%s %s %s) = %d'\n", ba, lstr, ba_name(ba), 1255 rstr, result); 1256 1257 goto out; 1258 } 1259 1260 lval = ba2long(lhs, dtev); 1261 if (rhs == NULL) { 1262 rval = 0; 1263 } else { 1264 assert(SLIST_NEXT(rhs, ba_next) == NULL); 1265 rval = ba2long(rhs, dtev); 1266 } 1267 1268 switch (ba->ba_type) { 1269 case B_AT_OP_PLUS: 1270 result = lval + rval; 1271 break; 1272 case B_AT_OP_MINUS: 1273 result = lval - rval; 1274 break; 1275 case B_AT_OP_MULT: 1276 result = lval * rval; 1277 break; 1278 case B_AT_OP_DIVIDE: 1279 result = lval / rval; 1280 break; 1281 case B_AT_OP_BAND: 1282 result = lval & rval; 1283 break; 1284 case B_AT_OP_XOR: 1285 result = lval ^ rval; 1286 break; 1287 case B_AT_OP_BOR: 1288 result = lval | rval; 1289 break; 1290 case B_AT_OP_EQ: 1291 result = (lval == rval); 1292 break; 1293 case B_AT_OP_NE: 1294 result = (lval != rval); 1295 break; 1296 case B_AT_OP_LE: 1297 result = (lval <= rval); 1298 break; 1299 case B_AT_OP_LT: 1300 result = (lval < rval); 1301 break; 1302 case B_AT_OP_GE: 1303 result = (lval >= rval); 1304 break; 1305 case B_AT_OP_GT: 1306 result = (lval > rval); 1307 break; 1308 case B_AT_OP_LAND: 1309 result = (lval && rval); 1310 break; 1311 case B_AT_OP_LOR: 1312 result = (lval || rval); 1313 break; 1314 default: 1315 xabort("unsupported operation %d", ba->ba_type); 1316 } 1317 1318 debug("ba=%p eval '(%ld %s %ld) = %d'\n", ba, lval, ba_name(ba), 1319 rval, result); 1320 1321 out: 1322 --recursions; 1323 1324 return result; 1325 } 1326 1327 const char * 1328 ba_name(struct bt_arg *ba) 1329 { 1330 switch (ba->ba_type) { 1331 case B_AT_STR: 1332 return (const char *)ba->ba_value; 1333 case B_AT_LONG: 1334 return ba2str(ba, NULL); 1335 case B_AT_NIL: 1336 return "0"; 1337 case B_AT_VAR: 1338 case B_AT_MAP: 1339 case B_AT_HIST: 1340 break; 1341 case B_AT_BI_PID: 1342 return "pid"; 1343 case B_AT_BI_TID: 1344 return "tid"; 1345 case B_AT_BI_COMM: 1346 return "comm"; 1347 case B_AT_BI_CPU: 1348 return "cpu"; 1349 case B_AT_BI_NSECS: 1350 return "nsecs"; 1351 case B_AT_BI_KSTACK: 1352 return "kstack"; 1353 case B_AT_BI_USTACK: 1354 return "ustack"; 1355 case B_AT_BI_ARG0: 1356 return "arg0"; 1357 case B_AT_BI_ARG1: 1358 return "arg1"; 1359 case B_AT_BI_ARG2: 1360 return "arg2"; 1361 case B_AT_BI_ARG3: 1362 return "arg3"; 1363 case B_AT_BI_ARG4: 1364 return "arg4"; 1365 case B_AT_BI_ARG5: 1366 return "arg5"; 1367 case B_AT_BI_ARG6: 1368 return "arg6"; 1369 case B_AT_BI_ARG7: 1370 return "arg7"; 1371 case B_AT_BI_ARG8: 1372 return "arg8"; 1373 case B_AT_BI_ARG9: 1374 return "arg9"; 1375 case B_AT_BI_ARGS: 1376 return "args"; 1377 case B_AT_BI_RETVAL: 1378 return "retval"; 1379 case B_AT_BI_PROBE: 1380 return "probe"; 1381 case B_AT_FN_STR: 1382 return "str"; 1383 case B_AT_OP_PLUS: 1384 return "+"; 1385 case B_AT_OP_MINUS: 1386 return "-"; 1387 case B_AT_OP_MULT: 1388 return "*"; 1389 case B_AT_OP_DIVIDE: 1390 return "/"; 1391 case B_AT_OP_BAND: 1392 return "&"; 1393 case B_AT_OP_XOR: 1394 return "^"; 1395 case B_AT_OP_BOR: 1396 return "|"; 1397 case B_AT_OP_EQ: 1398 return "=="; 1399 case B_AT_OP_NE: 1400 return "!="; 1401 case B_AT_OP_LE: 1402 return "<="; 1403 case B_AT_OP_LT: 1404 return "<"; 1405 case B_AT_OP_GE: 1406 return ">="; 1407 case B_AT_OP_GT: 1408 return ">"; 1409 case B_AT_OP_LAND: 1410 return "&&"; 1411 case B_AT_OP_LOR: 1412 return "||"; 1413 default: 1414 xabort("unsupported type %d", ba->ba_type); 1415 } 1416 1417 assert(ba->ba_type == B_AT_VAR || ba->ba_type == B_AT_MAP || 1418 ba->ba_type == B_AT_HIST); 1419 1420 static char buf[64]; 1421 size_t sz; 1422 int l; 1423 1424 buf[0] = '@'; 1425 buf[1] = '\0'; 1426 sz = sizeof(buf) - 1; 1427 l = snprintf(buf+1, sz, "%s", bv_name(ba->ba_value)); 1428 if (l < 0 || (size_t)l > sz) { 1429 warn("string too long %d > %zu", l, sz); 1430 return buf; 1431 } 1432 1433 if (ba->ba_type == B_AT_MAP) { 1434 sz -= l; 1435 l = snprintf(buf+1+l, sz, "[%s]", ba_name(ba->ba_key)); 1436 if (l < 0 || (size_t)l > sz) { 1437 warn("string too long %d > %zu", l, sz); 1438 return buf; 1439 } 1440 } 1441 1442 return buf; 1443 } 1444 1445 /* 1446 * Return the representation of `ba' as long. 1447 */ 1448 long 1449 ba2long(struct bt_arg *ba, struct dt_evt *dtev) 1450 { 1451 struct bt_var *bv; 1452 long val; 1453 1454 switch (ba->ba_type) { 1455 case B_AT_LONG: 1456 val = (long)ba->ba_value; 1457 break; 1458 case B_AT_VAR: 1459 ba = ba_read(ba); 1460 val = (long)ba->ba_value; 1461 break; 1462 case B_AT_MAP: 1463 bv = ba->ba_value; 1464 /* Uninitialized map */ 1465 if (bv->bv_value == NULL) 1466 return 0; 1467 val = ba2long(map_get((struct map *)bv->bv_value, 1468 ba2str(ba->ba_key, dtev)), dtev); 1469 break; 1470 case B_AT_NIL: 1471 val = 0L; 1472 break; 1473 case B_AT_BI_PID: 1474 val = dtev->dtev_pid; 1475 break; 1476 case B_AT_BI_TID: 1477 val = dtev->dtev_tid; 1478 break; 1479 case B_AT_BI_CPU: 1480 val = dtev->dtev_cpu; 1481 break; 1482 case B_AT_BI_NSECS: 1483 val = builtin_nsecs(dtev); 1484 break; 1485 case B_AT_BI_ARG0 ... B_AT_BI_ARG9: 1486 val = dtev->dtev_args[ba->ba_type - B_AT_BI_ARG0]; 1487 break; 1488 case B_AT_BI_RETVAL: 1489 val = dtev->dtev_retval[0]; 1490 break; 1491 case B_AT_BI_PROBE: 1492 val = dtev->dtev_pbn; 1493 break; 1494 case B_AT_OP_PLUS ... B_AT_OP_LOR: 1495 val = baexpr2long(ba, dtev); 1496 break; 1497 default: 1498 xabort("no long conversion for type %d", ba->ba_type); 1499 } 1500 1501 return val; 1502 } 1503 1504 /* 1505 * Return the representation of `ba' as string. 1506 */ 1507 const char * 1508 ba2str(struct bt_arg *ba, struct dt_evt *dtev) 1509 { 1510 static char buf[STRLEN]; 1511 struct bt_var *bv; 1512 struct dtioc_probe_info *dtpi; 1513 const char *str; 1514 1515 buf[0] = '\0'; 1516 switch (ba->ba_type) { 1517 case B_AT_STR: 1518 str = (const char *)ba->ba_value; 1519 break; 1520 case B_AT_LONG: 1521 snprintf(buf, sizeof(buf), "%ld",(long)ba->ba_value); 1522 str = buf; 1523 break; 1524 case B_AT_NIL: 1525 str = ""; 1526 break; 1527 case B_AT_BI_KSTACK: 1528 str = builtin_stack(dtev, 1); 1529 break; 1530 case B_AT_BI_USTACK: 1531 str = builtin_stack(dtev, 0); 1532 break; 1533 case B_AT_BI_COMM: 1534 str = dtev->dtev_comm; 1535 break; 1536 case B_AT_BI_CPU: 1537 snprintf(buf, sizeof(buf), "%u", dtev->dtev_cpu); 1538 str = buf; 1539 break; 1540 case B_AT_BI_PID: 1541 snprintf(buf, sizeof(buf), "%d", dtev->dtev_pid); 1542 str = buf; 1543 break; 1544 case B_AT_BI_TID: 1545 snprintf(buf, sizeof(buf), "%d", dtev->dtev_tid); 1546 str = buf; 1547 break; 1548 case B_AT_BI_NSECS: 1549 snprintf(buf, sizeof(buf), "%llu", builtin_nsecs(dtev)); 1550 str = buf; 1551 break; 1552 case B_AT_BI_ARG0 ... B_AT_BI_ARG9: 1553 str = builtin_arg(dtev, ba->ba_type); 1554 break; 1555 case B_AT_BI_RETVAL: 1556 snprintf(buf, sizeof(buf), "%ld", (long)dtev->dtev_retval[0]); 1557 str = buf; 1558 break; 1559 case B_AT_BI_PROBE: 1560 dtpi = &dt_dtpis[dtev->dtev_pbn - 1]; 1561 if (dtpi != NULL) 1562 snprintf(buf, sizeof(buf), "%s:%s:%s", 1563 dtpi->dtpi_prov, dtpi_func(dtpi), dtpi->dtpi_name); 1564 else 1565 snprintf(buf, sizeof(buf), "%u", dtev->dtev_pbn); 1566 str = buf; 1567 break; 1568 case B_AT_MAP: 1569 bv = ba->ba_value; 1570 /* Uninitialized map */ 1571 if (bv->bv_value == NULL) { 1572 str = buf; 1573 break; 1574 } 1575 str = ba2str(map_get((struct map *)bv->bv_value, 1576 ba2str(ba->ba_key, dtev)), dtev); 1577 break; 1578 case B_AT_VAR: 1579 str = ba2str(ba_read(ba), dtev); 1580 break; 1581 case B_AT_FN_STR: 1582 str = (const char*)(fn_str(ba, dtev, buf))->ba_value; 1583 break; 1584 case B_AT_OP_PLUS ... B_AT_OP_LOR: 1585 snprintf(buf, sizeof(buf), "%ld", ba2long(ba, dtev)); 1586 str = buf; 1587 break; 1588 case B_AT_MF_COUNT: 1589 case B_AT_MF_MAX: 1590 case B_AT_MF_MIN: 1591 case B_AT_MF_SUM: 1592 assert(0); 1593 break; 1594 default: 1595 xabort("no string conversion for type %d", ba->ba_type); 1596 } 1597 1598 return str; 1599 } 1600 1601 /* 1602 * Return dt(4) flags indicating which data should be recorded by the 1603 * kernel, if any, for a given `ba'. 1604 */ 1605 int 1606 ba2dtflags(struct bt_arg *ba) 1607 { 1608 static long recursions; 1609 struct bt_arg *bval; 1610 int flags = 0; 1611 1612 if (++recursions >= __MAXOPERANDS) 1613 errx(1, "too many operands (>%d) in expression", __MAXOPERANDS); 1614 1615 do { 1616 if (ba->ba_type == B_AT_MAP) 1617 bval = ba->ba_key; 1618 else 1619 bval = ba; 1620 1621 switch (bval->ba_type) { 1622 case B_AT_STR: 1623 case B_AT_LONG: 1624 case B_AT_VAR: 1625 case B_AT_HIST: 1626 case B_AT_NIL: 1627 break; 1628 case B_AT_BI_KSTACK: 1629 flags |= DTEVT_KSTACK; 1630 break; 1631 case B_AT_BI_USTACK: 1632 flags |= DTEVT_USTACK; 1633 break; 1634 case B_AT_BI_COMM: 1635 flags |= DTEVT_EXECNAME; 1636 break; 1637 case B_AT_BI_CPU: 1638 case B_AT_BI_PID: 1639 case B_AT_BI_TID: 1640 case B_AT_BI_NSECS: 1641 break; 1642 case B_AT_BI_ARG0 ... B_AT_BI_ARG9: 1643 flags |= DTEVT_FUNCARGS; 1644 break; 1645 case B_AT_BI_RETVAL: 1646 case B_AT_BI_PROBE: 1647 break; 1648 case B_AT_MF_COUNT: 1649 case B_AT_MF_MAX: 1650 case B_AT_MF_MIN: 1651 case B_AT_MF_SUM: 1652 case B_AT_FN_STR: 1653 break; 1654 case B_AT_OP_PLUS ... B_AT_OP_LOR: 1655 flags |= ba2dtflags(bval->ba_value); 1656 break; 1657 default: 1658 xabort("invalid argument type %d", bval->ba_type); 1659 } 1660 } while ((ba = SLIST_NEXT(ba, ba_next)) != NULL); 1661 1662 --recursions; 1663 1664 return flags; 1665 } 1666 1667 long 1668 bacmp(struct bt_arg *a, struct bt_arg *b) 1669 { 1670 assert(a->ba_type == b->ba_type); 1671 assert(a->ba_type == B_AT_LONG); 1672 1673 return ba2long(a, NULL) - ba2long(b, NULL); 1674 } 1675 1676 __dead void 1677 xabort(const char *fmt, ...) 1678 { 1679 va_list ap; 1680 1681 va_start(ap, fmt); 1682 vfprintf(stderr, fmt, ap); 1683 va_end(ap); 1684 1685 fprintf(stderr, "\n"); 1686 abort(); 1687 } 1688 1689 void 1690 debug(const char *fmt, ...) 1691 { 1692 va_list ap; 1693 1694 if (verbose < 2) 1695 return; 1696 1697 fprintf(stderr, "debug: "); 1698 1699 va_start(ap, fmt); 1700 vfprintf(stderr, fmt, ap); 1701 va_end(ap); 1702 } 1703 1704 void 1705 debugx(const char *fmt, ...) 1706 { 1707 va_list ap; 1708 1709 if (verbose < 2) 1710 return; 1711 1712 va_start(ap, fmt); 1713 vfprintf(stderr, fmt, ap); 1714 va_end(ap); 1715 } 1716 1717 void 1718 debug_dump_term(struct bt_arg *ba) 1719 { 1720 switch (ba->ba_type) { 1721 case B_AT_LONG: 1722 debugx("%s", ba2str(ba, NULL)); 1723 break; 1724 case B_AT_OP_PLUS ... B_AT_OP_LOR: 1725 debug_dump_expr(ba); 1726 break; 1727 default: 1728 debugx("%s", ba_name(ba)); 1729 } 1730 } 1731 1732 void 1733 debug_dump_expr(struct bt_arg *ba) 1734 { 1735 struct bt_arg *lhs, *rhs; 1736 1737 lhs = ba->ba_value; 1738 rhs = SLIST_NEXT(lhs, ba_next); 1739 1740 /* Left */ 1741 debug_dump_term(lhs); 1742 1743 /* Right */ 1744 if (rhs != NULL) { 1745 debugx(" %s ", ba_name(ba)); 1746 debug_dump_term(rhs); 1747 } else { 1748 if (ba->ba_type != B_AT_OP_NE) 1749 debugx(" %s NULL", ba_name(ba)); 1750 } 1751 } 1752 1753 void 1754 debug_dump_filter(struct bt_rule *r) 1755 { 1756 struct bt_stmt *bs; 1757 1758 if (verbose < 2) 1759 return; 1760 1761 if (r->br_filter == NULL) { 1762 debugx("\n"); 1763 return; 1764 } 1765 1766 bs = r->br_filter->bf_condition; 1767 1768 debugx(" /"); 1769 debug_dump_expr(SLIST_FIRST(&bs->bs_args)); 1770 debugx("/\n"); 1771 } 1772 1773 const char * 1774 debug_probe_name(struct bt_probe *bp) 1775 { 1776 static char buf[64]; 1777 1778 if (verbose < 2) 1779 return ""; 1780 1781 if (bp->bp_type == B_PT_BEGIN) 1782 return "BEGIN"; 1783 1784 if (bp->bp_type == B_PT_END) 1785 return "END"; 1786 1787 assert(bp->bp_type == B_PT_PROBE); 1788 1789 if (bp->bp_rate) { 1790 snprintf(buf, sizeof(buf), "%s:%s:%u", bp->bp_prov, 1791 bp->bp_unit, bp->bp_rate); 1792 } else { 1793 snprintf(buf, sizeof(buf), "%s:%s:%s", bp->bp_prov, 1794 bp->bp_unit, bp->bp_name); 1795 } 1796 1797 return buf; 1798 } 1799