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 21 #include "util/parse-options.h" 22 #include "util/parse-events.h" 23 24 #define SHOW_KERNEL 1 25 #define SHOW_USER 2 26 #define SHOW_HV 4 27 28 static char const *input_name = "perf.data"; 29 static char *vmlinux = "vmlinux"; 30 31 static char default_sort_order[] = "comm,symbol"; 32 static char *sort_order = default_sort_order; 33 34 static int input; 35 static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 36 37 static int dump_trace = 0; 38 #define dprintf(x...) do { if (dump_trace) printf(x); } while (0) 39 40 static int verbose; 41 42 static int modules; 43 44 static int full_paths; 45 46 static int print_line; 47 48 static unsigned long page_size; 49 static unsigned long mmap_window = 32; 50 51 struct ip_event { 52 struct perf_event_header header; 53 u64 ip; 54 u32 pid, tid; 55 }; 56 57 struct mmap_event { 58 struct perf_event_header header; 59 u32 pid, tid; 60 u64 start; 61 u64 len; 62 u64 pgoff; 63 char filename[PATH_MAX]; 64 }; 65 66 struct comm_event { 67 struct perf_event_header header; 68 u32 pid, tid; 69 char comm[16]; 70 }; 71 72 struct fork_event { 73 struct perf_event_header header; 74 u32 pid, ppid; 75 }; 76 77 typedef union event_union { 78 struct perf_event_header header; 79 struct ip_event ip; 80 struct mmap_event mmap; 81 struct comm_event comm; 82 struct fork_event fork; 83 } event_t; 84 85 86 struct sym_ext { 87 struct rb_node node; 88 double percent; 89 char *path; 90 }; 91 92 static LIST_HEAD(dsos); 93 static struct dso *kernel_dso; 94 static struct dso *vdso; 95 96 97 static void dsos__add(struct dso *dso) 98 { 99 list_add_tail(&dso->node, &dsos); 100 } 101 102 static struct dso *dsos__find(const char *name) 103 { 104 struct dso *pos; 105 106 list_for_each_entry(pos, &dsos, node) 107 if (strcmp(pos->name, name) == 0) 108 return pos; 109 return NULL; 110 } 111 112 static struct dso *dsos__findnew(const char *name) 113 { 114 struct dso *dso = dsos__find(name); 115 int nr; 116 117 if (dso) 118 return dso; 119 120 dso = dso__new(name, 0); 121 if (!dso) 122 goto out_delete_dso; 123 124 nr = dso__load(dso, NULL, verbose); 125 if (nr < 0) { 126 if (verbose) 127 fprintf(stderr, "Failed to open: %s\n", name); 128 goto out_delete_dso; 129 } 130 if (!nr && verbose) { 131 fprintf(stderr, 132 "No symbols found in: %s, maybe install a debug package?\n", 133 name); 134 } 135 136 dsos__add(dso); 137 138 return dso; 139 140 out_delete_dso: 141 dso__delete(dso); 142 return NULL; 143 } 144 145 static void dsos__fprintf(FILE *fp) 146 { 147 struct dso *pos; 148 149 list_for_each_entry(pos, &dsos, node) 150 dso__fprintf(pos, fp); 151 } 152 153 static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 154 { 155 return dso__find_symbol(dso, ip); 156 } 157 158 static int load_kernel(void) 159 { 160 int err; 161 162 kernel_dso = dso__new("[kernel]", 0); 163 if (!kernel_dso) 164 return -1; 165 166 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); 167 if (err <= 0) { 168 dso__delete(kernel_dso); 169 kernel_dso = NULL; 170 } else 171 dsos__add(kernel_dso); 172 173 vdso = dso__new("[vdso]", 0); 174 if (!vdso) 175 return -1; 176 177 vdso->find_symbol = vdso__find_symbol; 178 179 dsos__add(vdso); 180 181 return err; 182 } 183 184 struct map { 185 struct list_head node; 186 u64 start; 187 u64 end; 188 u64 pgoff; 189 u64 (*map_ip)(struct map *, u64); 190 struct dso *dso; 191 }; 192 193 static u64 map__map_ip(struct map *map, u64 ip) 194 { 195 return ip - map->start + map->pgoff; 196 } 197 198 static u64 vdso__map_ip(struct map *map __used, u64 ip) 199 { 200 return ip; 201 } 202 203 static struct map *map__new(struct mmap_event *event) 204 { 205 struct map *self = malloc(sizeof(*self)); 206 207 if (self != NULL) { 208 const char *filename = event->filename; 209 210 self->start = event->start; 211 self->end = event->start + event->len; 212 self->pgoff = event->pgoff; 213 214 self->dso = dsos__findnew(filename); 215 if (self->dso == NULL) 216 goto out_delete; 217 218 if (self->dso == vdso) 219 self->map_ip = vdso__map_ip; 220 else 221 self->map_ip = map__map_ip; 222 } 223 return self; 224 out_delete: 225 free(self); 226 return NULL; 227 } 228 229 static struct map *map__clone(struct map *self) 230 { 231 struct map *map = malloc(sizeof(*self)); 232 233 if (!map) 234 return NULL; 235 236 memcpy(map, self, sizeof(*self)); 237 238 return map; 239 } 240 241 static int map__overlap(struct map *l, struct map *r) 242 { 243 if (l->start > r->start) { 244 struct map *t = l; 245 l = r; 246 r = t; 247 } 248 249 if (l->end > r->start) 250 return 1; 251 252 return 0; 253 } 254 255 static size_t map__fprintf(struct map *self, FILE *fp) 256 { 257 return fprintf(fp, " %Lx-%Lx %Lx %s\n", 258 self->start, self->end, self->pgoff, self->dso->name); 259 } 260 261 262 struct thread { 263 struct rb_node rb_node; 264 struct list_head maps; 265 pid_t pid; 266 char *comm; 267 }; 268 269 static struct thread *thread__new(pid_t pid) 270 { 271 struct thread *self = malloc(sizeof(*self)); 272 273 if (self != NULL) { 274 self->pid = pid; 275 self->comm = malloc(32); 276 if (self->comm) 277 snprintf(self->comm, 32, ":%d", self->pid); 278 INIT_LIST_HEAD(&self->maps); 279 } 280 281 return self; 282 } 283 284 static int thread__set_comm(struct thread *self, const char *comm) 285 { 286 if (self->comm) 287 free(self->comm); 288 self->comm = strdup(comm); 289 return self->comm ? 0 : -ENOMEM; 290 } 291 292 static size_t thread__fprintf(struct thread *self, FILE *fp) 293 { 294 struct map *pos; 295 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); 296 297 list_for_each_entry(pos, &self->maps, node) 298 ret += map__fprintf(pos, fp); 299 300 return ret; 301 } 302 303 304 static struct rb_root threads; 305 static struct thread *last_match; 306 307 static struct thread *threads__findnew(pid_t pid) 308 { 309 struct rb_node **p = &threads.rb_node; 310 struct rb_node *parent = NULL; 311 struct thread *th; 312 313 /* 314 * Font-end cache - PID lookups come in blocks, 315 * so most of the time we dont have to look up 316 * the full rbtree: 317 */ 318 if (last_match && last_match->pid == pid) 319 return last_match; 320 321 while (*p != NULL) { 322 parent = *p; 323 th = rb_entry(parent, struct thread, rb_node); 324 325 if (th->pid == pid) { 326 last_match = th; 327 return th; 328 } 329 330 if (pid < th->pid) 331 p = &(*p)->rb_left; 332 else 333 p = &(*p)->rb_right; 334 } 335 336 th = thread__new(pid); 337 if (th != NULL) { 338 rb_link_node(&th->rb_node, parent, p); 339 rb_insert_color(&th->rb_node, &threads); 340 last_match = th; 341 } 342 343 return th; 344 } 345 346 static void thread__insert_map(struct thread *self, struct map *map) 347 { 348 struct map *pos, *tmp; 349 350 list_for_each_entry_safe(pos, tmp, &self->maps, node) { 351 if (map__overlap(pos, map)) { 352 list_del_init(&pos->node); 353 /* XXX leaks dsos */ 354 free(pos); 355 } 356 } 357 358 list_add_tail(&map->node, &self->maps); 359 } 360 361 static int thread__fork(struct thread *self, struct thread *parent) 362 { 363 struct map *map; 364 365 if (self->comm) 366 free(self->comm); 367 self->comm = strdup(parent->comm); 368 if (!self->comm) 369 return -ENOMEM; 370 371 list_for_each_entry(map, &parent->maps, node) { 372 struct map *new = map__clone(map); 373 if (!new) 374 return -ENOMEM; 375 thread__insert_map(self, new); 376 } 377 378 return 0; 379 } 380 381 static struct map *thread__find_map(struct thread *self, u64 ip) 382 { 383 struct map *pos; 384 385 if (self == NULL) 386 return NULL; 387 388 list_for_each_entry(pos, &self->maps, node) 389 if (ip >= pos->start && ip <= pos->end) 390 return pos; 391 392 return NULL; 393 } 394 395 static size_t threads__fprintf(FILE *fp) 396 { 397 size_t ret = 0; 398 struct rb_node *nd; 399 400 for (nd = rb_first(&threads); nd; nd = rb_next(nd)) { 401 struct thread *pos = rb_entry(nd, struct thread, rb_node); 402 403 ret += thread__fprintf(pos, fp); 404 } 405 406 return ret; 407 } 408 409 /* 410 * histogram, sorted on item, collects counts 411 */ 412 413 static struct rb_root hist; 414 415 struct hist_entry { 416 struct rb_node rb_node; 417 418 struct thread *thread; 419 struct map *map; 420 struct dso *dso; 421 struct symbol *sym; 422 u64 ip; 423 char level; 424 425 uint32_t count; 426 }; 427 428 /* 429 * configurable sorting bits 430 */ 431 432 struct sort_entry { 433 struct list_head list; 434 435 char *header; 436 437 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 438 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 439 size_t (*print)(FILE *fp, struct hist_entry *); 440 }; 441 442 /* --sort pid */ 443 444 static int64_t 445 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) 446 { 447 return right->thread->pid - left->thread->pid; 448 } 449 450 static size_t 451 sort__thread_print(FILE *fp, struct hist_entry *self) 452 { 453 return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid); 454 } 455 456 static struct sort_entry sort_thread = { 457 .header = " Command: Pid", 458 .cmp = sort__thread_cmp, 459 .print = sort__thread_print, 460 }; 461 462 /* --sort comm */ 463 464 static int64_t 465 sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 466 { 467 return right->thread->pid - left->thread->pid; 468 } 469 470 static int64_t 471 sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 472 { 473 char *comm_l = left->thread->comm; 474 char *comm_r = right->thread->comm; 475 476 if (!comm_l || !comm_r) { 477 if (!comm_l && !comm_r) 478 return 0; 479 else if (!comm_l) 480 return -1; 481 else 482 return 1; 483 } 484 485 return strcmp(comm_l, comm_r); 486 } 487 488 static size_t 489 sort__comm_print(FILE *fp, struct hist_entry *self) 490 { 491 return fprintf(fp, "%16s", self->thread->comm); 492 } 493 494 static struct sort_entry sort_comm = { 495 .header = " Command", 496 .cmp = sort__comm_cmp, 497 .collapse = sort__comm_collapse, 498 .print = sort__comm_print, 499 }; 500 501 /* --sort dso */ 502 503 static int64_t 504 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) 505 { 506 struct dso *dso_l = left->dso; 507 struct dso *dso_r = right->dso; 508 509 if (!dso_l || !dso_r) { 510 if (!dso_l && !dso_r) 511 return 0; 512 else if (!dso_l) 513 return -1; 514 else 515 return 1; 516 } 517 518 return strcmp(dso_l->name, dso_r->name); 519 } 520 521 static size_t 522 sort__dso_print(FILE *fp, struct hist_entry *self) 523 { 524 if (self->dso) 525 return fprintf(fp, "%-25s", self->dso->name); 526 527 return fprintf(fp, "%016llx ", (u64)self->ip); 528 } 529 530 static struct sort_entry sort_dso = { 531 .header = "Shared Object ", 532 .cmp = sort__dso_cmp, 533 .print = sort__dso_print, 534 }; 535 536 /* --sort symbol */ 537 538 static int64_t 539 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 540 { 541 u64 ip_l, ip_r; 542 543 if (left->sym == right->sym) 544 return 0; 545 546 ip_l = left->sym ? left->sym->start : left->ip; 547 ip_r = right->sym ? right->sym->start : right->ip; 548 549 return (int64_t)(ip_r - ip_l); 550 } 551 552 static size_t 553 sort__sym_print(FILE *fp, struct hist_entry *self) 554 { 555 size_t ret = 0; 556 557 if (verbose) 558 ret += fprintf(fp, "%#018llx ", (u64)self->ip); 559 560 if (self->sym) { 561 ret += fprintf(fp, "[%c] %s", 562 self->dso == kernel_dso ? 'k' : '.', self->sym->name); 563 } else { 564 ret += fprintf(fp, "%#016llx", (u64)self->ip); 565 } 566 567 return ret; 568 } 569 570 static struct sort_entry sort_sym = { 571 .header = "Symbol", 572 .cmp = sort__sym_cmp, 573 .print = sort__sym_print, 574 }; 575 576 static int sort__need_collapse = 0; 577 578 struct sort_dimension { 579 char *name; 580 struct sort_entry *entry; 581 int taken; 582 }; 583 584 static struct sort_dimension sort_dimensions[] = { 585 { .name = "pid", .entry = &sort_thread, }, 586 { .name = "comm", .entry = &sort_comm, }, 587 { .name = "dso", .entry = &sort_dso, }, 588 { .name = "symbol", .entry = &sort_sym, }, 589 }; 590 591 static LIST_HEAD(hist_entry__sort_list); 592 593 static int sort_dimension__add(char *tok) 594 { 595 unsigned int i; 596 597 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 598 struct sort_dimension *sd = &sort_dimensions[i]; 599 600 if (sd->taken) 601 continue; 602 603 if (strncasecmp(tok, sd->name, strlen(tok))) 604 continue; 605 606 if (sd->entry->collapse) 607 sort__need_collapse = 1; 608 609 list_add_tail(&sd->entry->list, &hist_entry__sort_list); 610 sd->taken = 1; 611 612 return 0; 613 } 614 615 return -ESRCH; 616 } 617 618 static int64_t 619 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) 620 { 621 struct sort_entry *se; 622 int64_t cmp = 0; 623 624 list_for_each_entry(se, &hist_entry__sort_list, list) { 625 cmp = se->cmp(left, right); 626 if (cmp) 627 break; 628 } 629 630 return cmp; 631 } 632 633 static int64_t 634 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) 635 { 636 struct sort_entry *se; 637 int64_t cmp = 0; 638 639 list_for_each_entry(se, &hist_entry__sort_list, list) { 640 int64_t (*f)(struct hist_entry *, struct hist_entry *); 641 642 f = se->collapse ?: se->cmp; 643 644 cmp = f(left, right); 645 if (cmp) 646 break; 647 } 648 649 return cmp; 650 } 651 652 /* 653 * collect histogram counts 654 */ 655 static void hist_hit(struct hist_entry *he, u64 ip) 656 { 657 unsigned int sym_size, offset; 658 struct symbol *sym = he->sym; 659 660 he->count++; 661 662 if (!sym || !sym->hist) 663 return; 664 665 sym_size = sym->end - sym->start; 666 offset = ip - sym->start; 667 668 if (offset >= sym_size) 669 return; 670 671 sym->hist_sum++; 672 sym->hist[offset]++; 673 674 if (verbose >= 3) 675 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n", 676 (void *)(unsigned long)he->sym->start, 677 he->sym->name, 678 (void *)(unsigned long)ip, ip - he->sym->start, 679 sym->hist[offset]); 680 } 681 682 static int 683 hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 684 struct symbol *sym, u64 ip, char level) 685 { 686 struct rb_node **p = &hist.rb_node; 687 struct rb_node *parent = NULL; 688 struct hist_entry *he; 689 struct hist_entry entry = { 690 .thread = thread, 691 .map = map, 692 .dso = dso, 693 .sym = sym, 694 .ip = ip, 695 .level = level, 696 .count = 1, 697 }; 698 int cmp; 699 700 while (*p != NULL) { 701 parent = *p; 702 he = rb_entry(parent, struct hist_entry, rb_node); 703 704 cmp = hist_entry__cmp(&entry, he); 705 706 if (!cmp) { 707 hist_hit(he, ip); 708 709 return 0; 710 } 711 712 if (cmp < 0) 713 p = &(*p)->rb_left; 714 else 715 p = &(*p)->rb_right; 716 } 717 718 he = malloc(sizeof(*he)); 719 if (!he) 720 return -ENOMEM; 721 *he = entry; 722 rb_link_node(&he->rb_node, parent, p); 723 rb_insert_color(&he->rb_node, &hist); 724 725 return 0; 726 } 727 728 static void hist_entry__free(struct hist_entry *he) 729 { 730 free(he); 731 } 732 733 /* 734 * collapse the histogram 735 */ 736 737 static struct rb_root collapse_hists; 738 739 static void collapse__insert_entry(struct hist_entry *he) 740 { 741 struct rb_node **p = &collapse_hists.rb_node; 742 struct rb_node *parent = NULL; 743 struct hist_entry *iter; 744 int64_t cmp; 745 746 while (*p != NULL) { 747 parent = *p; 748 iter = rb_entry(parent, struct hist_entry, rb_node); 749 750 cmp = hist_entry__collapse(iter, he); 751 752 if (!cmp) { 753 iter->count += he->count; 754 hist_entry__free(he); 755 return; 756 } 757 758 if (cmp < 0) 759 p = &(*p)->rb_left; 760 else 761 p = &(*p)->rb_right; 762 } 763 764 rb_link_node(&he->rb_node, parent, p); 765 rb_insert_color(&he->rb_node, &collapse_hists); 766 } 767 768 static void collapse__resort(void) 769 { 770 struct rb_node *next; 771 struct hist_entry *n; 772 773 if (!sort__need_collapse) 774 return; 775 776 next = rb_first(&hist); 777 while (next) { 778 n = rb_entry(next, struct hist_entry, rb_node); 779 next = rb_next(&n->rb_node); 780 781 rb_erase(&n->rb_node, &hist); 782 collapse__insert_entry(n); 783 } 784 } 785 786 /* 787 * reverse the map, sort on count. 788 */ 789 790 static struct rb_root output_hists; 791 792 static void output__insert_entry(struct hist_entry *he) 793 { 794 struct rb_node **p = &output_hists.rb_node; 795 struct rb_node *parent = NULL; 796 struct hist_entry *iter; 797 798 while (*p != NULL) { 799 parent = *p; 800 iter = rb_entry(parent, struct hist_entry, rb_node); 801 802 if (he->count > iter->count) 803 p = &(*p)->rb_left; 804 else 805 p = &(*p)->rb_right; 806 } 807 808 rb_link_node(&he->rb_node, parent, p); 809 rb_insert_color(&he->rb_node, &output_hists); 810 } 811 812 static void output__resort(void) 813 { 814 struct rb_node *next; 815 struct hist_entry *n; 816 struct rb_root *tree = &hist; 817 818 if (sort__need_collapse) 819 tree = &collapse_hists; 820 821 next = rb_first(tree); 822 823 while (next) { 824 n = rb_entry(next, struct hist_entry, rb_node); 825 next = rb_next(&n->rb_node); 826 827 rb_erase(&n->rb_node, tree); 828 output__insert_entry(n); 829 } 830 } 831 832 static void register_idle_thread(void) 833 { 834 struct thread *thread = threads__findnew(0); 835 836 if (thread == NULL || 837 thread__set_comm(thread, "[idle]")) { 838 fprintf(stderr, "problem inserting idle task.\n"); 839 exit(-1); 840 } 841 } 842 843 static unsigned long total = 0, 844 total_mmap = 0, 845 total_comm = 0, 846 total_fork = 0, 847 total_unknown = 0; 848 849 static int 850 process_sample_event(event_t *event, unsigned long offset, unsigned long head) 851 { 852 char level; 853 int show = 0; 854 struct dso *dso = NULL; 855 struct thread *thread = threads__findnew(event->ip.pid); 856 u64 ip = event->ip.ip; 857 struct map *map = NULL; 858 859 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", 860 (void *)(offset + head), 861 (void *)(long)(event->header.size), 862 event->header.misc, 863 event->ip.pid, 864 (void *)(long)ip); 865 866 dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); 867 868 if (thread == NULL) { 869 fprintf(stderr, "problem processing %d event, skipping it.\n", 870 event->header.type); 871 return -1; 872 } 873 874 if (event->header.misc & PERF_EVENT_MISC_KERNEL) { 875 show = SHOW_KERNEL; 876 level = 'k'; 877 878 dso = kernel_dso; 879 880 dprintf(" ...... dso: %s\n", dso->name); 881 882 } else if (event->header.misc & PERF_EVENT_MISC_USER) { 883 884 show = SHOW_USER; 885 level = '.'; 886 887 map = thread__find_map(thread, ip); 888 if (map != NULL) { 889 ip = map->map_ip(map, ip); 890 dso = map->dso; 891 } else { 892 /* 893 * If this is outside of all known maps, 894 * and is a negative address, try to look it 895 * up in the kernel dso, as it might be a 896 * vsyscall (which executes in user-mode): 897 */ 898 if ((long long)ip < 0) 899 dso = kernel_dso; 900 } 901 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 902 903 } else { 904 show = SHOW_HV; 905 level = 'H'; 906 dprintf(" ...... dso: [hypervisor]\n"); 907 } 908 909 if (show & show_mask) { 910 struct symbol *sym = NULL; 911 912 if (dso) 913 sym = dso->find_symbol(dso, ip); 914 915 if (hist_entry__add(thread, map, dso, sym, ip, level)) { 916 fprintf(stderr, 917 "problem incrementing symbol count, skipping event\n"); 918 return -1; 919 } 920 } 921 total++; 922 923 return 0; 924 } 925 926 static int 927 process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 928 { 929 struct thread *thread = threads__findnew(event->mmap.pid); 930 struct map *map = map__new(&event->mmap); 931 932 dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", 933 (void *)(offset + head), 934 (void *)(long)(event->header.size), 935 event->mmap.pid, 936 (void *)(long)event->mmap.start, 937 (void *)(long)event->mmap.len, 938 (void *)(long)event->mmap.pgoff, 939 event->mmap.filename); 940 941 if (thread == NULL || map == NULL) { 942 dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n"); 943 return 0; 944 } 945 946 thread__insert_map(thread, map); 947 total_mmap++; 948 949 return 0; 950 } 951 952 static int 953 process_comm_event(event_t *event, unsigned long offset, unsigned long head) 954 { 955 struct thread *thread = threads__findnew(event->comm.pid); 956 957 dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", 958 (void *)(offset + head), 959 (void *)(long)(event->header.size), 960 event->comm.comm, event->comm.pid); 961 962 if (thread == NULL || 963 thread__set_comm(thread, event->comm.comm)) { 964 dprintf("problem processing PERF_EVENT_COMM, skipping event.\n"); 965 return -1; 966 } 967 total_comm++; 968 969 return 0; 970 } 971 972 static int 973 process_fork_event(event_t *event, unsigned long offset, unsigned long head) 974 { 975 struct thread *thread = threads__findnew(event->fork.pid); 976 struct thread *parent = threads__findnew(event->fork.ppid); 977 978 dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", 979 (void *)(offset + head), 980 (void *)(long)(event->header.size), 981 event->fork.pid, event->fork.ppid); 982 983 if (!thread || !parent || thread__fork(thread, parent)) { 984 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 985 return -1; 986 } 987 total_fork++; 988 989 return 0; 990 } 991 992 static int 993 process_event(event_t *event, unsigned long offset, unsigned long head) 994 { 995 switch (event->header.type) { 996 case PERF_EVENT_SAMPLE: 997 return process_sample_event(event, offset, head); 998 999 case PERF_EVENT_MMAP: 1000 return process_mmap_event(event, offset, head); 1001 1002 case PERF_EVENT_COMM: 1003 return process_comm_event(event, offset, head); 1004 1005 case PERF_EVENT_FORK: 1006 return process_fork_event(event, offset, head); 1007 /* 1008 * We dont process them right now but they are fine: 1009 */ 1010 1011 case PERF_EVENT_THROTTLE: 1012 case PERF_EVENT_UNTHROTTLE: 1013 return 0; 1014 1015 default: 1016 return -1; 1017 } 1018 1019 return 0; 1020 } 1021 1022 static int 1023 parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 1024 { 1025 char *line = NULL, *tmp, *tmp2; 1026 static const char *prev_line; 1027 static const char *prev_color; 1028 unsigned int offset; 1029 size_t line_len; 1030 s64 line_ip; 1031 int ret; 1032 char *c; 1033 1034 if (getline(&line, &line_len, file) < 0) 1035 return -1; 1036 if (!line) 1037 return -1; 1038 1039 c = strchr(line, '\n'); 1040 if (c) 1041 *c = 0; 1042 1043 line_ip = -1; 1044 offset = 0; 1045 ret = -2; 1046 1047 /* 1048 * Strip leading spaces: 1049 */ 1050 tmp = line; 1051 while (*tmp) { 1052 if (*tmp != ' ') 1053 break; 1054 tmp++; 1055 } 1056 1057 if (*tmp) { 1058 /* 1059 * Parse hexa addresses followed by ':' 1060 */ 1061 line_ip = strtoull(tmp, &tmp2, 16); 1062 if (*tmp2 != ':') 1063 line_ip = -1; 1064 } 1065 1066 if (line_ip != -1) { 1067 const char *path = NULL; 1068 unsigned int hits = 0; 1069 double percent = 0.0; 1070 char *color; 1071 struct sym_ext *sym_ext = sym->priv; 1072 1073 offset = line_ip - start; 1074 if (offset < len) 1075 hits = sym->hist[offset]; 1076 1077 if (offset < len && sym_ext) { 1078 path = sym_ext[offset].path; 1079 percent = sym_ext[offset].percent; 1080 } else if (sym->hist_sum) 1081 percent = 100.0 * hits / sym->hist_sum; 1082 1083 color = get_percent_color(percent); 1084 1085 /* 1086 * Also color the filename and line if needed, with 1087 * the same color than the percentage. Don't print it 1088 * twice for close colored ip with the same filename:line 1089 */ 1090 if (path) { 1091 if (!prev_line || strcmp(prev_line, path) 1092 || color != prev_color) { 1093 color_fprintf(stdout, color, " %s", path); 1094 prev_line = path; 1095 prev_color = color; 1096 } 1097 } 1098 1099 color_fprintf(stdout, color, " %7.2f", percent); 1100 printf(" : "); 1101 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", line); 1102 } else { 1103 if (!*line) 1104 printf(" :\n"); 1105 else 1106 printf(" : %s\n", line); 1107 } 1108 1109 return 0; 1110 } 1111 1112 static struct rb_root root_sym_ext; 1113 1114 static void insert_source_line(struct sym_ext *sym_ext) 1115 { 1116 struct sym_ext *iter; 1117 struct rb_node **p = &root_sym_ext.rb_node; 1118 struct rb_node *parent = NULL; 1119 1120 while (*p != NULL) { 1121 parent = *p; 1122 iter = rb_entry(parent, struct sym_ext, node); 1123 1124 if (sym_ext->percent > iter->percent) 1125 p = &(*p)->rb_left; 1126 else 1127 p = &(*p)->rb_right; 1128 } 1129 1130 rb_link_node(&sym_ext->node, parent, p); 1131 rb_insert_color(&sym_ext->node, &root_sym_ext); 1132 } 1133 1134 static void free_source_line(struct symbol *sym, int len) 1135 { 1136 struct sym_ext *sym_ext = sym->priv; 1137 int i; 1138 1139 if (!sym_ext) 1140 return; 1141 1142 for (i = 0; i < len; i++) 1143 free(sym_ext[i].path); 1144 free(sym_ext); 1145 1146 sym->priv = NULL; 1147 root_sym_ext = RB_ROOT; 1148 } 1149 1150 /* Get the filename:line for the colored entries */ 1151 static void 1152 get_source_line(struct symbol *sym, u64 start, int len, char *filename) 1153 { 1154 int i; 1155 char cmd[PATH_MAX * 2]; 1156 struct sym_ext *sym_ext; 1157 1158 if (!sym->hist_sum) 1159 return; 1160 1161 sym->priv = calloc(len, sizeof(struct sym_ext)); 1162 if (!sym->priv) 1163 return; 1164 1165 sym_ext = sym->priv; 1166 1167 for (i = 0; i < len; i++) { 1168 char *path = NULL; 1169 size_t line_len; 1170 u64 offset; 1171 FILE *fp; 1172 1173 sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum; 1174 if (sym_ext[i].percent <= 0.5) 1175 continue; 1176 1177 offset = start + i; 1178 sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 1179 fp = popen(cmd, "r"); 1180 if (!fp) 1181 continue; 1182 1183 if (getline(&path, &line_len, fp) < 0 || !line_len) 1184 goto next; 1185 1186 sym_ext[i].path = malloc(sizeof(char) * line_len + 1); 1187 if (!sym_ext[i].path) 1188 goto next; 1189 1190 strcpy(sym_ext[i].path, path); 1191 insert_source_line(&sym_ext[i]); 1192 1193 next: 1194 pclose(fp); 1195 } 1196 } 1197 1198 static void print_summary(char *filename) 1199 { 1200 struct sym_ext *sym_ext; 1201 struct rb_node *node; 1202 1203 printf("\nSorted summary for file %s\n", filename); 1204 printf("----------------------------------------------\n\n"); 1205 1206 if (RB_EMPTY_ROOT(&root_sym_ext)) { 1207 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN); 1208 return; 1209 } 1210 1211 node = rb_first(&root_sym_ext); 1212 while (node) { 1213 double percent; 1214 char *color; 1215 char *path; 1216 1217 sym_ext = rb_entry(node, struct sym_ext, node); 1218 percent = sym_ext->percent; 1219 color = get_percent_color(percent); 1220 path = sym_ext->path; 1221 1222 color_fprintf(stdout, color, " %7.2f %s", percent, path); 1223 node = rb_next(node); 1224 } 1225 } 1226 1227 static void annotate_sym(struct dso *dso, struct symbol *sym) 1228 { 1229 char *filename = dso->name, *d_filename; 1230 u64 start, end, len; 1231 char command[PATH_MAX*2]; 1232 FILE *file; 1233 1234 if (!filename) 1235 return; 1236 if (sym->module) 1237 filename = sym->module->path; 1238 else if (dso == kernel_dso) 1239 filename = vmlinux; 1240 1241 start = sym->obj_start; 1242 if (!start) 1243 start = sym->start; 1244 if (full_paths) 1245 d_filename = filename; 1246 else 1247 d_filename = basename(filename); 1248 1249 end = start + sym->end - sym->start + 1; 1250 len = sym->end - sym->start; 1251 1252 if (print_line) { 1253 get_source_line(sym, start, len, filename); 1254 print_summary(filename); 1255 } 1256 1257 printf("\n\n------------------------------------------------\n"); 1258 printf(" Percent | Source code & Disassembly of %s\n", d_filename); 1259 printf("------------------------------------------------\n"); 1260 1261 if (verbose >= 2) 1262 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 1263 1264 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", 1265 (u64)start, (u64)end, filename, filename); 1266 1267 if (verbose >= 3) 1268 printf("doing: %s\n", command); 1269 1270 file = popen(command, "r"); 1271 if (!file) 1272 return; 1273 1274 while (!feof(file)) { 1275 if (parse_line(file, sym, start, len) < 0) 1276 break; 1277 } 1278 1279 pclose(file); 1280 if (print_line) 1281 free_source_line(sym, len); 1282 } 1283 1284 static void find_annotations(void) 1285 { 1286 struct rb_node *nd; 1287 struct dso *dso; 1288 int count = 0; 1289 1290 list_for_each_entry(dso, &dsos, node) { 1291 1292 for (nd = rb_first(&dso->syms); nd; nd = rb_next(nd)) { 1293 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 1294 1295 if (sym->hist) { 1296 annotate_sym(dso, sym); 1297 count++; 1298 } 1299 } 1300 } 1301 1302 if (!count) 1303 printf(" Error: symbol '%s' not present amongst the samples.\n", sym_hist_filter); 1304 } 1305 1306 static int __cmd_annotate(void) 1307 { 1308 int ret, rc = EXIT_FAILURE; 1309 unsigned long offset = 0; 1310 unsigned long head = 0; 1311 struct stat stat; 1312 event_t *event; 1313 uint32_t size; 1314 char *buf; 1315 1316 register_idle_thread(); 1317 1318 input = open(input_name, O_RDONLY); 1319 if (input < 0) { 1320 perror("failed to open file"); 1321 exit(-1); 1322 } 1323 1324 ret = fstat(input, &stat); 1325 if (ret < 0) { 1326 perror("failed to stat file"); 1327 exit(-1); 1328 } 1329 1330 if (!stat.st_size) { 1331 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1332 exit(0); 1333 } 1334 1335 if (load_kernel() < 0) { 1336 perror("failed to load kernel symbols"); 1337 return EXIT_FAILURE; 1338 } 1339 1340 remap: 1341 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, 1342 MAP_SHARED, input, offset); 1343 if (buf == MAP_FAILED) { 1344 perror("failed to mmap file"); 1345 exit(-1); 1346 } 1347 1348 more: 1349 event = (event_t *)(buf + head); 1350 1351 size = event->header.size; 1352 if (!size) 1353 size = 8; 1354 1355 if (head + event->header.size >= page_size * mmap_window) { 1356 unsigned long shift = page_size * (head / page_size); 1357 int ret; 1358 1359 ret = munmap(buf, page_size * mmap_window); 1360 assert(ret == 0); 1361 1362 offset += shift; 1363 head -= shift; 1364 goto remap; 1365 } 1366 1367 size = event->header.size; 1368 1369 dprintf("%p [%p]: event: %d\n", 1370 (void *)(offset + head), 1371 (void *)(long)event->header.size, 1372 event->header.type); 1373 1374 if (!size || process_event(event, offset, head) < 0) { 1375 1376 dprintf("%p [%p]: skipping unknown header type: %d\n", 1377 (void *)(offset + head), 1378 (void *)(long)(event->header.size), 1379 event->header.type); 1380 1381 total_unknown++; 1382 1383 /* 1384 * assume we lost track of the stream, check alignment, and 1385 * increment a single u64 in the hope to catch on again 'soon'. 1386 */ 1387 1388 if (unlikely(head & 7)) 1389 head &= ~7ULL; 1390 1391 size = 8; 1392 } 1393 1394 head += size; 1395 1396 if (offset + head < (unsigned long)stat.st_size) 1397 goto more; 1398 1399 rc = EXIT_SUCCESS; 1400 close(input); 1401 1402 dprintf(" IP events: %10ld\n", total); 1403 dprintf(" mmap events: %10ld\n", total_mmap); 1404 dprintf(" comm events: %10ld\n", total_comm); 1405 dprintf(" fork events: %10ld\n", total_fork); 1406 dprintf(" unknown events: %10ld\n", total_unknown); 1407 1408 if (dump_trace) 1409 return 0; 1410 1411 if (verbose >= 3) 1412 threads__fprintf(stdout); 1413 1414 if (verbose >= 2) 1415 dsos__fprintf(stdout); 1416 1417 collapse__resort(); 1418 output__resort(); 1419 1420 find_annotations(); 1421 1422 return rc; 1423 } 1424 1425 static const char * const annotate_usage[] = { 1426 "perf annotate [<options>] <command>", 1427 NULL 1428 }; 1429 1430 static const struct option options[] = { 1431 OPT_STRING('i', "input", &input_name, "file", 1432 "input file name"), 1433 OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", 1434 "symbol to annotate"), 1435 OPT_BOOLEAN('v', "verbose", &verbose, 1436 "be more verbose (show symbol address, etc)"), 1437 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1438 "dump raw trace in ASCII"), 1439 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1440 OPT_BOOLEAN('m', "modules", &modules, 1441 "load module symbols - WARNING: use only with -k and LIVE kernel"), 1442 OPT_BOOLEAN('l', "print-line", &print_line, 1443 "print matching source lines (may be slow)"), 1444 OPT_BOOLEAN('P', "full-paths", &full_paths, 1445 "Don't shorten the displayed pathnames"), 1446 OPT_END() 1447 }; 1448 1449 static void setup_sorting(void) 1450 { 1451 char *tmp, *tok, *str = strdup(sort_order); 1452 1453 for (tok = strtok_r(str, ", ", &tmp); 1454 tok; tok = strtok_r(NULL, ", ", &tmp)) { 1455 if (sort_dimension__add(tok) < 0) { 1456 error("Unknown --sort key: `%s'", tok); 1457 usage_with_options(annotate_usage, options); 1458 } 1459 } 1460 1461 free(str); 1462 } 1463 1464 int cmd_annotate(int argc, const char **argv, const char *prefix __used) 1465 { 1466 symbol__init(); 1467 1468 page_size = getpagesize(); 1469 1470 argc = parse_options(argc, argv, options, annotate_usage, 0); 1471 1472 setup_sorting(); 1473 1474 if (argc) { 1475 /* 1476 * Special case: if there's an argument left then assume tha 1477 * it's a symbol filter: 1478 */ 1479 if (argc > 1) 1480 usage_with_options(annotate_usage, options); 1481 1482 sym_hist_filter = argv[0]; 1483 } 1484 1485 if (!sym_hist_filter) 1486 usage_with_options(annotate_usage, options); 1487 1488 setup_pager(); 1489 1490 return __cmd_annotate(); 1491 } 1492