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