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