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