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