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