perf: Do the big rename: Performance Counters -> Performance Events
[linux-2.6.git] / 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 unsigned long total = 0,
476                      total_mmap = 0,
477                      total_comm = 0,
478                      total_fork = 0,
479                      total_unknown = 0;
480
481 static int
482 process_sample_event(event_t *event, unsigned long offset, unsigned long head)
483 {
484         char level;
485         int show = 0;
486         struct dso *dso = NULL;
487         struct thread *thread;
488         u64 ip = event->ip.ip;
489         struct map *map = NULL;
490
491         thread = threads__findnew(event->ip.pid, &threads, &last_match);
492
493         dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
494                 (void *)(offset + head),
495                 (void *)(long)(event->header.size),
496                 event->header.misc,
497                 event->ip.pid,
498                 (void *)(long)ip);
499
500         dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
501
502         if (thread == NULL) {
503                 fprintf(stderr, "problem processing %d event, skipping it.\n",
504                         event->header.type);
505                 return -1;
506         }
507
508         if (event->header.misc & PERF_RECORD_MISC_KERNEL) {
509                 show = SHOW_KERNEL;
510                 level = 'k';
511
512                 dso = kernel_dso;
513
514                 dump_printf(" ...... dso: %s\n", dso->name);
515
516         } else if (event->header.misc & PERF_RECORD_MISC_USER) {
517
518                 show = SHOW_USER;
519                 level = '.';
520
521                 map = thread__find_map(thread, ip);
522                 if (map != NULL) {
523                         ip = map->map_ip(map, ip);
524                         dso = map->dso;
525                 } else {
526                         /*
527                          * If this is outside of all known maps,
528                          * and is a negative address, try to look it
529                          * up in the kernel dso, as it might be a
530                          * vsyscall (which executes in user-mode):
531                          */
532                         if ((long long)ip < 0)
533                                 dso = kernel_dso;
534                 }
535                 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
536
537         } else {
538                 show = SHOW_HV;
539                 level = 'H';
540                 dump_printf(" ...... dso: [hypervisor]\n");
541         }
542
543         if (show & show_mask) {
544                 struct symbol *sym = NULL;
545
546                 if (dso)
547                         sym = dso->find_symbol(dso, ip);
548
549                 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
550                         fprintf(stderr,
551                 "problem incrementing symbol count, skipping event\n");
552                         return -1;
553                 }
554         }
555         total++;
556
557         return 0;
558 }
559
560 static int
561 process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
562 {
563         struct thread *thread;
564         struct map *map = map__new(&event->mmap, NULL, 0);
565
566         thread = threads__findnew(event->mmap.pid, &threads, &last_match);
567
568         dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n",
569                 (void *)(offset + head),
570                 (void *)(long)(event->header.size),
571                 event->mmap.pid,
572                 (void *)(long)event->mmap.start,
573                 (void *)(long)event->mmap.len,
574                 (void *)(long)event->mmap.pgoff,
575                 event->mmap.filename);
576
577         if (thread == NULL || map == NULL) {
578                 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
579                 return 0;
580         }
581
582         thread__insert_map(thread, map);
583         total_mmap++;
584
585         return 0;
586 }
587
588 static int
589 process_comm_event(event_t *event, unsigned long offset, unsigned long head)
590 {
591         struct thread *thread;
592
593         thread = threads__findnew(event->comm.pid, &threads, &last_match);
594         dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
595                 (void *)(offset + head),
596                 (void *)(long)(event->header.size),
597                 event->comm.comm, event->comm.pid);
598
599         if (thread == NULL ||
600             thread__set_comm(thread, event->comm.comm)) {
601                 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
602                 return -1;
603         }
604         total_comm++;
605
606         return 0;
607 }
608
609 static int
610 process_fork_event(event_t *event, unsigned long offset, unsigned long head)
611 {
612         struct thread *thread;
613         struct thread *parent;
614
615         thread = threads__findnew(event->fork.pid, &threads, &last_match);
616         parent = threads__findnew(event->fork.ppid, &threads, &last_match);
617         dump_printf("%p [%p]: PERF_RECORD_FORK: %d:%d\n",
618                 (void *)(offset + head),
619                 (void *)(long)(event->header.size),
620                 event->fork.pid, event->fork.ppid);
621
622         /*
623          * A thread clone will have the same PID for both
624          * parent and child.
625          */
626         if (thread == parent)
627                 return 0;
628
629         if (!thread || !parent || thread__fork(thread, parent)) {
630                 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
631                 return -1;
632         }
633         total_fork++;
634
635         return 0;
636 }
637
638 static int
639 process_event(event_t *event, unsigned long offset, unsigned long head)
640 {
641         switch (event->header.type) {
642         case PERF_RECORD_SAMPLE:
643                 return process_sample_event(event, offset, head);
644
645         case PERF_RECORD_MMAP:
646                 return process_mmap_event(event, offset, head);
647
648         case PERF_RECORD_COMM:
649                 return process_comm_event(event, offset, head);
650
651         case PERF_RECORD_FORK:
652                 return process_fork_event(event, offset, head);
653         /*
654          * We dont process them right now but they are fine:
655          */
656
657         case PERF_RECORD_THROTTLE:
658         case PERF_RECORD_UNTHROTTLE:
659                 return 0;
660
661         default:
662                 return -1;
663         }
664
665         return 0;
666 }
667
668 static int
669 parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
670 {
671         char *line = NULL, *tmp, *tmp2;
672         static const char *prev_line;
673         static const char *prev_color;
674         unsigned int offset;
675         size_t line_len;
676         s64 line_ip;
677         int ret;
678         char *c;
679
680         if (getline(&line, &line_len, file) < 0)
681                 return -1;
682         if (!line)
683                 return -1;
684
685         c = strchr(line, '\n');
686         if (c)
687                 *c = 0;
688
689         line_ip = -1;
690         offset = 0;
691         ret = -2;
692
693         /*
694          * Strip leading spaces:
695          */
696         tmp = line;
697         while (*tmp) {
698                 if (*tmp != ' ')
699                         break;
700                 tmp++;
701         }
702
703         if (*tmp) {
704                 /*
705                  * Parse hexa addresses followed by ':'
706                  */
707                 line_ip = strtoull(tmp, &tmp2, 16);
708                 if (*tmp2 != ':')
709                         line_ip = -1;
710         }
711
712         if (line_ip != -1) {
713                 const char *path = NULL;
714                 unsigned int hits = 0;
715                 double percent = 0.0;
716                 const char *color;
717                 struct sym_ext *sym_ext = sym->priv;
718
719                 offset = line_ip - start;
720                 if (offset < len)
721                         hits = sym->hist[offset];
722
723                 if (offset < len && sym_ext) {
724                         path = sym_ext[offset].path;
725                         percent = sym_ext[offset].percent;
726                 } else if (sym->hist_sum)
727                         percent = 100.0 * hits / sym->hist_sum;
728
729                 color = get_percent_color(percent);
730
731                 /*
732                  * Also color the filename and line if needed, with
733                  * the same color than the percentage. Don't print it
734                  * twice for close colored ip with the same filename:line
735                  */
736                 if (path) {
737                         if (!prev_line || strcmp(prev_line, path)
738                                        || color != prev_color) {
739                                 color_fprintf(stdout, color, " %s", path);
740                                 prev_line = path;
741                                 prev_color = color;
742                         }
743                 }
744
745                 color_fprintf(stdout, color, " %7.2f", percent);
746                 printf(" :      ");
747                 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", line);
748         } else {
749                 if (!*line)
750                         printf("         :\n");
751                 else
752                         printf("         :      %s\n", line);
753         }
754
755         return 0;
756 }
757
758 static struct rb_root root_sym_ext;
759
760 static void insert_source_line(struct sym_ext *sym_ext)
761 {
762         struct sym_ext *iter;
763         struct rb_node **p = &root_sym_ext.rb_node;
764         struct rb_node *parent = NULL;
765
766         while (*p != NULL) {
767                 parent = *p;
768                 iter = rb_entry(parent, struct sym_ext, node);
769
770                 if (sym_ext->percent > iter->percent)
771                         p = &(*p)->rb_left;
772                 else
773                         p = &(*p)->rb_right;
774         }
775
776         rb_link_node(&sym_ext->node, parent, p);
777         rb_insert_color(&sym_ext->node, &root_sym_ext);
778 }
779
780 static void free_source_line(struct symbol *sym, int len)
781 {
782         struct sym_ext *sym_ext = sym->priv;
783         int i;
784
785         if (!sym_ext)
786                 return;
787
788         for (i = 0; i < len; i++)
789                 free(sym_ext[i].path);
790         free(sym_ext);
791
792         sym->priv = NULL;
793         root_sym_ext = RB_ROOT;
794 }
795
796 /* Get the filename:line for the colored entries */
797 static void
798 get_source_line(struct symbol *sym, u64 start, int len, const char *filename)
799 {
800         int i;
801         char cmd[PATH_MAX * 2];
802         struct sym_ext *sym_ext;
803
804         if (!sym->hist_sum)
805                 return;
806
807         sym->priv = calloc(len, sizeof(struct sym_ext));
808         if (!sym->priv)
809                 return;
810
811         sym_ext = sym->priv;
812
813         for (i = 0; i < len; i++) {
814                 char *path = NULL;
815                 size_t line_len;
816                 u64 offset;
817                 FILE *fp;
818
819                 sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum;
820                 if (sym_ext[i].percent <= 0.5)
821                         continue;
822
823                 offset = start + i;
824                 sprintf(cmd, "addr2line -e %s %016llx", filename, offset);
825                 fp = popen(cmd, "r");
826                 if (!fp)
827                         continue;
828
829                 if (getline(&path, &line_len, fp) < 0 || !line_len)
830                         goto next;
831
832                 sym_ext[i].path = malloc(sizeof(char) * line_len + 1);
833                 if (!sym_ext[i].path)
834                         goto next;
835
836                 strcpy(sym_ext[i].path, path);
837                 insert_source_line(&sym_ext[i]);
838
839         next:
840                 pclose(fp);
841         }
842 }
843
844 static void print_summary(const char *filename)
845 {
846         struct sym_ext *sym_ext;
847         struct rb_node *node;
848
849         printf("\nSorted summary for file %s\n", filename);
850         printf("----------------------------------------------\n\n");
851
852         if (RB_EMPTY_ROOT(&root_sym_ext)) {
853                 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
854                 return;
855         }
856
857         node = rb_first(&root_sym_ext);
858         while (node) {
859                 double percent;
860                 const char *color;
861                 char *path;
862
863                 sym_ext = rb_entry(node, struct sym_ext, node);
864                 percent = sym_ext->percent;
865                 color = get_percent_color(percent);
866                 path = sym_ext->path;
867
868                 color_fprintf(stdout, color, " %7.2f %s", percent, path);
869                 node = rb_next(node);
870         }
871 }
872
873 static void annotate_sym(struct dso *dso, struct symbol *sym)
874 {
875         const char *filename = dso->name, *d_filename;
876         u64 start, end, len;
877         char command[PATH_MAX*2];
878         FILE *file;
879
880         if (!filename)
881                 return;
882         if (sym->module)
883                 filename = sym->module->path;
884         else if (dso == kernel_dso)
885                 filename = vmlinux_name;
886
887         start = sym->obj_start;
888         if (!start)
889                 start = sym->start;
890         if (full_paths)
891                 d_filename = filename;
892         else
893                 d_filename = basename(filename);
894
895         end = start + sym->end - sym->start + 1;
896         len = sym->end - sym->start;
897
898         if (print_line) {
899                 get_source_line(sym, start, len, filename);
900                 print_summary(filename);
901         }
902
903         printf("\n\n------------------------------------------------\n");
904         printf(" Percent |      Source code & Disassembly of %s\n", d_filename);
905         printf("------------------------------------------------\n");
906
907         if (verbose >= 2)
908                 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
909
910         sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
911                         (u64)start, (u64)end, filename, filename);
912
913         if (verbose >= 3)
914                 printf("doing: %s\n", command);
915
916         file = popen(command, "r");
917         if (!file)
918                 return;
919
920         while (!feof(file)) {
921                 if (parse_line(file, sym, start, len) < 0)
922                         break;
923         }
924
925         pclose(file);
926         if (print_line)
927                 free_source_line(sym, len);
928 }
929
930 static void find_annotations(void)
931 {
932         struct rb_node *nd;
933         struct dso *dso;
934         int count = 0;
935
936         list_for_each_entry(dso, &dsos, node) {
937
938                 for (nd = rb_first(&dso->syms); nd; nd = rb_next(nd)) {
939                         struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
940
941                         if (sym->hist) {
942                                 annotate_sym(dso, sym);
943                                 count++;
944                         }
945                 }
946         }
947
948         if (!count)
949                 printf(" Error: symbol '%s' not present amongst the samples.\n", sym_hist_filter);
950 }
951
952 static int __cmd_annotate(void)
953 {
954         int ret, rc = EXIT_FAILURE;
955         unsigned long offset = 0;
956         unsigned long head = 0;
957         struct stat input_stat;
958         event_t *event;
959         uint32_t size;
960         char *buf;
961
962         register_idle_thread(&threads, &last_match);
963
964         input = open(input_name, O_RDONLY);
965         if (input < 0) {
966                 perror("failed to open file");
967                 exit(-1);
968         }
969
970         ret = fstat(input, &input_stat);
971         if (ret < 0) {
972                 perror("failed to stat file");
973                 exit(-1);
974         }
975
976         if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
977                 fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
978                 exit(-1);
979         }
980
981         if (!input_stat.st_size) {
982                 fprintf(stderr, "zero-sized file, nothing to do!\n");
983                 exit(0);
984         }
985
986         if (load_kernel() < 0) {
987                 perror("failed to load kernel symbols");
988                 return EXIT_FAILURE;
989         }
990
991 remap:
992         buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
993                            MAP_SHARED, input, offset);
994         if (buf == MAP_FAILED) {
995                 perror("failed to mmap file");
996                 exit(-1);
997         }
998
999 more:
1000         event = (event_t *)(buf + head);
1001
1002         size = event->header.size;
1003         if (!size)
1004                 size = 8;
1005
1006         if (head + event->header.size >= page_size * mmap_window) {
1007                 unsigned long shift = page_size * (head / page_size);
1008                 int munmap_ret;
1009
1010                 munmap_ret = munmap(buf, page_size * mmap_window);
1011                 assert(munmap_ret == 0);
1012
1013                 offset += shift;
1014                 head -= shift;
1015                 goto remap;
1016         }
1017
1018         size = event->header.size;
1019
1020         dump_printf("%p [%p]: event: %d\n",
1021                         (void *)(offset + head),
1022                         (void *)(long)event->header.size,
1023                         event->header.type);
1024
1025         if (!size || process_event(event, offset, head) < 0) {
1026
1027                 dump_printf("%p [%p]: skipping unknown header type: %d\n",
1028                         (void *)(offset + head),
1029                         (void *)(long)(event->header.size),
1030                         event->header.type);
1031
1032                 total_unknown++;
1033
1034                 /*
1035                  * assume we lost track of the stream, check alignment, and
1036                  * increment a single u64 in the hope to catch on again 'soon'.
1037                  */
1038
1039                 if (unlikely(head & 7))
1040                         head &= ~7ULL;
1041
1042                 size = 8;
1043         }
1044
1045         head += size;
1046
1047         if (offset + head < (unsigned long)input_stat.st_size)
1048                 goto more;
1049
1050         rc = EXIT_SUCCESS;
1051         close(input);
1052
1053         dump_printf("      IP events: %10ld\n", total);
1054         dump_printf("    mmap events: %10ld\n", total_mmap);
1055         dump_printf("    comm events: %10ld\n", total_comm);
1056         dump_printf("    fork events: %10ld\n", total_fork);
1057         dump_printf(" unknown events: %10ld\n", total_unknown);
1058
1059         if (dump_trace)
1060                 return 0;
1061
1062         if (verbose >= 3)
1063                 threads__fprintf(stdout, &threads);
1064
1065         if (verbose >= 2)
1066                 dsos__fprintf(stdout);
1067
1068         collapse__resort();
1069         output__resort();
1070
1071         find_annotations();
1072
1073         return rc;
1074 }
1075
1076 static const char * const annotate_usage[] = {
1077         "perf annotate [<options>] <command>",
1078         NULL
1079 };
1080
1081 static const struct option options[] = {
1082         OPT_STRING('i', "input", &input_name, "file",
1083                     "input file name"),
1084         OPT_STRING('s', "symbol", &sym_hist_filter, "symbol",
1085                     "symbol to annotate"),
1086         OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
1087         OPT_BOOLEAN('v', "verbose", &verbose,
1088                     "be more verbose (show symbol address, etc)"),
1089         OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1090                     "dump raw trace in ASCII"),
1091         OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
1092         OPT_BOOLEAN('m', "modules", &modules,
1093                     "load module symbols - WARNING: use only with -k and LIVE kernel"),
1094         OPT_BOOLEAN('l', "print-line", &print_line,
1095                     "print matching source lines (may be slow)"),
1096         OPT_BOOLEAN('P', "full-paths", &full_paths,
1097                     "Don't shorten the displayed pathnames"),
1098         OPT_END()
1099 };
1100
1101 static void setup_sorting(void)
1102 {
1103         char *tmp, *tok, *str = strdup(sort_order);
1104
1105         for (tok = strtok_r(str, ", ", &tmp);
1106                         tok; tok = strtok_r(NULL, ", ", &tmp)) {
1107                 if (sort_dimension__add(tok) < 0) {
1108                         error("Unknown --sort key: `%s'", tok);
1109                         usage_with_options(annotate_usage, options);
1110                 }
1111         }
1112
1113         free(str);
1114 }
1115
1116 int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1117 {
1118         symbol__init();
1119
1120         page_size = getpagesize();
1121
1122         argc = parse_options(argc, argv, options, annotate_usage, 0);
1123
1124         setup_sorting();
1125
1126         if (argc) {
1127                 /*
1128                  * Special case: if there's an argument left then assume tha
1129                  * it's a symbol filter:
1130                  */
1131                 if (argc > 1)
1132                         usage_with_options(annotate_usage, options);
1133
1134                 sym_hist_filter = argv[0];
1135         }
1136
1137         if (!sym_hist_filter)
1138                 usage_with_options(annotate_usage, options);
1139
1140         setup_pager();
1141
1142         return __cmd_annotate();
1143 }