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 /* 984 * A thread clone will have the same PID for both 985 * parent and child. 986 */ 987 if (thread == parent) 988 return 0; 989 990 if (!thread || !parent || thread__fork(thread, parent)) { 991 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 992 return -1; 993 } 994 total_fork++; 995 996 return 0; 997 } 998 999 static int 1000 process_event(event_t *event, unsigned long offset, unsigned long head) 1001 { 1002 switch (event->header.type) { 1003 case PERF_EVENT_SAMPLE: 1004 return process_sample_event(event, offset, head); 1005 1006 case PERF_EVENT_MMAP: 1007 return process_mmap_event(event, offset, head); 1008 1009 case PERF_EVENT_COMM: 1010 return process_comm_event(event, offset, head); 1011 1012 case PERF_EVENT_FORK: 1013 return process_fork_event(event, offset, head); 1014 /* 1015 * We dont process them right now but they are fine: 1016 */ 1017 1018 case PERF_EVENT_THROTTLE: 1019 case PERF_EVENT_UNTHROTTLE: 1020 return 0; 1021 1022 default: 1023 return -1; 1024 } 1025 1026 return 0; 1027 } 1028 1029 static int 1030 parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 1031 { 1032 char *line = NULL, *tmp, *tmp2; 1033 static const char *prev_line; 1034 static const char *prev_color; 1035 unsigned int offset; 1036 size_t line_len; 1037 s64 line_ip; 1038 int ret; 1039 char *c; 1040 1041 if (getline(&line, &line_len, file) < 0) 1042 return -1; 1043 if (!line) 1044 return -1; 1045 1046 c = strchr(line, '\n'); 1047 if (c) 1048 *c = 0; 1049 1050 line_ip = -1; 1051 offset = 0; 1052 ret = -2; 1053 1054 /* 1055 * Strip leading spaces: 1056 */ 1057 tmp = line; 1058 while (*tmp) { 1059 if (*tmp != ' ') 1060 break; 1061 tmp++; 1062 } 1063 1064 if (*tmp) { 1065 /* 1066 * Parse hexa addresses followed by ':' 1067 */ 1068 line_ip = strtoull(tmp, &tmp2, 16); 1069 if (*tmp2 != ':') 1070 line_ip = -1; 1071 } 1072 1073 if (line_ip != -1) { 1074 const char *path = NULL; 1075 unsigned int hits = 0; 1076 double percent = 0.0; 1077 char *color; 1078 struct sym_ext *sym_ext = sym->priv; 1079 1080 offset = line_ip - start; 1081 if (offset < len) 1082 hits = sym->hist[offset]; 1083 1084 if (offset < len && sym_ext) { 1085 path = sym_ext[offset].path; 1086 percent = sym_ext[offset].percent; 1087 } else if (sym->hist_sum) 1088 percent = 100.0 * hits / sym->hist_sum; 1089 1090 color = get_percent_color(percent); 1091 1092 /* 1093 * Also color the filename and line if needed, with 1094 * the same color than the percentage. Don't print it 1095 * twice for close colored ip with the same filename:line 1096 */ 1097 if (path) { 1098 if (!prev_line || strcmp(prev_line, path) 1099 || color != prev_color) { 1100 color_fprintf(stdout, color, " %s", path); 1101 prev_line = path; 1102 prev_color = color; 1103 } 1104 } 1105 1106 color_fprintf(stdout, color, " %7.2f", percent); 1107 printf(" : "); 1108 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", line); 1109 } else { 1110 if (!*line) 1111 printf(" :\n"); 1112 else 1113 printf(" : %s\n", line); 1114 } 1115 1116 return 0; 1117 } 1118 1119 static struct rb_root root_sym_ext; 1120 1121 static void insert_source_line(struct sym_ext *sym_ext) 1122 { 1123 struct sym_ext *iter; 1124 struct rb_node **p = &root_sym_ext.rb_node; 1125 struct rb_node *parent = NULL; 1126 1127 while (*p != NULL) { 1128 parent = *p; 1129 iter = rb_entry(parent, struct sym_ext, node); 1130 1131 if (sym_ext->percent > iter->percent) 1132 p = &(*p)->rb_left; 1133 else 1134 p = &(*p)->rb_right; 1135 } 1136 1137 rb_link_node(&sym_ext->node, parent, p); 1138 rb_insert_color(&sym_ext->node, &root_sym_ext); 1139 } 1140 1141 static void free_source_line(struct symbol *sym, int len) 1142 { 1143 struct sym_ext *sym_ext = sym->priv; 1144 int i; 1145 1146 if (!sym_ext) 1147 return; 1148 1149 for (i = 0; i < len; i++) 1150 free(sym_ext[i].path); 1151 free(sym_ext); 1152 1153 sym->priv = NULL; 1154 root_sym_ext = RB_ROOT; 1155 } 1156 1157 /* Get the filename:line for the colored entries */ 1158 static void 1159 get_source_line(struct symbol *sym, u64 start, int len, char *filename) 1160 { 1161 int i; 1162 char cmd[PATH_MAX * 2]; 1163 struct sym_ext *sym_ext; 1164 1165 if (!sym->hist_sum) 1166 return; 1167 1168 sym->priv = calloc(len, sizeof(struct sym_ext)); 1169 if (!sym->priv) 1170 return; 1171 1172 sym_ext = sym->priv; 1173 1174 for (i = 0; i < len; i++) { 1175 char *path = NULL; 1176 size_t line_len; 1177 u64 offset; 1178 FILE *fp; 1179 1180 sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum; 1181 if (sym_ext[i].percent <= 0.5) 1182 continue; 1183 1184 offset = start + i; 1185 sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 1186 fp = popen(cmd, "r"); 1187 if (!fp) 1188 continue; 1189 1190 if (getline(&path, &line_len, fp) < 0 || !line_len) 1191 goto next; 1192 1193 sym_ext[i].path = malloc(sizeof(char) * line_len + 1); 1194 if (!sym_ext[i].path) 1195 goto next; 1196 1197 strcpy(sym_ext[i].path, path); 1198 insert_source_line(&sym_ext[i]); 1199 1200 next: 1201 pclose(fp); 1202 } 1203 } 1204 1205 static void print_summary(char *filename) 1206 { 1207 struct sym_ext *sym_ext; 1208 struct rb_node *node; 1209 1210 printf("\nSorted summary for file %s\n", filename); 1211 printf("----------------------------------------------\n\n"); 1212 1213 if (RB_EMPTY_ROOT(&root_sym_ext)) { 1214 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN); 1215 return; 1216 } 1217 1218 node = rb_first(&root_sym_ext); 1219 while (node) { 1220 double percent; 1221 char *color; 1222 char *path; 1223 1224 sym_ext = rb_entry(node, struct sym_ext, node); 1225 percent = sym_ext->percent; 1226 color = get_percent_color(percent); 1227 path = sym_ext->path; 1228 1229 color_fprintf(stdout, color, " %7.2f %s", percent, path); 1230 node = rb_next(node); 1231 } 1232 } 1233 1234 static void annotate_sym(struct dso *dso, struct symbol *sym) 1235 { 1236 char *filename = dso->name, *d_filename; 1237 u64 start, end, len; 1238 char command[PATH_MAX*2]; 1239 FILE *file; 1240 1241 if (!filename) 1242 return; 1243 if (sym->module) 1244 filename = sym->module->path; 1245 else if (dso == kernel_dso) 1246 filename = vmlinux; 1247 1248 start = sym->obj_start; 1249 if (!start) 1250 start = sym->start; 1251 if (full_paths) 1252 d_filename = filename; 1253 else 1254 d_filename = basename(filename); 1255 1256 end = start + sym->end - sym->start + 1; 1257 len = sym->end - sym->start; 1258 1259 if (print_line) { 1260 get_source_line(sym, start, len, filename); 1261 print_summary(filename); 1262 } 1263 1264 printf("\n\n------------------------------------------------\n"); 1265 printf(" Percent | Source code & Disassembly of %s\n", d_filename); 1266 printf("------------------------------------------------\n"); 1267 1268 if (verbose >= 2) 1269 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 1270 1271 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", 1272 (u64)start, (u64)end, filename, filename); 1273 1274 if (verbose >= 3) 1275 printf("doing: %s\n", command); 1276 1277 file = popen(command, "r"); 1278 if (!file) 1279 return; 1280 1281 while (!feof(file)) { 1282 if (parse_line(file, sym, start, len) < 0) 1283 break; 1284 } 1285 1286 pclose(file); 1287 if (print_line) 1288 free_source_line(sym, len); 1289 } 1290 1291 static void find_annotations(void) 1292 { 1293 struct rb_node *nd; 1294 struct dso *dso; 1295 int count = 0; 1296 1297 list_for_each_entry(dso, &dsos, node) { 1298 1299 for (nd = rb_first(&dso->syms); nd; nd = rb_next(nd)) { 1300 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 1301 1302 if (sym->hist) { 1303 annotate_sym(dso, sym); 1304 count++; 1305 } 1306 } 1307 } 1308 1309 if (!count) 1310 printf(" Error: symbol '%s' not present amongst the samples.\n", sym_hist_filter); 1311 } 1312 1313 static int __cmd_annotate(void) 1314 { 1315 int ret, rc = EXIT_FAILURE; 1316 unsigned long offset = 0; 1317 unsigned long head = 0; 1318 struct stat stat; 1319 event_t *event; 1320 uint32_t size; 1321 char *buf; 1322 1323 register_idle_thread(); 1324 1325 input = open(input_name, O_RDONLY); 1326 if (input < 0) { 1327 perror("failed to open file"); 1328 exit(-1); 1329 } 1330 1331 ret = fstat(input, &stat); 1332 if (ret < 0) { 1333 perror("failed to stat file"); 1334 exit(-1); 1335 } 1336 1337 if (!stat.st_size) { 1338 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1339 exit(0); 1340 } 1341 1342 if (load_kernel() < 0) { 1343 perror("failed to load kernel symbols"); 1344 return EXIT_FAILURE; 1345 } 1346 1347 remap: 1348 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, 1349 MAP_SHARED, input, offset); 1350 if (buf == MAP_FAILED) { 1351 perror("failed to mmap file"); 1352 exit(-1); 1353 } 1354 1355 more: 1356 event = (event_t *)(buf + head); 1357 1358 size = event->header.size; 1359 if (!size) 1360 size = 8; 1361 1362 if (head + event->header.size >= page_size * mmap_window) { 1363 unsigned long shift = page_size * (head / page_size); 1364 int ret; 1365 1366 ret = munmap(buf, page_size * mmap_window); 1367 assert(ret == 0); 1368 1369 offset += shift; 1370 head -= shift; 1371 goto remap; 1372 } 1373 1374 size = event->header.size; 1375 1376 dprintf("%p [%p]: event: %d\n", 1377 (void *)(offset + head), 1378 (void *)(long)event->header.size, 1379 event->header.type); 1380 1381 if (!size || process_event(event, offset, head) < 0) { 1382 1383 dprintf("%p [%p]: skipping unknown header type: %d\n", 1384 (void *)(offset + head), 1385 (void *)(long)(event->header.size), 1386 event->header.type); 1387 1388 total_unknown++; 1389 1390 /* 1391 * assume we lost track of the stream, check alignment, and 1392 * increment a single u64 in the hope to catch on again 'soon'. 1393 */ 1394 1395 if (unlikely(head & 7)) 1396 head &= ~7ULL; 1397 1398 size = 8; 1399 } 1400 1401 head += size; 1402 1403 if (offset + head < (unsigned long)stat.st_size) 1404 goto more; 1405 1406 rc = EXIT_SUCCESS; 1407 close(input); 1408 1409 dprintf(" IP events: %10ld\n", total); 1410 dprintf(" mmap events: %10ld\n", total_mmap); 1411 dprintf(" comm events: %10ld\n", total_comm); 1412 dprintf(" fork events: %10ld\n", total_fork); 1413 dprintf(" unknown events: %10ld\n", total_unknown); 1414 1415 if (dump_trace) 1416 return 0; 1417 1418 if (verbose >= 3) 1419 threads__fprintf(stdout); 1420 1421 if (verbose >= 2) 1422 dsos__fprintf(stdout); 1423 1424 collapse__resort(); 1425 output__resort(); 1426 1427 find_annotations(); 1428 1429 return rc; 1430 } 1431 1432 static const char * const annotate_usage[] = { 1433 "perf annotate [<options>] <command>", 1434 NULL 1435 }; 1436 1437 static const struct option options[] = { 1438 OPT_STRING('i', "input", &input_name, "file", 1439 "input file name"), 1440 OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", 1441 "symbol to annotate"), 1442 OPT_BOOLEAN('v', "verbose", &verbose, 1443 "be more verbose (show symbol address, etc)"), 1444 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1445 "dump raw trace in ASCII"), 1446 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1447 OPT_BOOLEAN('m', "modules", &modules, 1448 "load module symbols - WARNING: use only with -k and LIVE kernel"), 1449 OPT_BOOLEAN('l', "print-line", &print_line, 1450 "print matching source lines (may be slow)"), 1451 OPT_BOOLEAN('P', "full-paths", &full_paths, 1452 "Don't shorten the displayed pathnames"), 1453 OPT_END() 1454 }; 1455 1456 static void setup_sorting(void) 1457 { 1458 char *tmp, *tok, *str = strdup(sort_order); 1459 1460 for (tok = strtok_r(str, ", ", &tmp); 1461 tok; tok = strtok_r(NULL, ", ", &tmp)) { 1462 if (sort_dimension__add(tok) < 0) { 1463 error("Unknown --sort key: `%s'", tok); 1464 usage_with_options(annotate_usage, options); 1465 } 1466 } 1467 1468 free(str); 1469 } 1470 1471 int cmd_annotate(int argc, const char **argv, const char *prefix __used) 1472 { 1473 symbol__init(); 1474 1475 page_size = getpagesize(); 1476 1477 argc = parse_options(argc, argv, options, annotate_usage, 0); 1478 1479 setup_sorting(); 1480 1481 if (argc) { 1482 /* 1483 * Special case: if there's an argument left then assume tha 1484 * it's a symbol filter: 1485 */ 1486 if (argc > 1) 1487 usage_with_options(annotate_usage, options); 1488 1489 sym_hist_filter = argv[0]; 1490 } 1491 1492 if (!sym_hist_filter) 1493 usage_with_options(annotate_usage, options); 1494 1495 setup_pager(); 1496 1497 return __cmd_annotate(); 1498 } 1499