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