1 /* 2 * probe-file.c : operate ftrace k/uprobe events files 3 * 4 * Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 */ 17 #include <sys/uio.h> 18 #include "util.h" 19 #include "event.h" 20 #include "strlist.h" 21 #include "debug.h" 22 #include "cache.h" 23 #include "color.h" 24 #include "symbol.h" 25 #include "thread.h" 26 #include <api/fs/tracing_path.h> 27 #include "probe-event.h" 28 #include "probe-file.h" 29 #include "session.h" 30 31 #define MAX_CMDLEN 256 32 33 static void print_open_warning(int err, bool uprobe) 34 { 35 char sbuf[STRERR_BUFSIZE]; 36 37 if (err == -ENOENT) { 38 const char *config; 39 40 if (uprobe) 41 config = "CONFIG_UPROBE_EVENTS"; 42 else 43 config = "CONFIG_KPROBE_EVENTS"; 44 45 pr_warning("%cprobe_events file does not exist" 46 " - please rebuild kernel with %s.\n", 47 uprobe ? 'u' : 'k', config); 48 } else if (err == -ENOTSUP) 49 pr_warning("Tracefs or debugfs is not mounted.\n"); 50 else 51 pr_warning("Failed to open %cprobe_events: %s\n", 52 uprobe ? 'u' : 'k', 53 str_error_r(-err, sbuf, sizeof(sbuf))); 54 } 55 56 static void print_both_open_warning(int kerr, int uerr) 57 { 58 /* Both kprobes and uprobes are disabled, warn it. */ 59 if (kerr == -ENOTSUP && uerr == -ENOTSUP) 60 pr_warning("Tracefs or debugfs is not mounted.\n"); 61 else if (kerr == -ENOENT && uerr == -ENOENT) 62 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS " 63 "or/and CONFIG_UPROBE_EVENTS.\n"); 64 else { 65 char sbuf[STRERR_BUFSIZE]; 66 pr_warning("Failed to open kprobe events: %s.\n", 67 str_error_r(-kerr, sbuf, sizeof(sbuf))); 68 pr_warning("Failed to open uprobe events: %s.\n", 69 str_error_r(-uerr, sbuf, sizeof(sbuf))); 70 } 71 } 72 73 static int open_probe_events(const char *trace_file, bool readwrite) 74 { 75 char buf[PATH_MAX]; 76 const char *tracing_dir = ""; 77 int ret; 78 79 ret = e_snprintf(buf, PATH_MAX, "%s/%s%s", 80 tracing_path, tracing_dir, trace_file); 81 if (ret >= 0) { 82 pr_debug("Opening %s write=%d\n", buf, readwrite); 83 if (readwrite && !probe_event_dry_run) 84 ret = open(buf, O_RDWR | O_APPEND, 0); 85 else 86 ret = open(buf, O_RDONLY, 0); 87 88 if (ret < 0) 89 ret = -errno; 90 } 91 return ret; 92 } 93 94 static int open_kprobe_events(bool readwrite) 95 { 96 return open_probe_events("kprobe_events", readwrite); 97 } 98 99 static int open_uprobe_events(bool readwrite) 100 { 101 return open_probe_events("uprobe_events", readwrite); 102 } 103 104 int probe_file__open(int flag) 105 { 106 int fd; 107 108 if (flag & PF_FL_UPROBE) 109 fd = open_uprobe_events(flag & PF_FL_RW); 110 else 111 fd = open_kprobe_events(flag & PF_FL_RW); 112 if (fd < 0) 113 print_open_warning(fd, flag & PF_FL_UPROBE); 114 115 return fd; 116 } 117 118 int probe_file__open_both(int *kfd, int *ufd, int flag) 119 { 120 if (!kfd || !ufd) 121 return -EINVAL; 122 123 *kfd = open_kprobe_events(flag & PF_FL_RW); 124 *ufd = open_uprobe_events(flag & PF_FL_RW); 125 if (*kfd < 0 && *ufd < 0) { 126 print_both_open_warning(*kfd, *ufd); 127 return *kfd; 128 } 129 130 return 0; 131 } 132 133 /* Get raw string list of current kprobe_events or uprobe_events */ 134 struct strlist *probe_file__get_rawlist(int fd) 135 { 136 int ret, idx; 137 FILE *fp; 138 char buf[MAX_CMDLEN]; 139 char *p; 140 struct strlist *sl; 141 142 if (fd < 0) 143 return NULL; 144 145 sl = strlist__new(NULL, NULL); 146 147 fp = fdopen(dup(fd), "r"); 148 while (!feof(fp)) { 149 p = fgets(buf, MAX_CMDLEN, fp); 150 if (!p) 151 break; 152 153 idx = strlen(p) - 1; 154 if (p[idx] == '\n') 155 p[idx] = '\0'; 156 ret = strlist__add(sl, buf); 157 if (ret < 0) { 158 pr_debug("strlist__add failed (%d)\n", ret); 159 strlist__delete(sl); 160 return NULL; 161 } 162 } 163 fclose(fp); 164 165 return sl; 166 } 167 168 static struct strlist *__probe_file__get_namelist(int fd, bool include_group) 169 { 170 char buf[128]; 171 struct strlist *sl, *rawlist; 172 struct str_node *ent; 173 struct probe_trace_event tev; 174 int ret = 0; 175 176 memset(&tev, 0, sizeof(tev)); 177 rawlist = probe_file__get_rawlist(fd); 178 if (!rawlist) 179 return NULL; 180 sl = strlist__new(NULL, NULL); 181 strlist__for_each_entry(ent, rawlist) { 182 ret = parse_probe_trace_command(ent->s, &tev); 183 if (ret < 0) 184 break; 185 if (include_group) { 186 ret = e_snprintf(buf, 128, "%s:%s", tev.group, 187 tev.event); 188 if (ret >= 0) 189 ret = strlist__add(sl, buf); 190 } else 191 ret = strlist__add(sl, tev.event); 192 clear_probe_trace_event(&tev); 193 if (ret < 0) 194 break; 195 } 196 strlist__delete(rawlist); 197 198 if (ret < 0) { 199 strlist__delete(sl); 200 return NULL; 201 } 202 return sl; 203 } 204 205 /* Get current perf-probe event names */ 206 struct strlist *probe_file__get_namelist(int fd) 207 { 208 return __probe_file__get_namelist(fd, false); 209 } 210 211 int probe_file__add_event(int fd, struct probe_trace_event *tev) 212 { 213 int ret = 0; 214 char *buf = synthesize_probe_trace_command(tev); 215 char sbuf[STRERR_BUFSIZE]; 216 217 if (!buf) { 218 pr_debug("Failed to synthesize probe trace event.\n"); 219 return -EINVAL; 220 } 221 222 pr_debug("Writing event: %s\n", buf); 223 if (!probe_event_dry_run) { 224 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) { 225 ret = -errno; 226 pr_warning("Failed to write event: %s\n", 227 str_error_r(errno, sbuf, sizeof(sbuf))); 228 } 229 } 230 free(buf); 231 232 return ret; 233 } 234 235 static int __del_trace_probe_event(int fd, struct str_node *ent) 236 { 237 char *p; 238 char buf[128]; 239 int ret; 240 241 /* Convert from perf-probe event to trace-probe event */ 242 ret = e_snprintf(buf, 128, "-:%s", ent->s); 243 if (ret < 0) 244 goto error; 245 246 p = strchr(buf + 2, ':'); 247 if (!p) { 248 pr_debug("Internal error: %s should have ':' but not.\n", 249 ent->s); 250 ret = -ENOTSUP; 251 goto error; 252 } 253 *p = '/'; 254 255 pr_debug("Writing event: %s\n", buf); 256 ret = write(fd, buf, strlen(buf)); 257 if (ret < 0) { 258 ret = -errno; 259 goto error; 260 } 261 262 return 0; 263 error: 264 pr_warning("Failed to delete event: %s\n", 265 str_error_r(-ret, buf, sizeof(buf))); 266 return ret; 267 } 268 269 int probe_file__get_events(int fd, struct strfilter *filter, 270 struct strlist *plist) 271 { 272 struct strlist *namelist; 273 struct str_node *ent; 274 const char *p; 275 int ret = -ENOENT; 276 277 if (!plist) 278 return -EINVAL; 279 280 namelist = __probe_file__get_namelist(fd, true); 281 if (!namelist) 282 return -ENOENT; 283 284 strlist__for_each_entry(ent, namelist) { 285 p = strchr(ent->s, ':'); 286 if ((p && strfilter__compare(filter, p + 1)) || 287 strfilter__compare(filter, ent->s)) { 288 strlist__add(plist, ent->s); 289 ret = 0; 290 } 291 } 292 strlist__delete(namelist); 293 294 return ret; 295 } 296 297 int probe_file__del_strlist(int fd, struct strlist *namelist) 298 { 299 int ret = 0; 300 struct str_node *ent; 301 302 strlist__for_each_entry(ent, namelist) { 303 ret = __del_trace_probe_event(fd, ent); 304 if (ret < 0) 305 break; 306 } 307 return ret; 308 } 309 310 int probe_file__del_events(int fd, struct strfilter *filter) 311 { 312 struct strlist *namelist; 313 int ret; 314 315 namelist = strlist__new(NULL, NULL); 316 if (!namelist) 317 return -ENOMEM; 318 319 ret = probe_file__get_events(fd, filter, namelist); 320 if (ret < 0) 321 return ret; 322 323 ret = probe_file__del_strlist(fd, namelist); 324 strlist__delete(namelist); 325 326 return ret; 327 } 328 329 /* Caller must ensure to remove this entry from list */ 330 static void probe_cache_entry__delete(struct probe_cache_entry *entry) 331 { 332 if (entry) { 333 BUG_ON(!list_empty(&entry->node)); 334 335 strlist__delete(entry->tevlist); 336 clear_perf_probe_event(&entry->pev); 337 zfree(&entry->spev); 338 free(entry); 339 } 340 } 341 342 static struct probe_cache_entry * 343 probe_cache_entry__new(struct perf_probe_event *pev) 344 { 345 struct probe_cache_entry *entry = zalloc(sizeof(*entry)); 346 347 if (entry) { 348 INIT_LIST_HEAD(&entry->node); 349 entry->tevlist = strlist__new(NULL, NULL); 350 if (!entry->tevlist) 351 zfree(&entry); 352 else if (pev) { 353 entry->spev = synthesize_perf_probe_command(pev); 354 if (!entry->spev || 355 perf_probe_event__copy(&entry->pev, pev) < 0) { 356 probe_cache_entry__delete(entry); 357 return NULL; 358 } 359 } 360 } 361 362 return entry; 363 } 364 365 /* For the kernel probe caches, pass target = NULL */ 366 static int probe_cache__open(struct probe_cache *pcache, const char *target) 367 { 368 char cpath[PATH_MAX]; 369 char sbuildid[SBUILD_ID_SIZE]; 370 char *dir_name = NULL; 371 bool is_kallsyms = !target; 372 int ret, fd; 373 374 if (target && build_id_cache__cached(target)) { 375 /* This is a cached buildid */ 376 strncpy(sbuildid, target, SBUILD_ID_SIZE); 377 dir_name = build_id_cache__linkname(sbuildid, NULL, 0); 378 goto found; 379 } 380 381 if (target) 382 ret = filename__sprintf_build_id(target, sbuildid); 383 else { 384 target = DSO__NAME_KALLSYMS; 385 ret = sysfs__sprintf_build_id("/", sbuildid); 386 } 387 if (ret < 0) { 388 pr_debug("Failed to get build-id from %s.\n", target); 389 return ret; 390 } 391 392 /* If we have no buildid cache, make it */ 393 if (!build_id_cache__cached(sbuildid)) { 394 ret = build_id_cache__add_s(sbuildid, target, 395 is_kallsyms, NULL); 396 if (ret < 0) { 397 pr_debug("Failed to add build-id cache: %s\n", target); 398 return ret; 399 } 400 } 401 402 dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms, 403 false); 404 found: 405 if (!dir_name) { 406 pr_debug("Failed to get cache from %s\n", target); 407 return -ENOMEM; 408 } 409 410 snprintf(cpath, PATH_MAX, "%s/probes", dir_name); 411 fd = open(cpath, O_CREAT | O_RDWR, 0644); 412 if (fd < 0) 413 pr_debug("Failed to open cache(%d): %s\n", fd, cpath); 414 free(dir_name); 415 pcache->fd = fd; 416 417 return fd; 418 } 419 420 static int probe_cache__load(struct probe_cache *pcache) 421 { 422 struct probe_cache_entry *entry = NULL; 423 char buf[MAX_CMDLEN], *p; 424 int ret = 0; 425 FILE *fp; 426 427 fp = fdopen(dup(pcache->fd), "r"); 428 if (!fp) 429 return -EINVAL; 430 431 while (!feof(fp)) { 432 if (!fgets(buf, MAX_CMDLEN, fp)) 433 break; 434 p = strchr(buf, '\n'); 435 if (p) 436 *p = '\0'; 437 /* #perf_probe_event or %sdt_event */ 438 if (buf[0] == '#' || buf[0] == '%') { 439 entry = probe_cache_entry__new(NULL); 440 if (!entry) { 441 ret = -ENOMEM; 442 goto out; 443 } 444 if (buf[0] == '%') 445 entry->sdt = true; 446 entry->spev = strdup(buf + 1); 447 if (entry->spev) 448 ret = parse_perf_probe_command(buf + 1, 449 &entry->pev); 450 else 451 ret = -ENOMEM; 452 if (ret < 0) { 453 probe_cache_entry__delete(entry); 454 goto out; 455 } 456 list_add_tail(&entry->node, &pcache->entries); 457 } else { /* trace_probe_event */ 458 if (!entry) { 459 ret = -EINVAL; 460 goto out; 461 } 462 strlist__add(entry->tevlist, buf); 463 } 464 } 465 out: 466 fclose(fp); 467 return ret; 468 } 469 470 static struct probe_cache *probe_cache__alloc(void) 471 { 472 struct probe_cache *pcache = zalloc(sizeof(*pcache)); 473 474 if (pcache) { 475 INIT_LIST_HEAD(&pcache->entries); 476 pcache->fd = -EINVAL; 477 } 478 return pcache; 479 } 480 481 void probe_cache__purge(struct probe_cache *pcache) 482 { 483 struct probe_cache_entry *entry, *n; 484 485 list_for_each_entry_safe(entry, n, &pcache->entries, node) { 486 list_del_init(&entry->node); 487 probe_cache_entry__delete(entry); 488 } 489 } 490 491 void probe_cache__delete(struct probe_cache *pcache) 492 { 493 if (!pcache) 494 return; 495 496 probe_cache__purge(pcache); 497 if (pcache->fd > 0) 498 close(pcache->fd); 499 free(pcache); 500 } 501 502 struct probe_cache *probe_cache__new(const char *target) 503 { 504 struct probe_cache *pcache = probe_cache__alloc(); 505 int ret; 506 507 if (!pcache) 508 return NULL; 509 510 ret = probe_cache__open(pcache, target); 511 if (ret < 0) { 512 pr_debug("Cache open error: %d\n", ret); 513 goto out_err; 514 } 515 516 ret = probe_cache__load(pcache); 517 if (ret < 0) { 518 pr_debug("Cache read error: %d\n", ret); 519 goto out_err; 520 } 521 522 return pcache; 523 524 out_err: 525 probe_cache__delete(pcache); 526 return NULL; 527 } 528 529 static bool streql(const char *a, const char *b) 530 { 531 if (a == b) 532 return true; 533 534 if (!a || !b) 535 return false; 536 537 return !strcmp(a, b); 538 } 539 540 struct probe_cache_entry * 541 probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev) 542 { 543 struct probe_cache_entry *entry = NULL; 544 char *cmd = synthesize_perf_probe_command(pev); 545 546 if (!cmd) 547 return NULL; 548 549 list_for_each_entry(entry, &pcache->entries, node) { 550 /* Hit if same event name or same command-string */ 551 if ((pev->event && 552 (streql(entry->pev.group, pev->group) && 553 streql(entry->pev.event, pev->event))) || 554 (!strcmp(entry->spev, cmd))) 555 goto found; 556 } 557 entry = NULL; 558 559 found: 560 free(cmd); 561 return entry; 562 } 563 564 struct probe_cache_entry * 565 probe_cache__find_by_name(struct probe_cache *pcache, 566 const char *group, const char *event) 567 { 568 struct probe_cache_entry *entry = NULL; 569 570 list_for_each_entry(entry, &pcache->entries, node) { 571 /* Hit if same event name or same command-string */ 572 if (streql(entry->pev.group, group) && 573 streql(entry->pev.event, event)) 574 goto found; 575 } 576 entry = NULL; 577 578 found: 579 return entry; 580 } 581 582 int probe_cache__add_entry(struct probe_cache *pcache, 583 struct perf_probe_event *pev, 584 struct probe_trace_event *tevs, int ntevs) 585 { 586 struct probe_cache_entry *entry = NULL; 587 char *command; 588 int i, ret = 0; 589 590 if (!pcache || !pev || !tevs || ntevs <= 0) { 591 ret = -EINVAL; 592 goto out_err; 593 } 594 595 /* Remove old cache entry */ 596 entry = probe_cache__find(pcache, pev); 597 if (entry) { 598 list_del_init(&entry->node); 599 probe_cache_entry__delete(entry); 600 } 601 602 ret = -ENOMEM; 603 entry = probe_cache_entry__new(pev); 604 if (!entry) 605 goto out_err; 606 607 for (i = 0; i < ntevs; i++) { 608 if (!tevs[i].point.symbol) 609 continue; 610 611 command = synthesize_probe_trace_command(&tevs[i]); 612 if (!command) 613 goto out_err; 614 strlist__add(entry->tevlist, command); 615 free(command); 616 } 617 list_add_tail(&entry->node, &pcache->entries); 618 pr_debug("Added probe cache: %d\n", ntevs); 619 return 0; 620 621 out_err: 622 pr_debug("Failed to add probe caches\n"); 623 probe_cache_entry__delete(entry); 624 return ret; 625 } 626 627 #ifdef HAVE_GELF_GETNOTE_SUPPORT 628 static unsigned long long sdt_note__get_addr(struct sdt_note *note) 629 { 630 return note->bit32 ? (unsigned long long)note->addr.a32[0] 631 : (unsigned long long)note->addr.a64[0]; 632 } 633 634 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname) 635 { 636 struct probe_cache_entry *entry = NULL; 637 struct list_head sdtlist; 638 struct sdt_note *note; 639 char *buf; 640 char sdtgrp[64]; 641 int ret; 642 643 INIT_LIST_HEAD(&sdtlist); 644 ret = get_sdt_note_list(&sdtlist, pathname); 645 if (ret < 0) { 646 pr_debug("Failed to get sdt note: %d\n", ret); 647 return ret; 648 } 649 list_for_each_entry(note, &sdtlist, note_list) { 650 ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider); 651 if (ret < 0) 652 break; 653 /* Try to find same-name entry */ 654 entry = probe_cache__find_by_name(pcache, sdtgrp, note->name); 655 if (!entry) { 656 entry = probe_cache_entry__new(NULL); 657 if (!entry) { 658 ret = -ENOMEM; 659 break; 660 } 661 entry->sdt = true; 662 ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp, 663 note->name, note->name); 664 if (ret < 0) 665 break; 666 entry->pev.event = strdup(note->name); 667 entry->pev.group = strdup(sdtgrp); 668 list_add_tail(&entry->node, &pcache->entries); 669 } 670 ret = asprintf(&buf, "p:%s/%s %s:0x%llx", 671 sdtgrp, note->name, pathname, 672 sdt_note__get_addr(note)); 673 if (ret < 0) 674 break; 675 strlist__add(entry->tevlist, buf); 676 free(buf); 677 entry = NULL; 678 } 679 if (entry) { 680 list_del_init(&entry->node); 681 probe_cache_entry__delete(entry); 682 } 683 cleanup_sdt_note_list(&sdtlist); 684 return ret; 685 } 686 #endif 687 688 static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd) 689 { 690 struct str_node *snode; 691 struct stat st; 692 struct iovec iov[3]; 693 const char *prefix = entry->sdt ? "%" : "#"; 694 int ret; 695 /* Save stat for rollback */ 696 ret = fstat(fd, &st); 697 if (ret < 0) 698 return ret; 699 700 pr_debug("Writing cache: %s%s\n", prefix, entry->spev); 701 iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1; 702 iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev); 703 iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1; 704 ret = writev(fd, iov, 3); 705 if (ret < (int)iov[1].iov_len + 2) 706 goto rollback; 707 708 strlist__for_each_entry(snode, entry->tevlist) { 709 iov[0].iov_base = (void *)snode->s; 710 iov[0].iov_len = strlen(snode->s); 711 iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1; 712 ret = writev(fd, iov, 2); 713 if (ret < (int)iov[0].iov_len + 1) 714 goto rollback; 715 } 716 return 0; 717 718 rollback: 719 /* Rollback to avoid cache file corruption */ 720 if (ret > 0) 721 ret = -1; 722 if (ftruncate(fd, st.st_size) < 0) 723 ret = -2; 724 725 return ret; 726 } 727 728 int probe_cache__commit(struct probe_cache *pcache) 729 { 730 struct probe_cache_entry *entry; 731 int ret = 0; 732 733 /* TBD: if we do not update existing entries, skip it */ 734 ret = lseek(pcache->fd, 0, SEEK_SET); 735 if (ret < 0) 736 goto out; 737 738 ret = ftruncate(pcache->fd, 0); 739 if (ret < 0) 740 goto out; 741 742 list_for_each_entry(entry, &pcache->entries, node) { 743 ret = probe_cache_entry__write(entry, pcache->fd); 744 pr_debug("Cache committed: %d\n", ret); 745 if (ret < 0) 746 break; 747 } 748 out: 749 return ret; 750 } 751 752 static bool probe_cache_entry__compare(struct probe_cache_entry *entry, 753 struct strfilter *filter) 754 { 755 char buf[128], *ptr = entry->spev; 756 757 if (entry->pev.event) { 758 snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event); 759 ptr = buf; 760 } 761 return strfilter__compare(filter, ptr); 762 } 763 764 int probe_cache__filter_purge(struct probe_cache *pcache, 765 struct strfilter *filter) 766 { 767 struct probe_cache_entry *entry, *tmp; 768 769 list_for_each_entry_safe(entry, tmp, &pcache->entries, node) { 770 if (probe_cache_entry__compare(entry, filter)) { 771 pr_info("Removed cached event: %s\n", entry->spev); 772 list_del_init(&entry->node); 773 probe_cache_entry__delete(entry); 774 } 775 } 776 return 0; 777 } 778 779 static int probe_cache__show_entries(struct probe_cache *pcache, 780 struct strfilter *filter) 781 { 782 struct probe_cache_entry *entry; 783 784 list_for_each_entry(entry, &pcache->entries, node) { 785 if (probe_cache_entry__compare(entry, filter)) 786 printf("%s\n", entry->spev); 787 } 788 return 0; 789 } 790 791 /* Show all cached probes */ 792 int probe_cache__show_all_caches(struct strfilter *filter) 793 { 794 struct probe_cache *pcache; 795 struct strlist *bidlist; 796 struct str_node *nd; 797 char *buf = strfilter__string(filter); 798 799 pr_debug("list cache with filter: %s\n", buf); 800 free(buf); 801 802 bidlist = build_id_cache__list_all(); 803 if (!bidlist) { 804 pr_debug("Failed to get buildids: %d\n", errno); 805 return -EINVAL; 806 } 807 strlist__for_each_entry(nd, bidlist) { 808 pcache = probe_cache__new(nd->s); 809 if (!pcache) 810 continue; 811 if (!list_empty(&pcache->entries)) { 812 buf = build_id_cache__origname(nd->s); 813 printf("%s (%s):\n", buf, nd->s); 814 free(buf); 815 probe_cache__show_entries(pcache, filter); 816 } 817 probe_cache__delete(pcache); 818 } 819 strlist__delete(bidlist); 820 821 return 0; 822 } 823