perf tools: Use common process_event functions for annotate and report
[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 #include "util/sort.h"
26 #include "util/hist.h"
27 #include "util/process_events.h"
28
29 static char             const *input_name = "perf.data";
30
31 static int              force;
32 static int              input;
33
34 static int              full_paths;
35
36 static int              print_line;
37 static bool             use_modules;
38
39 static unsigned long    page_size;
40 static unsigned long    mmap_window = 32;
41 const char              *vmlinux_name;
42
43 struct sym_hist {
44         u64             sum;
45         u64             ip[0];
46 };
47
48 struct sym_ext {
49         struct rb_node  node;
50         double          percent;
51         char            *path;
52 };
53
54 struct sym_priv {
55         struct sym_hist *hist;
56         struct sym_ext  *ext;
57 };
58
59 static const char *sym_hist_filter;
60
61 static int symbol_filter(struct map *map __used, struct symbol *sym)
62 {
63         if (sym_hist_filter == NULL ||
64             strcmp(sym->name, sym_hist_filter) == 0) {
65                 struct sym_priv *priv = symbol__priv(sym);
66                 const int size = (sizeof(*priv->hist) +
67                                   (sym->end - sym->start) * sizeof(u64));
68
69                 priv->hist = malloc(size);
70                 if (priv->hist)
71                         memset(priv->hist, 0, size);
72                 return 0;
73         }
74         /*
75          * FIXME: We should really filter it out, as we don't want to go thru symbols
76          * we're not interested, and if a DSO ends up with no symbols, delete it too,
77          * but right now the kernel loading routines in symbol.c bail out if no symbols
78          * are found, fix it later.
79          */
80         return 0;
81 }
82
83 /*
84  * collect histogram counts
85  */
86 static void hist_hit(struct hist_entry *he, u64 ip)
87 {
88         unsigned int sym_size, offset;
89         struct symbol *sym = he->sym;
90         struct sym_priv *priv;
91         struct sym_hist *h;
92
93         he->count++;
94
95         if (!sym || !he->map)
96                 return;
97
98         priv = symbol__priv(sym);
99         if (!priv->hist)
100                 return;
101
102         sym_size = sym->end - sym->start;
103         offset = ip - sym->start;
104
105         if (verbose)
106                 fprintf(stderr, "%s: ip=%Lx\n", __func__,
107                         he->map->unmap_ip(he->map, ip));
108
109         if (offset >= sym_size)
110                 return;
111
112         h = priv->hist;
113         h->sum++;
114         h->ip[offset]++;
115
116         if (verbose >= 3)
117                 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n",
118                         (void *)(unsigned long)he->sym->start,
119                         he->sym->name,
120                         (void *)(unsigned long)ip, ip - he->sym->start,
121                         h->ip[offset]);
122 }
123
124 static int hist_entry__add(struct thread *thread, struct map *map,
125                            struct symbol *sym, u64 ip, u64 count, char level)
126 {
127         bool hit;
128         struct hist_entry *he = __hist_entry__add(thread, map, sym, NULL, ip,
129                                                   count, level, &hit);
130         if (he == NULL)
131                 return -ENOMEM;
132         hist_hit(he, ip);
133         return 0;
134 }
135
136 static int
137 process_sample_event(event_t *event, unsigned long offset, unsigned long head)
138 {
139         char level;
140         u64 ip = event->ip.ip;
141         struct map *map = NULL;
142         struct symbol *sym = NULL;
143         struct thread *thread = threads__findnew(event->ip.pid);
144
145         dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
146                 (void *)(offset + head),
147                 (void *)(long)(event->header.size),
148                 event->header.misc,
149                 event->ip.pid,
150                 (void *)(long)ip);
151
152         if (thread == NULL) {
153                 fprintf(stderr, "problem processing %d event, skipping it.\n",
154                         event->header.type);
155                 return -1;
156         }
157
158         dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
159
160         if (event->header.misc & PERF_RECORD_MISC_KERNEL) {
161                 level = 'k';
162                 sym = kernel_maps__find_symbol(ip, &map, symbol_filter);
163                 dump_printf(" ...... dso: %s\n",
164                             map ? map->dso->long_name : "<not found>");
165         } else if (event->header.misc & PERF_RECORD_MISC_USER) {
166                 level = '.';
167                 map = thread__find_map(thread, ip);
168                 if (map != NULL) {
169 got_map:
170                         ip = map->map_ip(map, ip);
171                         sym = map__find_symbol(map, ip, symbol_filter);
172                 } else {
173                         /*
174                          * If this is outside of all known maps,
175                          * and is a negative address, try to look it
176                          * up in the kernel dso, as it might be a
177                          * vsyscall or vdso (which executes in user-mode).
178                          *
179                          * XXX This is nasty, we should have a symbol list in
180                          * the "[vdso]" dso, but for now lets use the old
181                          * trick of looking in the whole kernel symbol list.
182                          */
183                         if ((long long)ip < 0) {
184                                 map = kernel_map;
185                                 goto got_map;
186                         }
187                 }
188                 dump_printf(" ...... dso: %s\n",
189                             map ? map->dso->long_name : "<not found>");
190         } else {
191                 level = 'H';
192                 dump_printf(" ...... dso: [hypervisor]\n");
193         }
194
195         if (hist_entry__add(thread, map, sym, ip, 1, level)) {
196                 fprintf(stderr, "problem incrementing symbol count, "
197                                 "skipping event\n");
198                 return -1;
199         }
200         total++;
201
202         return 0;
203 }
204
205 static int
206 process_comm_event(event_t *event, unsigned long offset, unsigned long head)
207 {
208         struct thread *thread = threads__findnew(event->comm.pid);
209
210         dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
211                 (void *)(offset + head),
212                 (void *)(long)(event->header.size),
213                 event->comm.comm, event->comm.pid);
214
215         if (thread == NULL ||
216             thread__set_comm(thread, event->comm.comm)) {
217                 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
218                 return -1;
219         }
220         total_comm++;
221
222         return 0;
223 }
224
225 static int
226 process_event(event_t *event, unsigned long offset, unsigned long head)
227 {
228         switch (event->header.type) {
229         case PERF_RECORD_SAMPLE:
230                 return process_sample_event(event, offset, head);
231
232         case PERF_RECORD_MMAP:
233                 return process_mmap_event(event, offset, head);
234
235         case PERF_RECORD_COMM:
236                 return process_comm_event(event, offset, head);
237
238         case PERF_RECORD_FORK:
239                 return process_task_event(event, offset, head);
240         /*
241          * We dont process them right now but they are fine:
242          */
243
244         case PERF_RECORD_THROTTLE:
245         case PERF_RECORD_UNTHROTTLE:
246                 return 0;
247
248         default:
249                 return -1;
250         }
251
252         return 0;
253 }
254
255 static int parse_line(FILE *file, struct hist_entry *he, u64 len)
256 {
257         struct symbol *sym = he->sym;
258         char *line = NULL, *tmp, *tmp2;
259         static const char *prev_line;
260         static const char *prev_color;
261         unsigned int offset;
262         size_t line_len;
263         u64 start;
264         s64 line_ip;
265         int ret;
266         char *c;
267
268         if (getline(&line, &line_len, file) < 0)
269                 return -1;
270         if (!line)
271                 return -1;
272
273         c = strchr(line, '\n');
274         if (c)
275                 *c = 0;
276
277         line_ip = -1;
278         offset = 0;
279         ret = -2;
280
281         /*
282          * Strip leading spaces:
283          */
284         tmp = line;
285         while (*tmp) {
286                 if (*tmp != ' ')
287                         break;
288                 tmp++;
289         }
290
291         if (*tmp) {
292                 /*
293                  * Parse hexa addresses followed by ':'
294                  */
295                 line_ip = strtoull(tmp, &tmp2, 16);
296                 if (*tmp2 != ':')
297                         line_ip = -1;
298         }
299
300         start = he->map->unmap_ip(he->map, sym->start);
301
302         if (line_ip != -1) {
303                 const char *path = NULL;
304                 unsigned int hits = 0;
305                 double percent = 0.0;
306                 const char *color;
307                 struct sym_priv *priv = symbol__priv(sym);
308                 struct sym_ext *sym_ext = priv->ext;
309                 struct sym_hist *h = priv->hist;
310
311                 offset = line_ip - start;
312                 if (offset < len)
313                         hits = h->ip[offset];
314
315                 if (offset < len && sym_ext) {
316                         path = sym_ext[offset].path;
317                         percent = sym_ext[offset].percent;
318                 } else if (h->sum)
319                         percent = 100.0 * hits / h->sum;
320
321                 color = get_percent_color(percent);
322
323                 /*
324                  * Also color the filename and line if needed, with
325                  * the same color than the percentage. Don't print it
326                  * twice for close colored ip with the same filename:line
327                  */
328                 if (path) {
329                         if (!prev_line || strcmp(prev_line, path)
330                                        || color != prev_color) {
331                                 color_fprintf(stdout, color, " %s", path);
332                                 prev_line = path;
333                                 prev_color = color;
334                         }
335                 }
336
337                 color_fprintf(stdout, color, " %7.2f", percent);
338                 printf(" :      ");
339                 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", line);
340         } else {
341                 if (!*line)
342                         printf("         :\n");
343                 else
344                         printf("         :      %s\n", line);
345         }
346
347         return 0;
348 }
349
350 static struct rb_root root_sym_ext;
351
352 static void insert_source_line(struct sym_ext *sym_ext)
353 {
354         struct sym_ext *iter;
355         struct rb_node **p = &root_sym_ext.rb_node;
356         struct rb_node *parent = NULL;
357
358         while (*p != NULL) {
359                 parent = *p;
360                 iter = rb_entry(parent, struct sym_ext, node);
361
362                 if (sym_ext->percent > iter->percent)
363                         p = &(*p)->rb_left;
364                 else
365                         p = &(*p)->rb_right;
366         }
367
368         rb_link_node(&sym_ext->node, parent, p);
369         rb_insert_color(&sym_ext->node, &root_sym_ext);
370 }
371
372 static void free_source_line(struct hist_entry *he, int len)
373 {
374         struct sym_priv *priv = symbol__priv(he->sym);
375         struct sym_ext *sym_ext = priv->ext;
376         int i;
377
378         if (!sym_ext)
379                 return;
380
381         for (i = 0; i < len; i++)
382                 free(sym_ext[i].path);
383         free(sym_ext);
384
385         priv->ext = NULL;
386         root_sym_ext = RB_ROOT;
387 }
388
389 /* Get the filename:line for the colored entries */
390 static void
391 get_source_line(struct hist_entry *he, int len, const char *filename)
392 {
393         struct symbol *sym = he->sym;
394         u64 start;
395         int i;
396         char cmd[PATH_MAX * 2];
397         struct sym_ext *sym_ext;
398         struct sym_priv *priv = symbol__priv(sym);
399         struct sym_hist *h = priv->hist;
400
401         if (!h->sum)
402                 return;
403
404         sym_ext = priv->ext = calloc(len, sizeof(struct sym_ext));
405         if (!priv->ext)
406                 return;
407
408         start = he->map->unmap_ip(he->map, sym->start);
409
410         for (i = 0; i < len; i++) {
411                 char *path = NULL;
412                 size_t line_len;
413                 u64 offset;
414                 FILE *fp;
415
416                 sym_ext[i].percent = 100.0 * h->ip[i] / h->sum;
417                 if (sym_ext[i].percent <= 0.5)
418                         continue;
419
420                 offset = start + i;
421                 sprintf(cmd, "addr2line -e %s %016llx", filename, offset);
422                 fp = popen(cmd, "r");
423                 if (!fp)
424                         continue;
425
426                 if (getline(&path, &line_len, fp) < 0 || !line_len)
427                         goto next;
428
429                 sym_ext[i].path = malloc(sizeof(char) * line_len + 1);
430                 if (!sym_ext[i].path)
431                         goto next;
432
433                 strcpy(sym_ext[i].path, path);
434                 insert_source_line(&sym_ext[i]);
435
436         next:
437                 pclose(fp);
438         }
439 }
440
441 static void print_summary(const char *filename)
442 {
443         struct sym_ext *sym_ext;
444         struct rb_node *node;
445
446         printf("\nSorted summary for file %s\n", filename);
447         printf("----------------------------------------------\n\n");
448
449         if (RB_EMPTY_ROOT(&root_sym_ext)) {
450                 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
451                 return;
452         }
453
454         node = rb_first(&root_sym_ext);
455         while (node) {
456                 double percent;
457                 const char *color;
458                 char *path;
459
460                 sym_ext = rb_entry(node, struct sym_ext, node);
461                 percent = sym_ext->percent;
462                 color = get_percent_color(percent);
463                 path = sym_ext->path;
464
465                 color_fprintf(stdout, color, " %7.2f %s", percent, path);
466                 node = rb_next(node);
467         }
468 }
469
470 static void annotate_sym(struct hist_entry *he)
471 {
472         struct map *map = he->map;
473         struct dso *dso = map->dso;
474         struct symbol *sym = he->sym;
475         const char *filename = dso->long_name, *d_filename;
476         u64 len;
477         char command[PATH_MAX*2];
478         FILE *file;
479
480         if (!filename)
481                 return;
482
483         if (verbose)
484                 fprintf(stderr, "%s: filename=%s, sym=%s, start=%Lx, end=%Lx\n",
485                         __func__, filename, sym->name,
486                         map->unmap_ip(map, sym->start),
487                         map->unmap_ip(map, sym->end));
488
489         if (full_paths)
490                 d_filename = filename;
491         else
492                 d_filename = basename(filename);
493
494         len = sym->end - sym->start;
495
496         if (print_line) {
497                 get_source_line(he, len, filename);
498                 print_summary(filename);
499         }
500
501         printf("\n\n------------------------------------------------\n");
502         printf(" Percent |      Source code & Disassembly of %s\n", d_filename);
503         printf("------------------------------------------------\n");
504
505         if (verbose >= 2)
506                 printf("annotating [%p] %30s : [%p] %30s\n",
507                        dso, dso->long_name, sym, sym->name);
508
509         sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
510                 map->unmap_ip(map, sym->start), map->unmap_ip(map, sym->end),
511                 filename, filename);
512
513         if (verbose >= 3)
514                 printf("doing: %s\n", command);
515
516         file = popen(command, "r");
517         if (!file)
518                 return;
519
520         while (!feof(file)) {
521                 if (parse_line(file, he, len) < 0)
522                         break;
523         }
524
525         pclose(file);
526         if (print_line)
527                 free_source_line(he, len);
528 }
529
530 static void find_annotations(void)
531 {
532         struct rb_node *nd;
533
534         for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
535                 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
536                 struct sym_priv *priv;
537
538                 if (he->sym == NULL)
539                         continue;
540
541                 priv = symbol__priv(he->sym);
542                 if (priv->hist == NULL)
543                         continue;
544
545                 annotate_sym(he);
546                 /*
547                  * Since we have a hist_entry per IP for the same symbol, free
548                  * he->sym->hist to signal we already processed this symbol.
549                  */
550                 free(priv->hist);
551                 priv->hist = NULL;
552         }
553 }
554
555 static int __cmd_annotate(void)
556 {
557         int ret, rc = EXIT_FAILURE;
558         unsigned long offset = 0;
559         unsigned long head = 0;
560         struct stat input_stat;
561         event_t *event;
562         uint32_t size;
563         char *buf;
564
565         register_idle_thread();
566
567         input = open(input_name, O_RDONLY);
568         if (input < 0) {
569                 perror("failed to open file");
570                 exit(-1);
571         }
572
573         ret = fstat(input, &input_stat);
574         if (ret < 0) {
575                 perror("failed to stat file");
576                 exit(-1);
577         }
578
579         if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
580                 fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
581                 exit(-1);
582         }
583
584         if (!input_stat.st_size) {
585                 fprintf(stderr, "zero-sized file, nothing to do!\n");
586                 exit(0);
587         }
588
589         if (kernel_maps__init(vmlinux_name, true, use_modules) < 0) {
590                 pr_err("failed to create kernel maps for symbol resolution\b");
591                 return -1;
592         }
593
594 remap:
595         buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
596                            MAP_SHARED, input, offset);
597         if (buf == MAP_FAILED) {
598                 perror("failed to mmap file");
599                 exit(-1);
600         }
601
602 more:
603         event = (event_t *)(buf + head);
604
605         size = event->header.size;
606         if (!size)
607                 size = 8;
608
609         if (head + event->header.size >= page_size * mmap_window) {
610                 unsigned long shift = page_size * (head / page_size);
611                 int munmap_ret;
612
613                 munmap_ret = munmap(buf, page_size * mmap_window);
614                 assert(munmap_ret == 0);
615
616                 offset += shift;
617                 head -= shift;
618                 goto remap;
619         }
620
621         size = event->header.size;
622
623         dump_printf("%p [%p]: event: %d\n",
624                         (void *)(offset + head),
625                         (void *)(long)event->header.size,
626                         event->header.type);
627
628         if (!size || process_event(event, offset, head) < 0) {
629
630                 dump_printf("%p [%p]: skipping unknown header type: %d\n",
631                         (void *)(offset + head),
632                         (void *)(long)(event->header.size),
633                         event->header.type);
634
635                 total_unknown++;
636
637                 /*
638                  * assume we lost track of the stream, check alignment, and
639                  * increment a single u64 in the hope to catch on again 'soon'.
640                  */
641
642                 if (unlikely(head & 7))
643                         head &= ~7ULL;
644
645                 size = 8;
646         }
647
648         head += size;
649
650         if (offset + head < (unsigned long)input_stat.st_size)
651                 goto more;
652
653         rc = EXIT_SUCCESS;
654         close(input);
655
656         dump_printf("      IP events: %10ld\n", total);
657         dump_printf("    mmap events: %10ld\n", total_mmap);
658         dump_printf("    comm events: %10ld\n", total_comm);
659         dump_printf("    fork events: %10ld\n", total_fork);
660         dump_printf(" unknown events: %10ld\n", total_unknown);
661
662         if (dump_trace)
663                 return 0;
664
665         if (verbose > 3)
666                 threads__fprintf(stdout);
667
668         if (verbose > 2)
669                 dsos__fprintf(stdout);
670
671         collapse__resort();
672         output__resort(total);
673
674         find_annotations();
675
676         return rc;
677 }
678
679 static const char * const annotate_usage[] = {
680         "perf annotate [<options>] <command>",
681         NULL
682 };
683
684 static const struct option options[] = {
685         OPT_STRING('i', "input", &input_name, "file",
686                     "input file name"),
687         OPT_STRING('s', "symbol", &sym_hist_filter, "symbol",
688                     "symbol to annotate"),
689         OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
690         OPT_BOOLEAN('v', "verbose", &verbose,
691                     "be more verbose (show symbol address, etc)"),
692         OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
693                     "dump raw trace in ASCII"),
694         OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
695         OPT_BOOLEAN('m', "modules", &use_modules,
696                     "load module symbols - WARNING: use only with -k and LIVE kernel"),
697         OPT_BOOLEAN('l', "print-line", &print_line,
698                     "print matching source lines (may be slow)"),
699         OPT_BOOLEAN('P', "full-paths", &full_paths,
700                     "Don't shorten the displayed pathnames"),
701         OPT_END()
702 };
703
704 static void setup_sorting(void)
705 {
706         char *tmp, *tok, *str = strdup(sort_order);
707
708         for (tok = strtok_r(str, ", ", &tmp);
709                         tok; tok = strtok_r(NULL, ", ", &tmp)) {
710                 if (sort_dimension__add(tok) < 0) {
711                         error("Unknown --sort key: `%s'", tok);
712                         usage_with_options(annotate_usage, options);
713                 }
714         }
715
716         free(str);
717 }
718
719 int cmd_annotate(int argc, const char **argv, const char *prefix __used)
720 {
721         symbol__init(sizeof(struct sym_priv));
722
723         page_size = getpagesize();
724
725         argc = parse_options(argc, argv, options, annotate_usage, 0);
726
727         setup_sorting();
728
729         if (argc) {
730                 /*
731                  * Special case: if there's an argument left then assume tha
732                  * it's a symbol filter:
733                  */
734                 if (argc > 1)
735                         usage_with_options(annotate_usage, options);
736
737                 sym_hist_filter = argv[0];
738         }
739
740         setup_pager();
741
742         if (field_sep && *field_sep == '.') {
743                 fputs("'.' is the only non valid --field-separator argument\n",
744                                 stderr);
745                 exit(129);
746         }
747
748         return __cmd_annotate();
749 }