]> git.karo-electronics.de Git - mv-sheeva.git/blob - Documentation/perf_counter/builtin-report.c
perf_counter: tools: report: Dynamic sort/print bits
[mv-sheeva.git] / Documentation / perf_counter / builtin-report.c
1 #include "util/util.h"
2 #include "builtin.h"
3
4 #include <libelf.h>
5 #include <gelf.h>
6 #include <elf.h>
7
8 #include "util/list.h"
9 #include "util/cache.h"
10 #include "util/rbtree.h"
11
12 #include "perf.h"
13
14 #include "util/parse-options.h"
15 #include "util/parse-events.h"
16
17 #define SHOW_KERNEL     1
18 #define SHOW_USER       2
19 #define SHOW_HV         4
20
21 static char             const *input_name = "perf.data";
22 static char             *vmlinux = NULL;
23 static int              input;
24 static int              show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
25
26 static int              dump_trace = 0;
27 static int              verbose;
28
29 static unsigned long    page_size;
30 static unsigned long    mmap_window = 32;
31
32 const char *perf_event_names[] = {
33         [PERF_EVENT_MMAP]   = " PERF_EVENT_MMAP",
34         [PERF_EVENT_MUNMAP] = " PERF_EVENT_MUNMAP",
35         [PERF_EVENT_COMM]   = " PERF_EVENT_COMM",
36 };
37
38 struct ip_event {
39         struct perf_event_header header;
40         __u64 ip;
41         __u32 pid, tid;
42 };
43 struct mmap_event {
44         struct perf_event_header header;
45         __u32 pid, tid;
46         __u64 start;
47         __u64 len;
48         __u64 pgoff;
49         char filename[PATH_MAX];
50 };
51 struct comm_event {
52         struct perf_event_header header;
53         __u32 pid,tid;
54         char comm[16];
55 };
56
57 typedef union event_union {
58         struct perf_event_header header;
59         struct ip_event ip;
60         struct mmap_event mmap;
61         struct comm_event comm;
62 } event_t;
63
64 struct symbol {
65         struct rb_node          rb_node;
66         __u64                   start;
67         __u64                   end;
68         char                    name[0];
69 };
70
71 static struct symbol *symbol__new(uint64_t start, uint64_t len, const char *name)
72 {
73         struct symbol *self = malloc(sizeof(*self) + strlen(name) + 1);
74
75         if (self != NULL) {
76                 self->start = start;
77                 self->end   = start + len;
78                 strcpy(self->name, name);
79         }
80
81         return self;
82 }
83
84 static void symbol__delete(struct symbol *self)
85 {
86         free(self);
87 }
88
89 static size_t symbol__fprintf(struct symbol *self, FILE *fp)
90 {
91         return fprintf(fp, " %llx-%llx %s\n",
92                        self->start, self->end, self->name);
93 }
94
95 struct dso {
96         struct list_head node;
97         struct rb_root   syms;
98         char             name[0];
99 };
100
101 static struct dso *dso__new(const char *name)
102 {
103         struct dso *self = malloc(sizeof(*self) + strlen(name) + 1);
104
105         if (self != NULL) {
106                 strcpy(self->name, name);
107                 self->syms = RB_ROOT;
108         }
109
110         return self;
111 }
112
113 static void dso__delete_symbols(struct dso *self)
114 {
115         struct symbol *pos;
116         struct rb_node *next = rb_first(&self->syms);
117
118         while (next) {
119                 pos = rb_entry(next, struct symbol, rb_node);
120                 next = rb_next(&pos->rb_node);
121                 symbol__delete(pos);
122         }
123 }
124
125 static void dso__delete(struct dso *self)
126 {
127         dso__delete_symbols(self);
128         free(self);
129 }
130
131 static void dso__insert_symbol(struct dso *self, struct symbol *sym)
132 {
133         struct rb_node **p = &self->syms.rb_node;
134         struct rb_node *parent = NULL;
135         const uint64_t ip = sym->start;
136         struct symbol *s;
137
138         while (*p != NULL) {
139                 parent = *p;
140                 s = rb_entry(parent, struct symbol, rb_node);
141                 if (ip < s->start)
142                         p = &(*p)->rb_left;
143                 else
144                         p = &(*p)->rb_right;
145         }
146         rb_link_node(&sym->rb_node, parent, p);
147         rb_insert_color(&sym->rb_node, &self->syms);
148 }
149
150 static struct symbol *dso__find_symbol(struct dso *self, uint64_t ip)
151 {
152         struct rb_node *n;
153
154         if (self == NULL)
155                 return NULL;
156
157         n = self->syms.rb_node;
158
159         while (n) {
160                 struct symbol *s = rb_entry(n, struct symbol, rb_node);
161
162                 if (ip < s->start)
163                         n = n->rb_left;
164                 else if (ip > s->end)
165                         n = n->rb_right;
166                 else
167                         return s;
168         }
169
170         return NULL;
171 }
172
173 /**
174  * elf_symtab__for_each_symbol - iterate thru all the symbols
175  *
176  * @self: struct elf_symtab instance to iterate
177  * @index: uint32_t index
178  * @sym: GElf_Sym iterator
179  */
180 #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \
181         for (index = 0, gelf_getsym(syms, index, &sym);\
182              index < nr_syms; \
183              index++, gelf_getsym(syms, index, &sym))
184
185 static inline uint8_t elf_sym__type(const GElf_Sym *sym)
186 {
187         return GELF_ST_TYPE(sym->st_info);
188 }
189
190 static inline int elf_sym__is_function(const GElf_Sym *sym)
191 {
192         return elf_sym__type(sym) == STT_FUNC &&
193                sym->st_name != 0 &&
194                sym->st_shndx != SHN_UNDEF &&
195                sym->st_size != 0;
196 }
197
198 static inline const char *elf_sym__name(const GElf_Sym *sym,
199                                         const Elf_Data *symstrs)
200 {
201         return symstrs->d_buf + sym->st_name;
202 }
203
204 static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
205                                     GElf_Shdr *shp, const char *name,
206                                     size_t *index)
207 {
208         Elf_Scn *sec = NULL;
209         size_t cnt = 1;
210
211         while ((sec = elf_nextscn(elf, sec)) != NULL) {
212                 char *str;
213
214                 gelf_getshdr(sec, shp);
215                 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
216                 if (!strcmp(name, str)) {
217                         if (index)
218                                 *index = cnt;
219                         break;
220                 }
221                 ++cnt;
222         }
223
224         return sec;
225 }
226
227 static int dso__load_sym(struct dso *self, int fd, char *name)
228 {
229         Elf_Data *symstrs;
230         uint32_t nr_syms;
231         int err = -1;
232         uint32_t index;
233         GElf_Ehdr ehdr;
234         GElf_Shdr shdr;
235         Elf_Data *syms;
236         GElf_Sym sym;
237         Elf_Scn *sec;
238         Elf *elf;
239         int nr = 0;
240
241         elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
242         if (elf == NULL) {
243                 fprintf(stderr, "%s: cannot read %s ELF file.\n",
244                         __func__, name);
245                 goto out_close;
246         }
247
248         if (gelf_getehdr(elf, &ehdr) == NULL) {
249                 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
250                 goto out_elf_end;
251         }
252
253         sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
254         if (sec == NULL)
255                 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
256
257         if (sec == NULL)
258                 goto out_elf_end;
259
260         syms = elf_getdata(sec, NULL);
261         if (syms == NULL)
262                 goto out_elf_end;
263
264         sec = elf_getscn(elf, shdr.sh_link);
265         if (sec == NULL)
266                 goto out_elf_end;
267
268         symstrs = elf_getdata(sec, NULL);
269         if (symstrs == NULL)
270                 goto out_elf_end;
271
272         nr_syms = shdr.sh_size / shdr.sh_entsize;
273
274         elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
275                 struct symbol *f;
276
277                 if (!elf_sym__is_function(&sym))
278                         continue;
279
280                 sec = elf_getscn(elf, sym.st_shndx);
281                 if (!sec)
282                         goto out_elf_end;
283
284                 gelf_getshdr(sec, &shdr);
285                 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
286
287                 f = symbol__new(sym.st_value, sym.st_size,
288                                 elf_sym__name(&sym, symstrs));
289                 if (!f)
290                         goto out_elf_end;
291
292                 dso__insert_symbol(self, f);
293
294                 nr++;
295         }
296
297         err = nr;
298 out_elf_end:
299         elf_end(elf);
300 out_close:
301         return err;
302 }
303
304 static int dso__load(struct dso *self)
305 {
306         int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug");
307         char *name = malloc(size);
308         int variant = 0;
309         int ret = -1;
310         int fd;
311
312         if (!name)
313                 return -1;
314
315 more:
316         do {
317                 switch (variant) {
318                 case 0: /* Fedora */
319                         snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
320                         break;
321                 case 1: /* Ubuntu */
322                         snprintf(name, size, "/usr/lib/debug%s", self->name);
323                         break;
324                 case 2: /* Sane people */
325                         snprintf(name, size, "%s", self->name);
326                         break;
327
328                 default:
329                         goto out;
330                 }
331                 variant++;
332
333                 fd = open(name, O_RDONLY);
334         } while (fd < 0);
335
336         ret = dso__load_sym(self, fd, name);
337         close(fd);
338
339         /*
340          * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
341          */
342         if (!ret)
343                 goto more;
344
345 out:
346         free(name);
347         return ret;
348 }
349
350 static size_t dso__fprintf(struct dso *self, FILE *fp)
351 {
352         size_t ret = fprintf(fp, "dso: %s\n", self->name);
353
354         struct rb_node *nd;
355         for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
356                 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
357                 ret += symbol__fprintf(pos, fp);
358         }
359
360         return ret;
361 }
362
363 static LIST_HEAD(dsos);
364 static struct dso *kernel_dso;
365
366 static void dsos__add(struct dso *dso)
367 {
368         list_add_tail(&dso->node, &dsos);
369 }
370
371 static struct dso *dsos__find(const char *name)
372 {
373         struct dso *pos;
374
375         list_for_each_entry(pos, &dsos, node)
376                 if (strcmp(pos->name, name) == 0)
377                         return pos;
378         return NULL;
379 }
380
381 static struct dso *dsos__findnew(const char *name)
382 {
383         struct dso *dso = dsos__find(name);
384         int nr;
385
386         if (dso == NULL) {
387                 dso = dso__new(name);
388                 if (!dso)
389                         goto out_delete_dso;
390
391                 nr = dso__load(dso);
392                 if (nr < 0) {
393                         fprintf(stderr, "Failed to open: %s\n", name);
394                         goto out_delete_dso;
395                 }
396                 if (!nr) {
397                         fprintf(stderr,
398                 "Failed to find debug symbols for: %s, maybe install a debug package?\n",
399                                         name);
400                 }
401
402                 dsos__add(dso);
403         }
404
405         return dso;
406
407 out_delete_dso:
408         dso__delete(dso);
409         return NULL;
410 }
411
412 static void dsos__fprintf(FILE *fp)
413 {
414         struct dso *pos;
415
416         list_for_each_entry(pos, &dsos, node)
417                 dso__fprintf(pos, fp);
418 }
419
420 static int hex(char ch)
421 {
422         if ((ch >= '0') && (ch <= '9'))
423                 return ch - '0';
424         if ((ch >= 'a') && (ch <= 'f'))
425                 return ch - 'a' + 10;
426         if ((ch >= 'A') && (ch <= 'F'))
427                 return ch - 'A' + 10;
428         return -1;
429 }
430
431 /*
432  * While we find nice hex chars, build a long_val.
433  * Return number of chars processed.
434  */
435 static int hex2long(char *ptr, unsigned long *long_val)
436 {
437         const char *p = ptr;
438         *long_val = 0;
439
440         while (*p) {
441                 const int hex_val = hex(*p);
442
443                 if (hex_val < 0)
444                         break;
445
446                 *long_val = (*long_val << 4) | hex_val;
447                 p++;
448         }
449
450         return p - ptr;
451 }
452
453 static int load_kallsyms(void)
454 {
455         struct rb_node *nd, *prevnd;
456         char *line = NULL;
457         FILE *file;
458         size_t n;
459
460         kernel_dso = dso__new("[kernel]");
461         if (kernel_dso == NULL)
462                 return -1;
463
464         file = fopen("/proc/kallsyms", "r");
465         if (file == NULL)
466                 goto out_delete_dso;
467
468         while (!feof(file)) {
469                 unsigned long start;
470                 struct symbol *sym;
471                 int line_len, len;
472                 char symbol_type;
473
474                 line_len = getline(&line, &n, file);
475                 if (line_len < 0)
476                         break;
477
478                 if (!line)
479                         goto out_delete_dso;
480
481                 line[--line_len] = '\0'; /* \n */
482
483                 len = hex2long(line, &start);
484
485                 len++;
486                 if (len + 2 >= line_len)
487                         continue;
488
489                 symbol_type = toupper(line[len]);
490                 /*
491                  * We're interested only in code ('T'ext)
492                  */
493                 if (symbol_type != 'T' && symbol_type != 'W')
494                         continue;
495                 /*
496                  * Well fix up the end later, when we have all sorted.
497                  */
498                 sym = symbol__new(start, 0xdead, line + len + 2);
499
500                 if (sym == NULL)
501                         goto out_delete_dso;
502
503                 dso__insert_symbol(kernel_dso, sym);
504         }
505
506         /*
507          * Now that we have all sorted out, just set the ->end of all
508          * symbols
509          */
510         prevnd = rb_first(&kernel_dso->syms);
511
512         if (prevnd == NULL)
513                 goto out_delete_line;
514
515         for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
516                 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
517                               *curr = rb_entry(nd, struct symbol, rb_node);
518
519                 prev->end = curr->start - 1;
520                 prevnd = nd;
521         }
522
523         dsos__add(kernel_dso);
524         free(line);
525         fclose(file);
526
527         return 0;
528
529 out_delete_line:
530         free(line);
531 out_delete_dso:
532         dso__delete(kernel_dso);
533         return -1;
534 }
535
536 static int load_kernel(void)
537 {
538         int fd, nr;
539
540         if (!vmlinux)
541                 goto kallsyms;
542
543         fd = open(vmlinux, O_RDONLY);
544         if (fd < 0)
545                 goto kallsyms;
546
547         kernel_dso = dso__new("[kernel]");
548         if (!kernel_dso)
549                 goto fail_open;
550
551         nr = dso__load_sym(kernel_dso, fd, vmlinux);
552
553         if (nr <= 0)
554                 goto fail_load;
555
556         dsos__add(kernel_dso);
557         close(fd);
558
559         return 0;
560
561 fail_load:
562         dso__delete(kernel_dso);
563 fail_open:
564         close(fd);
565 kallsyms:
566         return load_kallsyms();
567 }
568
569 struct map {
570         struct list_head node;
571         uint64_t         start;
572         uint64_t         end;
573         uint64_t         pgoff;
574         struct dso       *dso;
575 };
576
577 static struct map *map__new(struct mmap_event *event)
578 {
579         struct map *self = malloc(sizeof(*self));
580
581         if (self != NULL) {
582                 self->start = event->start;
583                 self->end   = event->start + event->len;
584                 self->pgoff = event->pgoff;
585
586                 self->dso = dsos__findnew(event->filename);
587                 if (self->dso == NULL)
588                         goto out_delete;
589         }
590         return self;
591 out_delete:
592         free(self);
593         return NULL;
594 }
595
596 struct thread;
597
598 static const char *thread__name(struct thread *self, char *bf, size_t size);
599
600 struct thread {
601         struct rb_node   rb_node;
602         struct list_head maps;
603         pid_t            pid;
604         char             *comm;
605 };
606
607 static const char *thread__name(struct thread *self, char *bf, size_t size)
608 {
609         if (self->comm)
610                 return self->comm;
611
612         snprintf(bf, sizeof(bf), ":%u", self->pid);
613         return bf;
614 }
615
616 static struct thread *thread__new(pid_t pid)
617 {
618         struct thread *self = malloc(sizeof(*self));
619
620         if (self != NULL) {
621                 self->pid = pid;
622                 self->comm = NULL;
623                 INIT_LIST_HEAD(&self->maps);
624         }
625
626         return self;
627 }
628
629 static int thread__set_comm(struct thread *self, const char *comm)
630 {
631         self->comm = strdup(comm);
632         return self->comm ? 0 : -ENOMEM;
633 }
634
635 static struct rb_root threads;
636
637 static struct thread *threads__findnew(pid_t pid)
638 {
639         struct rb_node **p = &threads.rb_node;
640         struct rb_node *parent = NULL;
641         struct thread *th;
642
643         while (*p != NULL) {
644                 parent = *p;
645                 th = rb_entry(parent, struct thread, rb_node);
646
647                 if (th->pid == pid)
648                         return th;
649
650                 if (pid < th->pid)
651                         p = &(*p)->rb_left;
652                 else
653                         p = &(*p)->rb_right;
654         }
655
656         th = thread__new(pid);
657         if (th != NULL) {
658                 rb_link_node(&th->rb_node, parent, p);
659                 rb_insert_color(&th->rb_node, &threads);
660         }
661         return th;
662 }
663
664 static void thread__insert_map(struct thread *self, struct map *map)
665 {
666         list_add_tail(&map->node, &self->maps);
667 }
668
669 static struct map *thread__find_map(struct thread *self, uint64_t ip)
670 {
671         struct map *pos;
672
673         if (self == NULL)
674                 return NULL;
675
676         list_for_each_entry(pos, &self->maps, node)
677                 if (ip >= pos->start && ip <= pos->end)
678                         return pos;
679
680         return NULL;
681 }
682
683 /*
684  * histogram, sorted on item, collects counts
685  */
686
687 static struct rb_root hist;
688
689 struct hist_entry {
690         struct rb_node   rb_node;
691
692         struct thread    *thread;
693         struct map       *map;
694         struct dso       *dso;
695         struct symbol    *sym;
696         uint64_t         ip;
697         char             level;
698
699         uint32_t         count;
700 };
701
702 /*
703  * configurable sorting bits
704  */
705
706 struct sort_entry {
707         struct list_head list;
708
709         int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
710         size_t  (*print)(FILE *fp, struct hist_entry *);
711 };
712
713 static int64_t
714 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
715 {
716         return right->thread->pid - left->thread->pid;
717 }
718
719 static size_t
720 sort__thread_print(FILE *fp, struct hist_entry *self)
721 {
722         char bf[32];
723
724         return fprintf(fp, "%14s ",
725                         thread__name(self->thread, bf, sizeof(bf)));
726 }
727
728 static struct sort_entry sort_thread = {
729         .cmp    = sort__thread_cmp,
730         .print  = sort__thread_print,
731 };
732
733 static int64_t
734 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
735 {
736         uint64_t ip_l, ip_r;
737
738         if (left->sym == right->sym)
739                 return 0;
740
741         ip_l = left->sym ? left->sym->start : left->ip;
742         ip_r = right->sym ? right->sym->start : right->ip;
743
744         return (int64_t)(ip_r - ip_l);
745 }
746
747 static size_t
748 sort__sym_print(FILE *fp, struct hist_entry *self)
749 {
750         size_t ret = 0;
751
752         ret += fprintf(fp, "[%c] ", self->level);
753
754         if (verbose)
755                 ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
756
757         if (self->level != '.')
758                 ret += fprintf(fp, "%s ",
759                                self->sym ? self->sym->name : "<unknown>");
760         else
761                 ret += fprintf(fp, "%s: %s ",
762                                self->dso ? self->dso->name : "<unknown>",
763                                self->sym ? self->sym->name : "<unknown>");
764
765         return ret;
766 }
767
768 static struct sort_entry sort_sym = {
769         .cmp    = sort__sym_cmp,
770         .print  = sort__sym_print,
771 };
772
773 static LIST_HEAD(hist_entry__sort_list);
774
775 static void setup_sorting(void)
776 {
777         list_add_tail(&sort_thread.list, &hist_entry__sort_list);
778         list_add_tail(&sort_sym.list, &hist_entry__sort_list);
779 }
780
781 static int64_t
782 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
783 {
784         struct sort_entry *se;
785         int64_t cmp = 0;
786
787         list_for_each_entry(se, &hist_entry__sort_list, list) {
788                 cmp = se->cmp(left, right);
789                 if (cmp)
790                         break;
791         }
792
793         return cmp;
794 }
795
796 static size_t
797 hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
798 {
799         struct sort_entry *se;
800         size_t ret;
801
802         if (total_samples) {
803                 ret = fprintf(fp, "%5.2f%% ",
804                                 (self->count * 100.0) / total_samples);
805         } else
806                 ret = fprintf(fp, "%12d ", self->count);
807
808         list_for_each_entry(se, &hist_entry__sort_list, list)
809                 ret += se->print(fp, self);
810
811         ret += fprintf(fp, "\n");
812
813         return ret;
814 }
815
816 /*
817  * collect histogram counts
818  */
819
820 static int
821 hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
822                 struct symbol *sym, uint64_t ip, char level)
823 {
824         struct rb_node **p = &hist.rb_node;
825         struct rb_node *parent = NULL;
826         struct hist_entry *he;
827         struct hist_entry entry = {
828                 .thread = thread,
829                 .map    = map,
830                 .dso    = dso,
831                 .sym    = sym,
832                 .ip     = ip,
833                 .level  = level,
834                 .count  = 1,
835         };
836         int cmp;
837
838         while (*p != NULL) {
839                 parent = *p;
840                 he = rb_entry(parent, struct hist_entry, rb_node);
841
842                 cmp = hist_entry__cmp(&entry, he);
843
844                 if (!cmp) {
845                         he->count++;
846                         return 0;
847                 }
848
849                 if (cmp < 0)
850                         p = &(*p)->rb_left;
851                 else
852                         p = &(*p)->rb_right;
853         }
854
855         he = malloc(sizeof(*he));
856         if (!he)
857                 return -ENOMEM;
858         *he = entry;
859         rb_link_node(&he->rb_node, parent, p);
860         rb_insert_color(&he->rb_node, &hist);
861
862         return 0;
863 }
864
865 /*
866  * reverse the map, sort on count.
867  */
868
869 static struct rb_root output_hists;
870
871 static void output__insert_entry(struct hist_entry *he)
872 {
873         struct rb_node **p = &output_hists.rb_node;
874         struct rb_node *parent = NULL;
875         struct hist_entry *iter;
876
877         while (*p != NULL) {
878                 parent = *p;
879                 iter = rb_entry(parent, struct hist_entry, rb_node);
880
881                 if (he->count > iter->count)
882                         p = &(*p)->rb_left;
883                 else
884                         p = &(*p)->rb_right;
885         }
886
887         rb_link_node(&he->rb_node, parent, p);
888         rb_insert_color(&he->rb_node, &output_hists);
889 }
890
891 static void output__resort(void)
892 {
893         struct rb_node *next = rb_first(&hist);
894         struct hist_entry *n;
895
896         while (next) {
897                 n = rb_entry(next, struct hist_entry, rb_node);
898                 next = rb_next(&n->rb_node);
899
900                 rb_erase(&n->rb_node, &hist);
901                 output__insert_entry(n);
902         }
903 }
904
905 static size_t output__fprintf(FILE *fp, uint64_t total_samples)
906 {
907         struct hist_entry *pos;
908         struct rb_node *nd;
909         size_t ret = 0;
910
911         for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
912                 pos = rb_entry(nd, struct hist_entry, rb_node);
913                 ret += hist_entry__fprintf(fp, pos, total_samples);
914         }
915
916         return ret;
917 }
918
919
920 static int __cmd_report(void)
921 {
922         unsigned long offset = 0;
923         unsigned long head = 0;
924         struct stat stat;
925         char *buf;
926         event_t *event;
927         int ret, rc = EXIT_FAILURE;
928         uint32_t size;
929         unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0;
930
931         input = open(input_name, O_RDONLY);
932         if (input < 0) {
933                 perror("failed to open file");
934                 exit(-1);
935         }
936
937         ret = fstat(input, &stat);
938         if (ret < 0) {
939                 perror("failed to stat file");
940                 exit(-1);
941         }
942
943         if (!stat.st_size) {
944                 fprintf(stderr, "zero-sized file, nothing to do!\n");
945                 exit(0);
946         }
947
948         if (load_kernel() < 0) {
949                 perror("failed to open kallsyms");
950                 return EXIT_FAILURE;
951         }
952
953 remap:
954         buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
955                            MAP_SHARED, input, offset);
956         if (buf == MAP_FAILED) {
957                 perror("failed to mmap file");
958                 exit(-1);
959         }
960
961 more:
962         event = (event_t *)(buf + head);
963
964         size = event->header.size;
965         if (!size)
966                 size = 8;
967
968         if (head + event->header.size >= page_size * mmap_window) {
969                 unsigned long shift = page_size * (head / page_size);
970                 int ret;
971
972                 ret = munmap(buf, page_size * mmap_window);
973                 assert(ret == 0);
974
975                 offset += shift;
976                 head -= shift;
977                 goto remap;
978         }
979
980         size = event->header.size;
981         if (!size)
982                 goto broken_event;
983
984         if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
985                 char level;
986                 int show = 0;
987                 struct dso *dso = NULL;
988                 struct thread *thread = threads__findnew(event->ip.pid);
989                 uint64_t ip = event->ip.ip;
990                 struct map *map = NULL;
991
992                 if (dump_trace) {
993                         fprintf(stderr, "%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
994                                 (void *)(offset + head),
995                                 (void *)(long)(event->header.size),
996                                 event->header.misc,
997                                 event->ip.pid,
998                                 (void *)(long)ip);
999                 }
1000
1001                 if (thread == NULL) {
1002                         fprintf(stderr, "problem processing %d event, bailing out\n",
1003                                 event->header.type);
1004                         goto done;
1005                 }
1006
1007                 if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
1008                         show = SHOW_KERNEL;
1009                         level = 'k';
1010
1011                         dso = kernel_dso;
1012
1013                 } else if (event->header.misc & PERF_EVENT_MISC_USER) {
1014
1015                         show = SHOW_USER;
1016                         level = '.';
1017
1018                         map = thread__find_map(thread, ip);
1019                         if (map != NULL) {
1020                                 dso = map->dso;
1021                                 ip -= map->start + map->pgoff;
1022                         }
1023
1024                 } else {
1025                         show = SHOW_HV;
1026                         level = 'H';
1027                 }
1028
1029                 if (show & show_mask) {
1030                         struct symbol *sym = dso__find_symbol(dso, ip);
1031
1032                         if (hist_entry__add(thread, map, dso, sym, ip, level)) {
1033                                 fprintf(stderr,
1034                 "problem incrementing symbol count, bailing out\n");
1035                                 goto done;
1036                         }
1037                 }
1038                 total++;
1039         } else switch (event->header.type) {
1040         case PERF_EVENT_MMAP: {
1041                 struct thread *thread = threads__findnew(event->mmap.pid);
1042                 struct map *map = map__new(&event->mmap);
1043
1044                 if (dump_trace) {
1045                         fprintf(stderr, "%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
1046                                 (void *)(offset + head),
1047                                 (void *)(long)(event->header.size),
1048                                 (void *)(long)event->mmap.start,
1049                                 (void *)(long)event->mmap.len,
1050                                 (void *)(long)event->mmap.pgoff,
1051                                 event->mmap.filename);
1052                 }
1053                 if (thread == NULL || map == NULL) {
1054                         fprintf(stderr, "problem processing PERF_EVENT_MMAP, bailing out\n");
1055                         goto done;
1056                 }
1057                 thread__insert_map(thread, map);
1058                 total_mmap++;
1059                 break;
1060         }
1061         case PERF_EVENT_COMM: {
1062                 struct thread *thread = threads__findnew(event->comm.pid);
1063
1064                 if (dump_trace) {
1065                         fprintf(stderr, "%p [%p]: PERF_EVENT_COMM: %s:%d\n",
1066                                 (void *)(offset + head),
1067                                 (void *)(long)(event->header.size),
1068                                 event->comm.comm, event->comm.pid);
1069                 }
1070                 if (thread == NULL ||
1071                     thread__set_comm(thread, event->comm.comm)) {
1072                         fprintf(stderr, "problem processing PERF_EVENT_COMM, bailing out\n");
1073                         goto done;
1074                 }
1075                 total_comm++;
1076                 break;
1077         }
1078         default: {
1079 broken_event:
1080                 if (dump_trace)
1081                         fprintf(stderr, "%p [%p]: skipping unknown header type: %d\n",
1082                                         (void *)(offset + head),
1083                                         (void *)(long)(event->header.size),
1084                                         event->header.type);
1085
1086                 total_unknown++;
1087
1088                 /*
1089                  * assume we lost track of the stream, check alignment, and
1090                  * increment a single u64 in the hope to catch on again 'soon'.
1091                  */
1092
1093                 if (unlikely(head & 7))
1094                         head &= ~7ULL;
1095
1096                 size = 8;
1097         }
1098         }
1099
1100         head += size;
1101
1102         if (offset + head < stat.st_size)
1103                 goto more;
1104
1105         rc = EXIT_SUCCESS;
1106 done:
1107         close(input);
1108
1109         if (dump_trace) {
1110                 fprintf(stderr, "      IP events: %10ld\n", total);
1111                 fprintf(stderr, "    mmap events: %10ld\n", total_mmap);
1112                 fprintf(stderr, "    comm events: %10ld\n", total_comm);
1113                 fprintf(stderr, " unknown events: %10ld\n", total_unknown);
1114
1115                 return 0;
1116         }
1117
1118         if (verbose >= 2)
1119                 dsos__fprintf(stdout);
1120
1121         output__resort();
1122         output__fprintf(stdout, total);
1123
1124         return rc;
1125 }
1126
1127 static const char * const report_usage[] = {
1128         "perf report [<options>] <command>",
1129         NULL
1130 };
1131
1132 static const struct option options[] = {
1133         OPT_STRING('i', "input", &input_name, "file",
1134                     "input file name"),
1135         OPT_BOOLEAN('v', "verbose", &verbose,
1136                     "be more verbose (show symbol address, etc)"),
1137         OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1138                     "dump raw trace in ASCII"),
1139         OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1140         OPT_END()
1141 };
1142
1143 int cmd_report(int argc, const char **argv, const char *prefix)
1144 {
1145         elf_version(EV_CURRENT);
1146
1147         page_size = getpagesize();
1148
1149         parse_options(argc, argv, options, report_usage, 0);
1150
1151         setup_sorting();
1152
1153         setup_pager();
1154
1155         return __cmd_report();
1156 }