1 /* 2 * builtin-annotate.c 3 * 4 * Builtin annotate command: Analyze the perf.data input file, 5 * look up and read DSOs and symbol information and display 6 * a histogram of results, along various sorting keys. 7 */ 8 #include "builtin.h" 9 10 #include "util/util.h" 11 12 #include "util/color.h" 13 #include <linux/list.h> 14 #include "util/cache.h" 15 #include <linux/rbtree.h> 16 #include "util/symbol.h" 17 #include "util/string.h" 18 19 #include "perf.h" 20 #include "util/debug.h" 21 22 #include "util/parse-options.h" 23 #include "util/parse-events.h" 24 #include "util/thread.h" 25 26 static char const *input_name = "perf.data"; 27 28 static char default_sort_order[] = "comm,symbol"; 29 static char *sort_order = default_sort_order; 30 31 static int force; 32 static int input; 33 static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 34 35 static int full_paths; 36 37 static int print_line; 38 39 static unsigned long page_size; 40 static unsigned long mmap_window = 32; 41 42 static struct rb_root threads; 43 static struct thread *last_match; 44 45 46 struct sym_ext { 47 struct rb_node node; 48 double percent; 49 char *path; 50 }; 51 52 /* 53 * histogram, sorted on item, collects counts 54 */ 55 56 static struct rb_root hist; 57 58 struct hist_entry { 59 struct rb_node rb_node; 60 61 struct thread *thread; 62 struct map *map; 63 struct dso *dso; 64 struct symbol *sym; 65 u64 ip; 66 char level; 67 68 uint32_t count; 69 }; 70 71 /* 72 * configurable sorting bits 73 */ 74 75 struct sort_entry { 76 struct list_head list; 77 78 const char *header; 79 80 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 81 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 82 size_t (*print)(FILE *fp, struct hist_entry *); 83 }; 84 85 /* --sort pid */ 86 87 static int64_t 88 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) 89 { 90 return right->thread->pid - left->thread->pid; 91 } 92 93 static size_t 94 sort__thread_print(FILE *fp, struct hist_entry *self) 95 { 96 return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid); 97 } 98 99 static struct sort_entry sort_thread = { 100 .header = " Command: Pid", 101 .cmp = sort__thread_cmp, 102 .print = sort__thread_print, 103 }; 104 105 /* --sort comm */ 106 107 static int64_t 108 sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 109 { 110 return right->thread->pid - left->thread->pid; 111 } 112 113 static int64_t 114 sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 115 { 116 char *comm_l = left->thread->comm; 117 char *comm_r = right->thread->comm; 118 119 if (!comm_l || !comm_r) { 120 if (!comm_l && !comm_r) 121 return 0; 122 else if (!comm_l) 123 return -1; 124 else 125 return 1; 126 } 127 128 return strcmp(comm_l, comm_r); 129 } 130 131 static size_t 132 sort__comm_print(FILE *fp, struct hist_entry *self) 133 { 134 return fprintf(fp, "%16s", self->thread->comm); 135 } 136 137 static struct sort_entry sort_comm = { 138 .header = " Command", 139 .cmp = sort__comm_cmp, 140 .collapse = sort__comm_collapse, 141 .print = sort__comm_print, 142 }; 143 144 /* --sort dso */ 145 146 static int64_t 147 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) 148 { 149 struct dso *dso_l = left->dso; 150 struct dso *dso_r = right->dso; 151 152 if (!dso_l || !dso_r) { 153 if (!dso_l && !dso_r) 154 return 0; 155 else if (!dso_l) 156 return -1; 157 else 158 return 1; 159 } 160 161 return strcmp(dso_l->name, dso_r->name); 162 } 163 164 static size_t 165 sort__dso_print(FILE *fp, struct hist_entry *self) 166 { 167 if (self->dso) 168 return fprintf(fp, "%-25s", self->dso->name); 169 170 return fprintf(fp, "%016llx ", (u64)self->ip); 171 } 172 173 static struct sort_entry sort_dso = { 174 .header = "Shared Object ", 175 .cmp = sort__dso_cmp, 176 .print = sort__dso_print, 177 }; 178 179 /* --sort symbol */ 180 181 static int64_t 182 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 183 { 184 u64 ip_l, ip_r; 185 186 if (left->sym == right->sym) 187 return 0; 188 189 ip_l = left->sym ? left->sym->start : left->ip; 190 ip_r = right->sym ? right->sym->start : right->ip; 191 192 return (int64_t)(ip_r - ip_l); 193 } 194 195 static size_t 196 sort__sym_print(FILE *fp, struct hist_entry *self) 197 { 198 size_t ret = 0; 199 200 if (verbose) 201 ret += fprintf(fp, "%#018llx ", (u64)self->ip); 202 203 if (self->sym) { 204 ret += fprintf(fp, "[%c] %s", 205 self->dso == kernel_dso ? 'k' : '.', self->sym->name); 206 } else { 207 ret += fprintf(fp, "%#016llx", (u64)self->ip); 208 } 209 210 return ret; 211 } 212 213 static struct sort_entry sort_sym = { 214 .header = "Symbol", 215 .cmp = sort__sym_cmp, 216 .print = sort__sym_print, 217 }; 218 219 static int sort__need_collapse = 0; 220 221 struct sort_dimension { 222 const char *name; 223 struct sort_entry *entry; 224 int taken; 225 }; 226 227 static struct sort_dimension sort_dimensions[] = { 228 { .name = "pid", .entry = &sort_thread, }, 229 { .name = "comm", .entry = &sort_comm, }, 230 { .name = "dso", .entry = &sort_dso, }, 231 { .name = "symbol", .entry = &sort_sym, }, 232 }; 233 234 static LIST_HEAD(hist_entry__sort_list); 235 236 static int sort_dimension__add(char *tok) 237 { 238 unsigned int i; 239 240 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 241 struct sort_dimension *sd = &sort_dimensions[i]; 242 243 if (sd->taken) 244 continue; 245 246 if (strncasecmp(tok, sd->name, strlen(tok))) 247 continue; 248 249 if (sd->entry->collapse) 250 sort__need_collapse = 1; 251 252 list_add_tail(&sd->entry->list, &hist_entry__sort_list); 253 sd->taken = 1; 254 255 return 0; 256 } 257 258 return -ESRCH; 259 } 260 261 static int64_t 262 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) 263 { 264 struct sort_entry *se; 265 int64_t cmp = 0; 266 267 list_for_each_entry(se, &hist_entry__sort_list, list) { 268 cmp = se->cmp(left, right); 269 if (cmp) 270 break; 271 } 272 273 return cmp; 274 } 275 276 static int64_t 277 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) 278 { 279 struct sort_entry *se; 280 int64_t cmp = 0; 281 282 list_for_each_entry(se, &hist_entry__sort_list, list) { 283 int64_t (*f)(struct hist_entry *, struct hist_entry *); 284 285 f = se->collapse ?: se->cmp; 286 287 cmp = f(left, right); 288 if (cmp) 289 break; 290 } 291 292 return cmp; 293 } 294 295 /* 296 * collect histogram counts 297 */ 298 static void hist_hit(struct hist_entry *he, u64 ip) 299 { 300 unsigned int sym_size, offset; 301 struct symbol *sym = he->sym; 302 303 he->count++; 304 305 if (!sym || !sym->hist) 306 return; 307 308 sym_size = sym->end - sym->start; 309 offset = ip - sym->start; 310 311 if (offset >= sym_size) 312 return; 313 314 sym->hist_sum++; 315 sym->hist[offset]++; 316 317 if (verbose >= 3) 318 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n", 319 (void *)(unsigned long)he->sym->start, 320 he->sym->name, 321 (void *)(unsigned long)ip, ip - he->sym->start, 322 sym->hist[offset]); 323 } 324 325 static int 326 hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 327 struct symbol *sym, u64 ip, char level) 328 { 329 struct rb_node **p = &hist.rb_node; 330 struct rb_node *parent = NULL; 331 struct hist_entry *he; 332 struct hist_entry entry = { 333 .thread = thread, 334 .map = map, 335 .dso = dso, 336 .sym = sym, 337 .ip = ip, 338 .level = level, 339 .count = 1, 340 }; 341 int cmp; 342 343 while (*p != NULL) { 344 parent = *p; 345 he = rb_entry(parent, struct hist_entry, rb_node); 346 347 cmp = hist_entry__cmp(&entry, he); 348 349 if (!cmp) { 350 hist_hit(he, ip); 351 352 return 0; 353 } 354 355 if (cmp < 0) 356 p = &(*p)->rb_left; 357 else 358 p = &(*p)->rb_right; 359 } 360 361 he = malloc(sizeof(*he)); 362 if (!he) 363 return -ENOMEM; 364 *he = entry; 365 rb_link_node(&he->rb_node, parent, p); 366 rb_insert_color(&he->rb_node, &hist); 367 368 return 0; 369 } 370 371 static void hist_entry__free(struct hist_entry *he) 372 { 373 free(he); 374 } 375 376 /* 377 * collapse the histogram 378 */ 379 380 static struct rb_root collapse_hists; 381 382 static void collapse__insert_entry(struct hist_entry *he) 383 { 384 struct rb_node **p = &collapse_hists.rb_node; 385 struct rb_node *parent = NULL; 386 struct hist_entry *iter; 387 int64_t cmp; 388 389 while (*p != NULL) { 390 parent = *p; 391 iter = rb_entry(parent, struct hist_entry, rb_node); 392 393 cmp = hist_entry__collapse(iter, he); 394 395 if (!cmp) { 396 iter->count += he->count; 397 hist_entry__free(he); 398 return; 399 } 400 401 if (cmp < 0) 402 p = &(*p)->rb_left; 403 else 404 p = &(*p)->rb_right; 405 } 406 407 rb_link_node(&he->rb_node, parent, p); 408 rb_insert_color(&he->rb_node, &collapse_hists); 409 } 410 411 static void collapse__resort(void) 412 { 413 struct rb_node *next; 414 struct hist_entry *n; 415 416 if (!sort__need_collapse) 417 return; 418 419 next = rb_first(&hist); 420 while (next) { 421 n = rb_entry(next, struct hist_entry, rb_node); 422 next = rb_next(&n->rb_node); 423 424 rb_erase(&n->rb_node, &hist); 425 collapse__insert_entry(n); 426 } 427 } 428 429 /* 430 * reverse the map, sort on count. 431 */ 432 433 static struct rb_root output_hists; 434 435 static void output__insert_entry(struct hist_entry *he) 436 { 437 struct rb_node **p = &output_hists.rb_node; 438 struct rb_node *parent = NULL; 439 struct hist_entry *iter; 440 441 while (*p != NULL) { 442 parent = *p; 443 iter = rb_entry(parent, struct hist_entry, rb_node); 444 445 if (he->count > iter->count) 446 p = &(*p)->rb_left; 447 else 448 p = &(*p)->rb_right; 449 } 450 451 rb_link_node(&he->rb_node, parent, p); 452 rb_insert_color(&he->rb_node, &output_hists); 453 } 454 455 static void output__resort(void) 456 { 457 struct rb_node *next; 458 struct hist_entry *n; 459 struct rb_root *tree = &hist; 460 461 if (sort__need_collapse) 462 tree = &collapse_hists; 463 464 next = rb_first(tree); 465 466 while (next) { 467 n = rb_entry(next, struct hist_entry, rb_node); 468 next = rb_next(&n->rb_node); 469 470 rb_erase(&n->rb_node, tree); 471 output__insert_entry(n); 472 } 473 } 474 475 static unsigned long total = 0, 476 total_mmap = 0, 477 total_comm = 0, 478 total_fork = 0, 479 total_unknown = 0; 480 481 static int 482 process_sample_event(event_t *event, unsigned long offset, unsigned long head) 483 { 484 char level; 485 int show = 0; 486 struct dso *dso = NULL; 487 struct thread *thread; 488 u64 ip = event->ip.ip; 489 struct map *map = NULL; 490 491 thread = threads__findnew(event->ip.pid, &threads, &last_match); 492 493 dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", 494 (void *)(offset + head), 495 (void *)(long)(event->header.size), 496 event->header.misc, 497 event->ip.pid, 498 (void *)(long)ip); 499 500 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 501 502 if (thread == NULL) { 503 fprintf(stderr, "problem processing %d event, skipping it.\n", 504 event->header.type); 505 return -1; 506 } 507 508 if (event->header.misc & PERF_RECORD_MISC_KERNEL) { 509 show = SHOW_KERNEL; 510 level = 'k'; 511 512 dso = kernel_dso; 513 514 dump_printf(" ...... dso: %s\n", dso->name); 515 516 } else if (event->header.misc & PERF_RECORD_MISC_USER) { 517 518 show = SHOW_USER; 519 level = '.'; 520 521 map = thread__find_map(thread, ip); 522 if (map != NULL) { 523 ip = map->map_ip(map, ip); 524 dso = map->dso; 525 } else { 526 /* 527 * If this is outside of all known maps, 528 * and is a negative address, try to look it 529 * up in the kernel dso, as it might be a 530 * vsyscall (which executes in user-mode): 531 */ 532 if ((long long)ip < 0) 533 dso = kernel_dso; 534 } 535 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 536 537 } else { 538 show = SHOW_HV; 539 level = 'H'; 540 dump_printf(" ...... dso: [hypervisor]\n"); 541 } 542 543 if (show & show_mask) { 544 struct symbol *sym = NULL; 545 546 if (dso) 547 sym = dso->find_symbol(dso, ip); 548 549 if (hist_entry__add(thread, map, dso, sym, ip, level)) { 550 fprintf(stderr, 551 "problem incrementing symbol count, skipping event\n"); 552 return -1; 553 } 554 } 555 total++; 556 557 return 0; 558 } 559 560 static int 561 process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 562 { 563 struct thread *thread; 564 struct map *map = map__new(&event->mmap, NULL, 0); 565 566 thread = threads__findnew(event->mmap.pid, &threads, &last_match); 567 568 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n", 569 (void *)(offset + head), 570 (void *)(long)(event->header.size), 571 event->mmap.pid, 572 (void *)(long)event->mmap.start, 573 (void *)(long)event->mmap.len, 574 (void *)(long)event->mmap.pgoff, 575 event->mmap.filename); 576 577 if (thread == NULL || map == NULL) { 578 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n"); 579 return 0; 580 } 581 582 thread__insert_map(thread, map); 583 total_mmap++; 584 585 return 0; 586 } 587 588 static int 589 process_comm_event(event_t *event, unsigned long offset, unsigned long head) 590 { 591 struct thread *thread; 592 593 thread = threads__findnew(event->comm.pid, &threads, &last_match); 594 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 595 (void *)(offset + head), 596 (void *)(long)(event->header.size), 597 event->comm.comm, event->comm.pid); 598 599 if (thread == NULL || 600 thread__set_comm(thread, event->comm.comm)) { 601 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 602 return -1; 603 } 604 total_comm++; 605 606 return 0; 607 } 608 609 static int 610 process_fork_event(event_t *event, unsigned long offset, unsigned long head) 611 { 612 struct thread *thread; 613 struct thread *parent; 614 615 thread = threads__findnew(event->fork.pid, &threads, &last_match); 616 parent = threads__findnew(event->fork.ppid, &threads, &last_match); 617 dump_printf("%p [%p]: PERF_RECORD_FORK: %d:%d\n", 618 (void *)(offset + head), 619 (void *)(long)(event->header.size), 620 event->fork.pid, event->fork.ppid); 621 622 /* 623 * A thread clone will have the same PID for both 624 * parent and child. 625 */ 626 if (thread == parent) 627 return 0; 628 629 if (!thread || !parent || thread__fork(thread, parent)) { 630 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 631 return -1; 632 } 633 total_fork++; 634 635 return 0; 636 } 637 638 static int 639 process_event(event_t *event, unsigned long offset, unsigned long head) 640 { 641 switch (event->header.type) { 642 case PERF_RECORD_SAMPLE: 643 return process_sample_event(event, offset, head); 644 645 case PERF_RECORD_MMAP: 646 return process_mmap_event(event, offset, head); 647 648 case PERF_RECORD_COMM: 649 return process_comm_event(event, offset, head); 650 651 case PERF_RECORD_FORK: 652 return process_fork_event(event, offset, head); 653 /* 654 * We dont process them right now but they are fine: 655 */ 656 657 case PERF_RECORD_THROTTLE: 658 case PERF_RECORD_UNTHROTTLE: 659 return 0; 660 661 default: 662 return -1; 663 } 664 665 return 0; 666 } 667 668 static int 669 parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 670 { 671 char *line = NULL, *tmp, *tmp2; 672 static const char *prev_line; 673 static const char *prev_color; 674 unsigned int offset; 675 size_t line_len; 676 s64 line_ip; 677 int ret; 678 char *c; 679 680 if (getline(&line, &line_len, file) < 0) 681 return -1; 682 if (!line) 683 return -1; 684 685 c = strchr(line, '\n'); 686 if (c) 687 *c = 0; 688 689 line_ip = -1; 690 offset = 0; 691 ret = -2; 692 693 /* 694 * Strip leading spaces: 695 */ 696 tmp = line; 697 while (*tmp) { 698 if (*tmp != ' ') 699 break; 700 tmp++; 701 } 702 703 if (*tmp) { 704 /* 705 * Parse hexa addresses followed by ':' 706 */ 707 line_ip = strtoull(tmp, &tmp2, 16); 708 if (*tmp2 != ':') 709 line_ip = -1; 710 } 711 712 if (line_ip != -1) { 713 const char *path = NULL; 714 unsigned int hits = 0; 715 double percent = 0.0; 716 const char *color; 717 struct sym_ext *sym_ext = sym->priv; 718 719 offset = line_ip - start; 720 if (offset < len) 721 hits = sym->hist[offset]; 722 723 if (offset < len && sym_ext) { 724 path = sym_ext[offset].path; 725 percent = sym_ext[offset].percent; 726 } else if (sym->hist_sum) 727 percent = 100.0 * hits / sym->hist_sum; 728 729 color = get_percent_color(percent); 730 731 /* 732 * Also color the filename and line if needed, with 733 * the same color than the percentage. Don't print it 734 * twice for close colored ip with the same filename:line 735 */ 736 if (path) { 737 if (!prev_line || strcmp(prev_line, path) 738 || color != prev_color) { 739 color_fprintf(stdout, color, " %s", path); 740 prev_line = path; 741 prev_color = color; 742 } 743 } 744 745 color_fprintf(stdout, color, " %7.2f", percent); 746 printf(" : "); 747 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", line); 748 } else { 749 if (!*line) 750 printf(" :\n"); 751 else 752 printf(" : %s\n", line); 753 } 754 755 return 0; 756 } 757 758 static struct rb_root root_sym_ext; 759 760 static void insert_source_line(struct sym_ext *sym_ext) 761 { 762 struct sym_ext *iter; 763 struct rb_node **p = &root_sym_ext.rb_node; 764 struct rb_node *parent = NULL; 765 766 while (*p != NULL) { 767 parent = *p; 768 iter = rb_entry(parent, struct sym_ext, node); 769 770 if (sym_ext->percent > iter->percent) 771 p = &(*p)->rb_left; 772 else 773 p = &(*p)->rb_right; 774 } 775 776 rb_link_node(&sym_ext->node, parent, p); 777 rb_insert_color(&sym_ext->node, &root_sym_ext); 778 } 779 780 static void free_source_line(struct symbol *sym, int len) 781 { 782 struct sym_ext *sym_ext = sym->priv; 783 int i; 784 785 if (!sym_ext) 786 return; 787 788 for (i = 0; i < len; i++) 789 free(sym_ext[i].path); 790 free(sym_ext); 791 792 sym->priv = NULL; 793 root_sym_ext = RB_ROOT; 794 } 795 796 /* Get the filename:line for the colored entries */ 797 static void 798 get_source_line(struct symbol *sym, u64 start, int len, const char *filename) 799 { 800 int i; 801 char cmd[PATH_MAX * 2]; 802 struct sym_ext *sym_ext; 803 804 if (!sym->hist_sum) 805 return; 806 807 sym->priv = calloc(len, sizeof(struct sym_ext)); 808 if (!sym->priv) 809 return; 810 811 sym_ext = sym->priv; 812 813 for (i = 0; i < len; i++) { 814 char *path = NULL; 815 size_t line_len; 816 u64 offset; 817 FILE *fp; 818 819 sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum; 820 if (sym_ext[i].percent <= 0.5) 821 continue; 822 823 offset = start + i; 824 sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 825 fp = popen(cmd, "r"); 826 if (!fp) 827 continue; 828 829 if (getline(&path, &line_len, fp) < 0 || !line_len) 830 goto next; 831 832 sym_ext[i].path = malloc(sizeof(char) * line_len + 1); 833 if (!sym_ext[i].path) 834 goto next; 835 836 strcpy(sym_ext[i].path, path); 837 insert_source_line(&sym_ext[i]); 838 839 next: 840 pclose(fp); 841 } 842 } 843 844 static void print_summary(const char *filename) 845 { 846 struct sym_ext *sym_ext; 847 struct rb_node *node; 848 849 printf("\nSorted summary for file %s\n", filename); 850 printf("----------------------------------------------\n\n"); 851 852 if (RB_EMPTY_ROOT(&root_sym_ext)) { 853 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN); 854 return; 855 } 856 857 node = rb_first(&root_sym_ext); 858 while (node) { 859 double percent; 860 const char *color; 861 char *path; 862 863 sym_ext = rb_entry(node, struct sym_ext, node); 864 percent = sym_ext->percent; 865 color = get_percent_color(percent); 866 path = sym_ext->path; 867 868 color_fprintf(stdout, color, " %7.2f %s", percent, path); 869 node = rb_next(node); 870 } 871 } 872 873 static void annotate_sym(struct dso *dso, struct symbol *sym) 874 { 875 const char *filename = dso->name, *d_filename; 876 u64 start, end, len; 877 char command[PATH_MAX*2]; 878 FILE *file; 879 880 if (!filename) 881 return; 882 if (sym->module) 883 filename = sym->module->path; 884 else if (dso == kernel_dso) 885 filename = vmlinux_name; 886 887 start = sym->obj_start; 888 if (!start) 889 start = sym->start; 890 if (full_paths) 891 d_filename = filename; 892 else 893 d_filename = basename(filename); 894 895 end = start + sym->end - sym->start + 1; 896 len = sym->end - sym->start; 897 898 if (print_line) { 899 get_source_line(sym, start, len, filename); 900 print_summary(filename); 901 } 902 903 printf("\n\n------------------------------------------------\n"); 904 printf(" Percent | Source code & Disassembly of %s\n", d_filename); 905 printf("------------------------------------------------\n"); 906 907 if (verbose >= 2) 908 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 909 910 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", 911 (u64)start, (u64)end, filename, filename); 912 913 if (verbose >= 3) 914 printf("doing: %s\n", command); 915 916 file = popen(command, "r"); 917 if (!file) 918 return; 919 920 while (!feof(file)) { 921 if (parse_line(file, sym, start, len) < 0) 922 break; 923 } 924 925 pclose(file); 926 if (print_line) 927 free_source_line(sym, len); 928 } 929 930 static void find_annotations(void) 931 { 932 struct rb_node *nd; 933 struct dso *dso; 934 int count = 0; 935 936 list_for_each_entry(dso, &dsos, node) { 937 938 for (nd = rb_first(&dso->syms); nd; nd = rb_next(nd)) { 939 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 940 941 if (sym->hist) { 942 annotate_sym(dso, sym); 943 count++; 944 } 945 } 946 } 947 948 if (!count) 949 printf(" Error: symbol '%s' not present amongst the samples.\n", sym_hist_filter); 950 } 951 952 static int __cmd_annotate(void) 953 { 954 int ret, rc = EXIT_FAILURE; 955 unsigned long offset = 0; 956 unsigned long head = 0; 957 struct stat input_stat; 958 event_t *event; 959 uint32_t size; 960 char *buf; 961 962 register_idle_thread(&threads, &last_match); 963 964 input = open(input_name, O_RDONLY); 965 if (input < 0) { 966 perror("failed to open file"); 967 exit(-1); 968 } 969 970 ret = fstat(input, &input_stat); 971 if (ret < 0) { 972 perror("failed to stat file"); 973 exit(-1); 974 } 975 976 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { 977 fprintf(stderr, "file: %s not owned by current user or root\n", input_name); 978 exit(-1); 979 } 980 981 if (!input_stat.st_size) { 982 fprintf(stderr, "zero-sized file, nothing to do!\n"); 983 exit(0); 984 } 985 986 if (load_kernel() < 0) { 987 perror("failed to load kernel symbols"); 988 return EXIT_FAILURE; 989 } 990 991 remap: 992 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, 993 MAP_SHARED, input, offset); 994 if (buf == MAP_FAILED) { 995 perror("failed to mmap file"); 996 exit(-1); 997 } 998 999 more: 1000 event = (event_t *)(buf + head); 1001 1002 size = event->header.size; 1003 if (!size) 1004 size = 8; 1005 1006 if (head + event->header.size >= page_size * mmap_window) { 1007 unsigned long shift = page_size * (head / page_size); 1008 int munmap_ret; 1009 1010 munmap_ret = munmap(buf, page_size * mmap_window); 1011 assert(munmap_ret == 0); 1012 1013 offset += shift; 1014 head -= shift; 1015 goto remap; 1016 } 1017 1018 size = event->header.size; 1019 1020 dump_printf("%p [%p]: event: %d\n", 1021 (void *)(offset + head), 1022 (void *)(long)event->header.size, 1023 event->header.type); 1024 1025 if (!size || process_event(event, offset, head) < 0) { 1026 1027 dump_printf("%p [%p]: skipping unknown header type: %d\n", 1028 (void *)(offset + head), 1029 (void *)(long)(event->header.size), 1030 event->header.type); 1031 1032 total_unknown++; 1033 1034 /* 1035 * assume we lost track of the stream, check alignment, and 1036 * increment a single u64 in the hope to catch on again 'soon'. 1037 */ 1038 1039 if (unlikely(head & 7)) 1040 head &= ~7ULL; 1041 1042 size = 8; 1043 } 1044 1045 head += size; 1046 1047 if (offset + head < (unsigned long)input_stat.st_size) 1048 goto more; 1049 1050 rc = EXIT_SUCCESS; 1051 close(input); 1052 1053 dump_printf(" IP events: %10ld\n", total); 1054 dump_printf(" mmap events: %10ld\n", total_mmap); 1055 dump_printf(" comm events: %10ld\n", total_comm); 1056 dump_printf(" fork events: %10ld\n", total_fork); 1057 dump_printf(" unknown events: %10ld\n", total_unknown); 1058 1059 if (dump_trace) 1060 return 0; 1061 1062 if (verbose >= 3) 1063 threads__fprintf(stdout, &threads); 1064 1065 if (verbose >= 2) 1066 dsos__fprintf(stdout); 1067 1068 collapse__resort(); 1069 output__resort(); 1070 1071 find_annotations(); 1072 1073 return rc; 1074 } 1075 1076 static const char * const annotate_usage[] = { 1077 "perf annotate [<options>] <command>", 1078 NULL 1079 }; 1080 1081 static const struct option options[] = { 1082 OPT_STRING('i', "input", &input_name, "file", 1083 "input file name"), 1084 OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", 1085 "symbol to annotate"), 1086 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 1087 OPT_BOOLEAN('v', "verbose", &verbose, 1088 "be more verbose (show symbol address, etc)"), 1089 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1090 "dump raw trace in ASCII"), 1091 OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), 1092 OPT_BOOLEAN('m', "modules", &modules, 1093 "load module symbols - WARNING: use only with -k and LIVE kernel"), 1094 OPT_BOOLEAN('l', "print-line", &print_line, 1095 "print matching source lines (may be slow)"), 1096 OPT_BOOLEAN('P', "full-paths", &full_paths, 1097 "Don't shorten the displayed pathnames"), 1098 OPT_END() 1099 }; 1100 1101 static void setup_sorting(void) 1102 { 1103 char *tmp, *tok, *str = strdup(sort_order); 1104 1105 for (tok = strtok_r(str, ", ", &tmp); 1106 tok; tok = strtok_r(NULL, ", ", &tmp)) { 1107 if (sort_dimension__add(tok) < 0) { 1108 error("Unknown --sort key: `%s'", tok); 1109 usage_with_options(annotate_usage, options); 1110 } 1111 } 1112 1113 free(str); 1114 } 1115 1116 int cmd_annotate(int argc, const char **argv, const char *prefix __used) 1117 { 1118 symbol__init(); 1119 1120 page_size = getpagesize(); 1121 1122 argc = parse_options(argc, argv, options, annotate_usage, 0); 1123 1124 setup_sorting(); 1125 1126 if (argc) { 1127 /* 1128 * Special case: if there's an argument left then assume tha 1129 * it's a symbol filter: 1130 */ 1131 if (argc > 1) 1132 usage_with_options(annotate_usage, options); 1133 1134 sym_hist_filter = argv[0]; 1135 } 1136 1137 if (!sym_hist_filter) 1138 usage_with_options(annotate_usage, options); 1139 1140 setup_pager(); 1141 1142 return __cmd_annotate(); 1143 } 1144