perf tools: Save partial non-overlapping map
[safe/jmp/linux-2.6] / tools / perf / 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 <linux/list.h>
14 #include "util/cache.h"
15 #include <linux/rbtree.h>
16 #include "util/symbol.h"
17 #include "util/string.h"
18 #include "util/callchain.h"
19 #include "util/strlist.h"
20 #include "util/values.h"
21
22 #include "perf.h"
23 #include "util/debug.h"
24 #include "util/header.h"
25
26 #include "util/parse-options.h"
27 #include "util/parse-events.h"
28
29 #include "util/thread.h"
30
31 static char             const *input_name = "perf.data";
32
33 static char             default_sort_order[] = "comm,dso,symbol";
34 static char             *sort_order = default_sort_order;
35 static char             *dso_list_str, *comm_list_str, *sym_list_str,
36                         *col_width_list_str;
37 static struct strlist   *dso_list, *comm_list, *sym_list;
38 static char             *field_sep;
39
40 static int              input;
41 static int              show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
42
43 static int              full_paths;
44 static int              show_nr_samples;
45
46 static int              show_threads;
47 static struct perf_read_values  show_threads_values;
48
49 static char             default_pretty_printing_style[] = "normal";
50 static char             *pretty_printing_style = default_pretty_printing_style;
51
52 static unsigned long    page_size;
53 static unsigned long    mmap_window = 32;
54
55 static char             default_parent_pattern[] = "^sys_|^do_page_fault";
56 static char             *parent_pattern = default_parent_pattern;
57 static regex_t          parent_regex;
58
59 static int              exclude_other = 1;
60
61 static char             callchain_default_opt[] = "fractal,0.5";
62
63 static int              callchain;
64
65 static char             __cwd[PATH_MAX];
66 static char             *cwd = __cwd;
67 static int              cwdlen;
68
69 static struct rb_root   threads;
70 static struct thread    *last_match;
71
72 static struct perf_header *header;
73
74 static
75 struct callchain_param  callchain_param = {
76         .mode   = CHAIN_GRAPH_REL,
77         .min_percent = 0.5
78 };
79
80 static u64              sample_type;
81
82 static int repsep_fprintf(FILE *fp, const char *fmt, ...)
83 {
84         int n;
85         va_list ap;
86
87         va_start(ap, fmt);
88         if (!field_sep)
89                 n = vfprintf(fp, fmt, ap);
90         else {
91                 char *bf = NULL;
92                 n = vasprintf(&bf, fmt, ap);
93                 if (n > 0) {
94                         char *sep = bf;
95
96                         while (1) {
97                                 sep = strchr(sep, *field_sep);
98                                 if (sep == NULL)
99                                         break;
100                                 *sep = '.';
101                         }
102                 }
103                 fputs(bf, fp);
104                 free(bf);
105         }
106         va_end(ap);
107         return n;
108 }
109
110 static unsigned int dsos__col_width,
111                     comms__col_width,
112                     threads__col_width;
113
114 /*
115  * histogram, sorted on item, collects counts
116  */
117
118 static struct rb_root hist;
119
120 struct hist_entry {
121         struct rb_node          rb_node;
122
123         struct thread           *thread;
124         struct map              *map;
125         struct dso              *dso;
126         struct symbol           *sym;
127         struct symbol           *parent;
128         u64                     ip;
129         char                    level;
130         struct callchain_node   callchain;
131         struct rb_root          sorted_chain;
132
133         u64                     count;
134 };
135
136 /*
137  * configurable sorting bits
138  */
139
140 struct sort_entry {
141         struct list_head list;
142
143         const char *header;
144
145         int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
146         int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
147         size_t  (*print)(FILE *fp, struct hist_entry *, unsigned int width);
148         unsigned int *width;
149         bool    elide;
150 };
151
152 static int64_t cmp_null(void *l, void *r)
153 {
154         if (!l && !r)
155                 return 0;
156         else if (!l)
157                 return -1;
158         else
159                 return 1;
160 }
161
162 /* --sort pid */
163
164 static int64_t
165 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
166 {
167         return right->thread->pid - left->thread->pid;
168 }
169
170 static size_t
171 sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
172 {
173         return repsep_fprintf(fp, "%*s:%5d", width - 6,
174                               self->thread->comm ?: "", self->thread->pid);
175 }
176
177 static struct sort_entry sort_thread = {
178         .header = "Command:  Pid",
179         .cmp    = sort__thread_cmp,
180         .print  = sort__thread_print,
181         .width  = &threads__col_width,
182 };
183
184 /* --sort comm */
185
186 static int64_t
187 sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
188 {
189         return right->thread->pid - left->thread->pid;
190 }
191
192 static int64_t
193 sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
194 {
195         char *comm_l = left->thread->comm;
196         char *comm_r = right->thread->comm;
197
198         if (!comm_l || !comm_r)
199                 return cmp_null(comm_l, comm_r);
200
201         return strcmp(comm_l, comm_r);
202 }
203
204 static size_t
205 sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
206 {
207         return repsep_fprintf(fp, "%*s", width, self->thread->comm);
208 }
209
210 static struct sort_entry sort_comm = {
211         .header         = "Command",
212         .cmp            = sort__comm_cmp,
213         .collapse       = sort__comm_collapse,
214         .print          = sort__comm_print,
215         .width          = &comms__col_width,
216 };
217
218 /* --sort dso */
219
220 static int64_t
221 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
222 {
223         struct dso *dso_l = left->dso;
224         struct dso *dso_r = right->dso;
225
226         if (!dso_l || !dso_r)
227                 return cmp_null(dso_l, dso_r);
228
229         return strcmp(dso_l->name, dso_r->name);
230 }
231
232 static size_t
233 sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
234 {
235         if (self->dso)
236                 return repsep_fprintf(fp, "%-*s", width, self->dso->name);
237
238         return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
239 }
240
241 static struct sort_entry sort_dso = {
242         .header = "Shared Object",
243         .cmp    = sort__dso_cmp,
244         .print  = sort__dso_print,
245         .width  = &dsos__col_width,
246 };
247
248 /* --sort symbol */
249
250 static int64_t
251 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
252 {
253         u64 ip_l, ip_r;
254
255         if (left->sym == right->sym)
256                 return 0;
257
258         ip_l = left->sym ? left->sym->start : left->ip;
259         ip_r = right->sym ? right->sym->start : right->ip;
260
261         return (int64_t)(ip_r - ip_l);
262 }
263
264 static size_t
265 sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
266 {
267         size_t ret = 0;
268
269         if (verbose)
270                 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
271                                       dso__symtab_origin(self->dso));
272
273         ret += repsep_fprintf(fp, "[%c] ", self->level);
274         if (self->sym) {
275                 ret += repsep_fprintf(fp, "%s", self->sym->name);
276
277                 if (self->sym->module)
278                         ret += repsep_fprintf(fp, "\t[%s]",
279                                              self->sym->module->name);
280         } else {
281                 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
282         }
283
284         return ret;
285 }
286
287 static struct sort_entry sort_sym = {
288         .header = "Symbol",
289         .cmp    = sort__sym_cmp,
290         .print  = sort__sym_print,
291 };
292
293 /* --sort parent */
294
295 static int64_t
296 sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
297 {
298         struct symbol *sym_l = left->parent;
299         struct symbol *sym_r = right->parent;
300
301         if (!sym_l || !sym_r)
302                 return cmp_null(sym_l, sym_r);
303
304         return strcmp(sym_l->name, sym_r->name);
305 }
306
307 static size_t
308 sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
309 {
310         return repsep_fprintf(fp, "%-*s", width,
311                               self->parent ? self->parent->name : "[other]");
312 }
313
314 static unsigned int parent_symbol__col_width;
315
316 static struct sort_entry sort_parent = {
317         .header = "Parent symbol",
318         .cmp    = sort__parent_cmp,
319         .print  = sort__parent_print,
320         .width  = &parent_symbol__col_width,
321 };
322
323 static int sort__need_collapse = 0;
324 static int sort__has_parent = 0;
325
326 struct sort_dimension {
327         const char              *name;
328         struct sort_entry       *entry;
329         int                     taken;
330 };
331
332 static struct sort_dimension sort_dimensions[] = {
333         { .name = "pid",        .entry = &sort_thread,  },
334         { .name = "comm",       .entry = &sort_comm,    },
335         { .name = "dso",        .entry = &sort_dso,     },
336         { .name = "symbol",     .entry = &sort_sym,     },
337         { .name = "parent",     .entry = &sort_parent,  },
338 };
339
340 static LIST_HEAD(hist_entry__sort_list);
341
342 static int sort_dimension__add(const char *tok)
343 {
344         unsigned int i;
345
346         for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
347                 struct sort_dimension *sd = &sort_dimensions[i];
348
349                 if (sd->taken)
350                         continue;
351
352                 if (strncasecmp(tok, sd->name, strlen(tok)))
353                         continue;
354
355                 if (sd->entry->collapse)
356                         sort__need_collapse = 1;
357
358                 if (sd->entry == &sort_parent) {
359                         int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
360                         if (ret) {
361                                 char err[BUFSIZ];
362
363                                 regerror(ret, &parent_regex, err, sizeof(err));
364                                 fprintf(stderr, "Invalid regex: %s\n%s",
365                                         parent_pattern, err);
366                                 exit(-1);
367                         }
368                         sort__has_parent = 1;
369                 }
370
371                 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
372                 sd->taken = 1;
373
374                 return 0;
375         }
376
377         return -ESRCH;
378 }
379
380 static int64_t
381 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
382 {
383         struct sort_entry *se;
384         int64_t cmp = 0;
385
386         list_for_each_entry(se, &hist_entry__sort_list, list) {
387                 cmp = se->cmp(left, right);
388                 if (cmp)
389                         break;
390         }
391
392         return cmp;
393 }
394
395 static int64_t
396 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
397 {
398         struct sort_entry *se;
399         int64_t cmp = 0;
400
401         list_for_each_entry(se, &hist_entry__sort_list, list) {
402                 int64_t (*f)(struct hist_entry *, struct hist_entry *);
403
404                 f = se->collapse ?: se->cmp;
405
406                 cmp = f(left, right);
407                 if (cmp)
408                         break;
409         }
410
411         return cmp;
412 }
413
414 static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
415 {
416         int i;
417         size_t ret = 0;
418
419         ret += fprintf(fp, "%s", "                ");
420
421         for (i = 0; i < depth; i++)
422                 if (depth_mask & (1 << i))
423                         ret += fprintf(fp, "|          ");
424                 else
425                         ret += fprintf(fp, "           ");
426
427         ret += fprintf(fp, "\n");
428
429         return ret;
430 }
431 static size_t
432 ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
433                        int depth_mask, int count, u64 total_samples,
434                        int hits)
435 {
436         int i;
437         size_t ret = 0;
438
439         ret += fprintf(fp, "%s", "                ");
440         for (i = 0; i < depth; i++) {
441                 if (depth_mask & (1 << i))
442                         ret += fprintf(fp, "|");
443                 else
444                         ret += fprintf(fp, " ");
445                 if (!count && i == depth - 1) {
446                         double percent;
447
448                         percent = hits * 100.0 / total_samples;
449                         ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
450                 } else
451                         ret += fprintf(fp, "%s", "          ");
452         }
453         if (chain->sym)
454                 ret += fprintf(fp, "%s\n", chain->sym->name);
455         else
456                 ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
457
458         return ret;
459 }
460
461 static struct symbol *rem_sq_bracket;
462 static struct callchain_list rem_hits;
463
464 static void init_rem_hits(void)
465 {
466         rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
467         if (!rem_sq_bracket) {
468                 fprintf(stderr, "Not enough memory to display remaining hits\n");
469                 return;
470         }
471
472         strcpy(rem_sq_bracket->name, "[...]");
473         rem_hits.sym = rem_sq_bracket;
474 }
475
476 static size_t
477 callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
478                         u64 total_samples, int depth, int depth_mask)
479 {
480         struct rb_node *node, *next;
481         struct callchain_node *child;
482         struct callchain_list *chain;
483         int new_depth_mask = depth_mask;
484         u64 new_total;
485         u64 remaining;
486         size_t ret = 0;
487         int i;
488
489         if (callchain_param.mode == CHAIN_GRAPH_REL)
490                 new_total = self->children_hit;
491         else
492                 new_total = total_samples;
493
494         remaining = new_total;
495
496         node = rb_first(&self->rb_root);
497         while (node) {
498                 u64 cumul;
499
500                 child = rb_entry(node, struct callchain_node, rb_node);
501                 cumul = cumul_hits(child);
502                 remaining -= cumul;
503
504                 /*
505                  * The depth mask manages the output of pipes that show
506                  * the depth. We don't want to keep the pipes of the current
507                  * level for the last child of this depth.
508                  * Except if we have remaining filtered hits. They will
509                  * supersede the last child
510                  */
511                 next = rb_next(node);
512                 if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
513                         new_depth_mask &= ~(1 << (depth - 1));
514
515                 /*
516                  * But we keep the older depth mask for the line seperator
517                  * to keep the level link until we reach the last child
518                  */
519                 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask);
520                 i = 0;
521                 list_for_each_entry(chain, &child->val, list) {
522                         if (chain->ip >= PERF_CONTEXT_MAX)
523                                 continue;
524                         ret += ipchain__fprintf_graph(fp, chain, depth,
525                                                       new_depth_mask, i++,
526                                                       new_total,
527                                                       cumul);
528                 }
529                 ret += callchain__fprintf_graph(fp, child, new_total,
530                                                 depth + 1,
531                                                 new_depth_mask | (1 << depth));
532                 node = next;
533         }
534
535         if (callchain_param.mode == CHAIN_GRAPH_REL &&
536                 remaining && remaining != new_total) {
537
538                 if (!rem_sq_bracket)
539                         return ret;
540
541                 new_depth_mask &= ~(1 << (depth - 1));
542
543                 ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
544                                               new_depth_mask, 0, new_total,
545                                               remaining);
546         }
547
548         return ret;
549 }
550
551 static size_t
552 callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
553                         u64 total_samples)
554 {
555         struct callchain_list *chain;
556         size_t ret = 0;
557
558         if (!self)
559                 return 0;
560
561         ret += callchain__fprintf_flat(fp, self->parent, total_samples);
562
563
564         list_for_each_entry(chain, &self->val, list) {
565                 if (chain->ip >= PERF_CONTEXT_MAX)
566                         continue;
567                 if (chain->sym)
568                         ret += fprintf(fp, "                %s\n", chain->sym->name);
569                 else
570                         ret += fprintf(fp, "                %p\n",
571                                         (void *)(long)chain->ip);
572         }
573
574         return ret;
575 }
576
577 static size_t
578 hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
579                               u64 total_samples)
580 {
581         struct rb_node *rb_node;
582         struct callchain_node *chain;
583         size_t ret = 0;
584
585         rb_node = rb_first(&self->sorted_chain);
586         while (rb_node) {
587                 double percent;
588
589                 chain = rb_entry(rb_node, struct callchain_node, rb_node);
590                 percent = chain->hit * 100.0 / total_samples;
591                 switch (callchain_param.mode) {
592                 case CHAIN_FLAT:
593                         ret += percent_color_fprintf(fp, "           %6.2f%%\n",
594                                                      percent);
595                         ret += callchain__fprintf_flat(fp, chain, total_samples);
596                         break;
597                 case CHAIN_GRAPH_ABS: /* Falldown */
598                 case CHAIN_GRAPH_REL:
599                         ret += callchain__fprintf_graph(fp, chain,
600                                                         total_samples, 1, 1);
601                 case CHAIN_NONE:
602                 default:
603                         break;
604                 }
605                 ret += fprintf(fp, "\n");
606                 rb_node = rb_next(rb_node);
607         }
608
609         return ret;
610 }
611
612
613 static size_t
614 hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
615 {
616         struct sort_entry *se;
617         size_t ret;
618
619         if (exclude_other && !self->parent)
620                 return 0;
621
622         if (total_samples)
623                 ret = percent_color_fprintf(fp,
624                                             field_sep ? "%.2f" : "   %6.2f%%",
625                                         (self->count * 100.0) / total_samples);
626         else
627                 ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
628
629         if (show_nr_samples) {
630                 if (field_sep)
631                         fprintf(fp, "%c%lld", *field_sep, self->count);
632                 else
633                         fprintf(fp, "%11lld", self->count);
634         }
635
636         list_for_each_entry(se, &hist_entry__sort_list, list) {
637                 if (se->elide)
638                         continue;
639
640                 fprintf(fp, "%s", field_sep ?: "  ");
641                 ret += se->print(fp, self, se->width ? *se->width : 0);
642         }
643
644         ret += fprintf(fp, "\n");
645
646         if (callchain)
647                 hist_entry_callchain__fprintf(fp, self, total_samples);
648
649         return ret;
650 }
651
652 /*
653  *
654  */
655
656 static void dso__calc_col_width(struct dso *self)
657 {
658         if (!col_width_list_str && !field_sep &&
659             (!dso_list || strlist__has_entry(dso_list, self->name))) {
660                 unsigned int slen = strlen(self->name);
661                 if (slen > dsos__col_width)
662                         dsos__col_width = slen;
663         }
664
665         self->slen_calculated = 1;
666 }
667
668 static int thread__set_comm_adjust(struct thread *self, const char *comm)
669 {
670         int ret = thread__set_comm(self, comm);
671
672         if (ret)
673                 return ret;
674
675         if (!col_width_list_str && !field_sep &&
676             (!comm_list || strlist__has_entry(comm_list, comm))) {
677                 unsigned int slen = strlen(comm);
678
679                 if (slen > comms__col_width) {
680                         comms__col_width = slen;
681                         threads__col_width = slen + 6;
682                 }
683         }
684
685         return 0;
686 }
687
688
689 static struct symbol *
690 resolve_symbol(struct thread *thread, struct map **mapp,
691                struct dso **dsop, u64 *ipp)
692 {
693         struct dso *dso = dsop ? *dsop : NULL;
694         struct map *map = mapp ? *mapp : NULL;
695         u64 ip = *ipp;
696
697         if (!thread)
698                 return NULL;
699
700         if (dso)
701                 goto got_dso;
702
703         if (map)
704                 goto got_map;
705
706         map = thread__find_map(thread, ip);
707         if (map != NULL) {
708                 /*
709                  * We have to do this here as we may have a dso
710                  * with no symbol hit that has a name longer than
711                  * the ones with symbols sampled.
712                  */
713                 if (!sort_dso.elide && !map->dso->slen_calculated)
714                         dso__calc_col_width(map->dso);
715
716                 if (mapp)
717                         *mapp = map;
718 got_map:
719                 ip = map->map_ip(map, ip);
720
721                 dso = map->dso;
722         } else {
723                 /*
724                  * If this is outside of all known maps,
725                  * and is a negative address, try to look it
726                  * up in the kernel dso, as it might be a
727                  * vsyscall (which executes in user-mode):
728                  */
729                 if ((long long)ip < 0)
730                 dso = kernel_dso;
731         }
732         dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
733         dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
734         *ipp  = ip;
735
736         if (dsop)
737                 *dsop = dso;
738
739         if (!dso)
740                 return NULL;
741 got_dso:
742         return dso->find_symbol(dso, ip);
743 }
744
745 static int call__match(struct symbol *sym)
746 {
747         if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
748                 return 1;
749
750         return 0;
751 }
752
753 static struct symbol **
754 resolve_callchain(struct thread *thread, struct map *map __used,
755                     struct ip_callchain *chain, struct hist_entry *entry)
756 {
757         u64 context = PERF_CONTEXT_MAX;
758         struct symbol **syms = NULL;
759         unsigned int i;
760
761         if (callchain) {
762                 syms = calloc(chain->nr, sizeof(*syms));
763                 if (!syms) {
764                         fprintf(stderr, "Can't allocate memory for symbols\n");
765                         exit(-1);
766                 }
767         }
768
769         for (i = 0; i < chain->nr; i++) {
770                 u64 ip = chain->ips[i];
771                 struct dso *dso = NULL;
772                 struct symbol *sym;
773
774                 if (ip >= PERF_CONTEXT_MAX) {
775                         context = ip;
776                         continue;
777                 }
778
779                 switch (context) {
780                 case PERF_CONTEXT_HV:
781                         dso = hypervisor_dso;
782                         break;
783                 case PERF_CONTEXT_KERNEL:
784                         dso = kernel_dso;
785                         break;
786                 default:
787                         break;
788                 }
789
790                 sym = resolve_symbol(thread, NULL, &dso, &ip);
791
792                 if (sym) {
793                         if (sort__has_parent && call__match(sym) &&
794                             !entry->parent)
795                                 entry->parent = sym;
796                         if (!callchain)
797                                 break;
798                         syms[i] = sym;
799                 }
800         }
801
802         return syms;
803 }
804
805 /*
806  * collect histogram counts
807  */
808
809 static int
810 hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
811                 struct symbol *sym, u64 ip, struct ip_callchain *chain,
812                 char level, u64 count)
813 {
814         struct rb_node **p = &hist.rb_node;
815         struct rb_node *parent = NULL;
816         struct hist_entry *he;
817         struct symbol **syms = NULL;
818         struct hist_entry entry = {
819                 .thread = thread,
820                 .map    = map,
821                 .dso    = dso,
822                 .sym    = sym,
823                 .ip     = ip,
824                 .level  = level,
825                 .count  = count,
826                 .parent = NULL,
827                 .sorted_chain = RB_ROOT
828         };
829         int cmp;
830
831         if ((sort__has_parent || callchain) && chain)
832                 syms = resolve_callchain(thread, map, chain, &entry);
833
834         while (*p != NULL) {
835                 parent = *p;
836                 he = rb_entry(parent, struct hist_entry, rb_node);
837
838                 cmp = hist_entry__cmp(&entry, he);
839
840                 if (!cmp) {
841                         he->count += count;
842                         if (callchain) {
843                                 append_chain(&he->callchain, chain, syms);
844                                 free(syms);
845                         }
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         if (callchain) {
860                 callchain_init(&he->callchain);
861                 append_chain(&he->callchain, chain, syms);
862                 free(syms);
863         }
864         rb_link_node(&he->rb_node, parent, p);
865         rb_insert_color(&he->rb_node, &hist);
866
867         return 0;
868 }
869
870 static void hist_entry__free(struct hist_entry *he)
871 {
872         free(he);
873 }
874
875 /*
876  * collapse the histogram
877  */
878
879 static struct rb_root collapse_hists;
880
881 static void collapse__insert_entry(struct hist_entry *he)
882 {
883         struct rb_node **p = &collapse_hists.rb_node;
884         struct rb_node *parent = NULL;
885         struct hist_entry *iter;
886         int64_t cmp;
887
888         while (*p != NULL) {
889                 parent = *p;
890                 iter = rb_entry(parent, struct hist_entry, rb_node);
891
892                 cmp = hist_entry__collapse(iter, he);
893
894                 if (!cmp) {
895                         iter->count += he->count;
896                         hist_entry__free(he);
897                         return;
898                 }
899
900                 if (cmp < 0)
901                         p = &(*p)->rb_left;
902                 else
903                         p = &(*p)->rb_right;
904         }
905
906         rb_link_node(&he->rb_node, parent, p);
907         rb_insert_color(&he->rb_node, &collapse_hists);
908 }
909
910 static void collapse__resort(void)
911 {
912         struct rb_node *next;
913         struct hist_entry *n;
914
915         if (!sort__need_collapse)
916                 return;
917
918         next = rb_first(&hist);
919         while (next) {
920                 n = rb_entry(next, struct hist_entry, rb_node);
921                 next = rb_next(&n->rb_node);
922
923                 rb_erase(&n->rb_node, &hist);
924                 collapse__insert_entry(n);
925         }
926 }
927
928 /*
929  * reverse the map, sort on count.
930  */
931
932 static struct rb_root output_hists;
933
934 static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
935 {
936         struct rb_node **p = &output_hists.rb_node;
937         struct rb_node *parent = NULL;
938         struct hist_entry *iter;
939
940         if (callchain)
941                 callchain_param.sort(&he->sorted_chain, &he->callchain,
942                                       min_callchain_hits, &callchain_param);
943
944         while (*p != NULL) {
945                 parent = *p;
946                 iter = rb_entry(parent, struct hist_entry, rb_node);
947
948                 if (he->count > iter->count)
949                         p = &(*p)->rb_left;
950                 else
951                         p = &(*p)->rb_right;
952         }
953
954         rb_link_node(&he->rb_node, parent, p);
955         rb_insert_color(&he->rb_node, &output_hists);
956 }
957
958 static void output__resort(u64 total_samples)
959 {
960         struct rb_node *next;
961         struct hist_entry *n;
962         struct rb_root *tree = &hist;
963         u64 min_callchain_hits;
964
965         min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
966
967         if (sort__need_collapse)
968                 tree = &collapse_hists;
969
970         next = rb_first(tree);
971
972         while (next) {
973                 n = rb_entry(next, struct hist_entry, rb_node);
974                 next = rb_next(&n->rb_node);
975
976                 rb_erase(&n->rb_node, tree);
977                 output__insert_entry(n, min_callchain_hits);
978         }
979 }
980
981 static size_t output__fprintf(FILE *fp, u64 total_samples)
982 {
983         struct hist_entry *pos;
984         struct sort_entry *se;
985         struct rb_node *nd;
986         size_t ret = 0;
987         unsigned int width;
988         char *col_width = col_width_list_str;
989         int raw_printing_style;
990
991         raw_printing_style = !strcmp(pretty_printing_style, "raw");
992
993         init_rem_hits();
994
995         fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
996         fprintf(fp, "#\n");
997
998         fprintf(fp, "# Overhead");
999         if (show_nr_samples) {
1000                 if (field_sep)
1001                         fprintf(fp, "%cSamples", *field_sep);
1002                 else
1003                         fputs("  Samples  ", fp);
1004         }
1005         list_for_each_entry(se, &hist_entry__sort_list, list) {
1006                 if (se->elide)
1007                         continue;
1008                 if (field_sep) {
1009                         fprintf(fp, "%c%s", *field_sep, se->header);
1010                         continue;
1011                 }
1012                 width = strlen(se->header);
1013                 if (se->width) {
1014                         if (col_width_list_str) {
1015                                 if (col_width) {
1016                                         *se->width = atoi(col_width);
1017                                         col_width = strchr(col_width, ',');
1018                                         if (col_width)
1019                                                 ++col_width;
1020                                 }
1021                         }
1022                         width = *se->width = max(*se->width, width);
1023                 }
1024                 fprintf(fp, "  %*s", width, se->header);
1025         }
1026         fprintf(fp, "\n");
1027
1028         if (field_sep)
1029                 goto print_entries;
1030
1031         fprintf(fp, "# ........");
1032         if (show_nr_samples)
1033                 fprintf(fp, " ..........");
1034         list_for_each_entry(se, &hist_entry__sort_list, list) {
1035                 unsigned int i;
1036
1037                 if (se->elide)
1038                         continue;
1039
1040                 fprintf(fp, "  ");
1041                 if (se->width)
1042                         width = *se->width;
1043                 else
1044                         width = strlen(se->header);
1045                 for (i = 0; i < width; i++)
1046                         fprintf(fp, ".");
1047         }
1048         fprintf(fp, "\n");
1049
1050         fprintf(fp, "#\n");
1051
1052 print_entries:
1053         for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
1054                 pos = rb_entry(nd, struct hist_entry, rb_node);
1055                 ret += hist_entry__fprintf(fp, pos, total_samples);
1056         }
1057
1058         if (sort_order == default_sort_order &&
1059                         parent_pattern == default_parent_pattern) {
1060                 fprintf(fp, "#\n");
1061                 fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
1062                 fprintf(fp, "#\n");
1063         }
1064         fprintf(fp, "\n");
1065
1066         free(rem_sq_bracket);
1067
1068         if (show_threads)
1069                 perf_read_values_display(fp, &show_threads_values,
1070                                          raw_printing_style);
1071
1072         return ret;
1073 }
1074
1075 static void register_idle_thread(void)
1076 {
1077         struct thread *thread = threads__findnew(0, &threads, &last_match);
1078
1079         if (thread == NULL ||
1080                         thread__set_comm_adjust(thread, "[idle]")) {
1081                 fprintf(stderr, "problem inserting idle task.\n");
1082                 exit(-1);
1083         }
1084 }
1085
1086 static unsigned long total = 0,
1087                      total_mmap = 0,
1088                      total_comm = 0,
1089                      total_fork = 0,
1090                      total_unknown = 0,
1091                      total_lost = 0;
1092
1093 static int validate_chain(struct ip_callchain *chain, event_t *event)
1094 {
1095         unsigned int chain_size;
1096
1097         chain_size = event->header.size;
1098         chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
1099
1100         if (chain->nr*sizeof(u64) > chain_size)
1101                 return -1;
1102
1103         return 0;
1104 }
1105
1106 static int
1107 process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1108 {
1109         char level;
1110         int show = 0;
1111         struct dso *dso = NULL;
1112         struct thread *thread;
1113         u64 ip = event->ip.ip;
1114         u64 period = 1;
1115         struct map *map = NULL;
1116         void *more_data = event->ip.__more_data;
1117         struct ip_callchain *chain = NULL;
1118         int cpumode;
1119
1120         thread = threads__findnew(event->ip.pid, &threads, &last_match);
1121
1122         if (sample_type & PERF_SAMPLE_PERIOD) {
1123                 period = *(u64 *)more_data;
1124                 more_data += sizeof(u64);
1125         }
1126
1127         dump_printf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
1128                 (void *)(offset + head),
1129                 (void *)(long)(event->header.size),
1130                 event->header.misc,
1131                 event->ip.pid, event->ip.tid,
1132                 (void *)(long)ip,
1133                 (long long)period);
1134
1135         if (sample_type & PERF_SAMPLE_CALLCHAIN) {
1136                 unsigned int i;
1137
1138                 chain = (void *)more_data;
1139
1140                 dump_printf("... chain: nr:%Lu\n", chain->nr);
1141
1142                 if (validate_chain(chain, event) < 0) {
1143                         eprintf("call-chain problem with event, skipping it.\n");
1144                         return 0;
1145                 }
1146
1147                 if (dump_trace) {
1148                         for (i = 0; i < chain->nr; i++)
1149                                 dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]);
1150                 }
1151         }
1152
1153         dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1154
1155         if (thread == NULL) {
1156                 eprintf("problem processing %d event, skipping it.\n",
1157                         event->header.type);
1158                 return -1;
1159         }
1160
1161         if (comm_list && !strlist__has_entry(comm_list, thread->comm))
1162                 return 0;
1163
1164         cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK;
1165
1166         if (cpumode == PERF_EVENT_MISC_KERNEL) {
1167                 show = SHOW_KERNEL;
1168                 level = 'k';
1169
1170                 dso = kernel_dso;
1171
1172                 dump_printf(" ...... dso: %s\n", dso->name);
1173
1174         } else if (cpumode == PERF_EVENT_MISC_USER) {
1175
1176                 show = SHOW_USER;
1177                 level = '.';
1178
1179         } else {
1180                 show = SHOW_HV;
1181                 level = 'H';
1182
1183                 dso = hypervisor_dso;
1184
1185                 dump_printf(" ...... dso: [hypervisor]\n");
1186         }
1187
1188         if (show & show_mask) {
1189                 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
1190
1191                 if (dso_list && (!dso || !dso->name ||
1192                                  !strlist__has_entry(dso_list, dso->name)))
1193                         return 0;
1194
1195                 if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name)))
1196                         return 0;
1197
1198                 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
1199                         eprintf("problem incrementing symbol count, skipping event\n");
1200                         return -1;
1201                 }
1202         }
1203         total += period;
1204
1205         return 0;
1206 }
1207
1208 static int
1209 process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1210 {
1211         struct thread *thread;
1212         struct map *map = map__new(&event->mmap, cwd, cwdlen);
1213
1214         thread = threads__findnew(event->mmap.pid, &threads, &last_match);
1215
1216         dump_printf("%p [%p]: PERF_EVENT_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
1217                 (void *)(offset + head),
1218                 (void *)(long)(event->header.size),
1219                 event->mmap.pid,
1220                 event->mmap.tid,
1221                 (void *)(long)event->mmap.start,
1222                 (void *)(long)event->mmap.len,
1223                 (void *)(long)event->mmap.pgoff,
1224                 event->mmap.filename);
1225
1226         if (thread == NULL || map == NULL) {
1227                 dump_printf("problem processing PERF_EVENT_MMAP, skipping event.\n");
1228                 return 0;
1229         }
1230
1231         thread__insert_map(thread, map);
1232         total_mmap++;
1233
1234         return 0;
1235 }
1236
1237 static int
1238 process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1239 {
1240         struct thread *thread;
1241
1242         thread = threads__findnew(event->comm.pid, &threads, &last_match);
1243
1244         dump_printf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
1245                 (void *)(offset + head),
1246                 (void *)(long)(event->header.size),
1247                 event->comm.comm, event->comm.pid);
1248
1249         if (thread == NULL ||
1250             thread__set_comm_adjust(thread, event->comm.comm)) {
1251                 dump_printf("problem processing PERF_EVENT_COMM, skipping event.\n");
1252                 return -1;
1253         }
1254         total_comm++;
1255
1256         return 0;
1257 }
1258
1259 static int
1260 process_task_event(event_t *event, unsigned long offset, unsigned long head)
1261 {
1262         struct thread *thread;
1263         struct thread *parent;
1264
1265         thread = threads__findnew(event->fork.pid, &threads, &last_match);
1266         parent = threads__findnew(event->fork.ppid, &threads, &last_match);
1267
1268         dump_printf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n",
1269                 (void *)(offset + head),
1270                 (void *)(long)(event->header.size),
1271                 event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT",
1272                 event->fork.pid, event->fork.tid,
1273                 event->fork.ppid, event->fork.ptid);
1274
1275         /*
1276          * A thread clone will have the same PID for both
1277          * parent and child.
1278          */
1279         if (thread == parent)
1280                 return 0;
1281
1282         if (event->header.type == PERF_EVENT_EXIT)
1283                 return 0;
1284
1285         if (!thread || !parent || thread__fork(thread, parent)) {
1286                 dump_printf("problem processing PERF_EVENT_FORK, skipping event.\n");
1287                 return -1;
1288         }
1289         total_fork++;
1290
1291         return 0;
1292 }
1293
1294 static int
1295 process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1296 {
1297         dump_printf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
1298                 (void *)(offset + head),
1299                 (void *)(long)(event->header.size),
1300                 event->lost.id,
1301                 event->lost.lost);
1302
1303         total_lost += event->lost.lost;
1304
1305         return 0;
1306 }
1307
1308 static int
1309 process_read_event(event_t *event, unsigned long offset, unsigned long head)
1310 {
1311         struct perf_counter_attr *attr;
1312
1313         attr = perf_header__find_attr(event->read.id, header);
1314
1315         if (show_threads) {
1316                 const char *name = attr ? __event_name(attr->type, attr->config)
1317                                    : "unknown";
1318                 perf_read_values_add_value(&show_threads_values,
1319                                            event->read.pid, event->read.tid,
1320                                            event->read.id,
1321                                            name,
1322                                            event->read.value);
1323         }
1324
1325         dump_printf("%p [%p]: PERF_EVENT_READ: %d %d %s %Lu\n",
1326                         (void *)(offset + head),
1327                         (void *)(long)(event->header.size),
1328                         event->read.pid,
1329                         event->read.tid,
1330                         attr ? __event_name(attr->type, attr->config)
1331                              : "FAIL",
1332                         event->read.value);
1333
1334         return 0;
1335 }
1336
1337 static int
1338 process_event(event_t *event, unsigned long offset, unsigned long head)
1339 {
1340         trace_event(event);
1341
1342         switch (event->header.type) {
1343         case PERF_EVENT_SAMPLE:
1344                 return process_sample_event(event, offset, head);
1345
1346         case PERF_EVENT_MMAP:
1347                 return process_mmap_event(event, offset, head);
1348
1349         case PERF_EVENT_COMM:
1350                 return process_comm_event(event, offset, head);
1351
1352         case PERF_EVENT_FORK:
1353         case PERF_EVENT_EXIT:
1354                 return process_task_event(event, offset, head);
1355
1356         case PERF_EVENT_LOST:
1357                 return process_lost_event(event, offset, head);
1358
1359         case PERF_EVENT_READ:
1360                 return process_read_event(event, offset, head);
1361
1362         /*
1363          * We dont process them right now but they are fine:
1364          */
1365
1366         case PERF_EVENT_THROTTLE:
1367         case PERF_EVENT_UNTHROTTLE:
1368                 return 0;
1369
1370         default:
1371                 return -1;
1372         }
1373
1374         return 0;
1375 }
1376
1377 static int __cmd_report(void)
1378 {
1379         int ret, rc = EXIT_FAILURE;
1380         unsigned long offset = 0;
1381         unsigned long head, shift;
1382         struct stat input_stat;
1383         event_t *event;
1384         uint32_t size;
1385         char *buf;
1386
1387         register_idle_thread();
1388
1389         if (show_threads)
1390                 perf_read_values_init(&show_threads_values);
1391
1392         input = open(input_name, O_RDONLY);
1393         if (input < 0) {
1394                 fprintf(stderr, " failed to open file: %s", input_name);
1395                 if (!strcmp(input_name, "perf.data"))
1396                         fprintf(stderr, "  (try 'perf record' first)");
1397                 fprintf(stderr, "\n");
1398                 exit(-1);
1399         }
1400
1401         ret = fstat(input, &input_stat);
1402         if (ret < 0) {
1403                 perror("failed to stat file");
1404                 exit(-1);
1405         }
1406
1407         if (!input_stat.st_size) {
1408                 fprintf(stderr, "zero-sized file, nothing to do!\n");
1409                 exit(0);
1410         }
1411
1412         header = perf_header__read(input);
1413         head = header->data_offset;
1414
1415         sample_type = perf_header__sample_type(header);
1416
1417         if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1418                 if (sort__has_parent) {
1419                         fprintf(stderr, "selected --sort parent, but no"
1420                                         " callchain data. Did you call"
1421                                         " perf record without -g?\n");
1422                         exit(-1);
1423                 }
1424                 if (callchain) {
1425                         fprintf(stderr, "selected -c but no callchain data."
1426                                         " Did you call perf record without"
1427                                         " -g?\n");
1428                         exit(-1);
1429                 }
1430         } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
1431                         callchain = 1;
1432                         if (register_callchain_param(&callchain_param) < 0) {
1433                                 fprintf(stderr, "Can't register callchain"
1434                                                 " params\n");
1435                                 exit(-1);
1436                         }
1437         }
1438
1439         if (load_kernel() < 0) {
1440                 perror("failed to load kernel symbols");
1441                 return EXIT_FAILURE;
1442         }
1443
1444         if (!full_paths) {
1445                 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
1446                         perror("failed to get the current directory");
1447                         return EXIT_FAILURE;
1448                 }
1449                 cwdlen = strlen(cwd);
1450         } else {
1451                 cwd = NULL;
1452                 cwdlen = 0;
1453         }
1454
1455         shift = page_size * (head / page_size);
1456         offset += shift;
1457         head -= shift;
1458
1459 remap:
1460         buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1461                            MAP_SHARED, input, offset);
1462         if (buf == MAP_FAILED) {
1463                 perror("failed to mmap file");
1464                 exit(-1);
1465         }
1466
1467 more:
1468         event = (event_t *)(buf + head);
1469
1470         size = event->header.size;
1471         if (!size)
1472                 size = 8;
1473
1474         if (head + event->header.size >= page_size * mmap_window) {
1475                 int munmap_ret;
1476
1477                 shift = page_size * (head / page_size);
1478
1479                 munmap_ret = munmap(buf, page_size * mmap_window);
1480                 assert(munmap_ret == 0);
1481
1482                 offset += shift;
1483                 head -= shift;
1484                 goto remap;
1485         }
1486
1487         size = event->header.size;
1488
1489         dump_printf("\n%p [%p]: event: %d\n",
1490                         (void *)(offset + head),
1491                         (void *)(long)event->header.size,
1492                         event->header.type);
1493
1494         if (!size || process_event(event, offset, head) < 0) {
1495
1496                 dump_printf("%p [%p]: skipping unknown header type: %d\n",
1497                         (void *)(offset + head),
1498                         (void *)(long)(event->header.size),
1499                         event->header.type);
1500
1501                 total_unknown++;
1502
1503                 /*
1504                  * assume we lost track of the stream, check alignment, and
1505                  * increment a single u64 in the hope to catch on again 'soon'.
1506                  */
1507
1508                 if (unlikely(head & 7))
1509                         head &= ~7ULL;
1510
1511                 size = 8;
1512         }
1513
1514         head += size;
1515
1516         if (offset + head >= header->data_offset + header->data_size)
1517                 goto done;
1518
1519         if (offset + head < (unsigned long)input_stat.st_size)
1520                 goto more;
1521
1522 done:
1523         rc = EXIT_SUCCESS;
1524         close(input);
1525
1526         dump_printf("      IP events: %10ld\n", total);
1527         dump_printf("    mmap events: %10ld\n", total_mmap);
1528         dump_printf("    comm events: %10ld\n", total_comm);
1529         dump_printf("    fork events: %10ld\n", total_fork);
1530         dump_printf("    lost events: %10ld\n", total_lost);
1531         dump_printf(" unknown events: %10ld\n", total_unknown);
1532
1533         if (dump_trace)
1534                 return 0;
1535
1536         if (verbose >= 3)
1537                 threads__fprintf(stdout, &threads);
1538
1539         if (verbose >= 2)
1540                 dsos__fprintf(stdout);
1541
1542         collapse__resort();
1543         output__resort(total);
1544         output__fprintf(stdout, total);
1545
1546         if (show_threads)
1547                 perf_read_values_destroy(&show_threads_values);
1548
1549         return rc;
1550 }
1551
1552 static int
1553 parse_callchain_opt(const struct option *opt __used, const char *arg,
1554                     int unset __used)
1555 {
1556         char *tok;
1557         char *endptr;
1558
1559         callchain = 1;
1560
1561         if (!arg)
1562                 return 0;
1563
1564         tok = strtok((char *)arg, ",");
1565         if (!tok)
1566                 return -1;
1567
1568         /* get the output mode */
1569         if (!strncmp(tok, "graph", strlen(arg)))
1570                 callchain_param.mode = CHAIN_GRAPH_ABS;
1571
1572         else if (!strncmp(tok, "flat", strlen(arg)))
1573                 callchain_param.mode = CHAIN_FLAT;
1574
1575         else if (!strncmp(tok, "fractal", strlen(arg)))
1576                 callchain_param.mode = CHAIN_GRAPH_REL;
1577
1578         else if (!strncmp(tok, "none", strlen(arg))) {
1579                 callchain_param.mode = CHAIN_NONE;
1580                 callchain = 0;
1581
1582                 return 0;
1583         }
1584
1585         else
1586                 return -1;
1587
1588         /* get the min percentage */
1589         tok = strtok(NULL, ",");
1590         if (!tok)
1591                 goto setup;
1592
1593         callchain_param.min_percent = strtod(tok, &endptr);
1594         if (tok == endptr)
1595                 return -1;
1596
1597 setup:
1598         if (register_callchain_param(&callchain_param) < 0) {
1599                 fprintf(stderr, "Can't register callchain params\n");
1600                 return -1;
1601         }
1602         return 0;
1603 }
1604
1605 static const char * const report_usage[] = {
1606         "perf report [<options>] <command>",
1607         NULL
1608 };
1609
1610 static const struct option options[] = {
1611         OPT_STRING('i', "input", &input_name, "file",
1612                     "input file name"),
1613         OPT_BOOLEAN('v', "verbose", &verbose,
1614                     "be more verbose (show symbol address, etc)"),
1615         OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1616                     "dump raw trace in ASCII"),
1617         OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
1618         OPT_BOOLEAN('m', "modules", &modules,
1619                     "load module symbols - WARNING: use only with -k and LIVE kernel"),
1620         OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
1621                     "Show a column with the number of samples"),
1622         OPT_BOOLEAN('T', "threads", &show_threads,
1623                     "Show per-thread event counters"),
1624         OPT_STRING(0, "pretty", &pretty_printing_style, "key",
1625                    "pretty printing style key: normal raw"),
1626         OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1627                    "sort by key(s): pid, comm, dso, symbol, parent"),
1628         OPT_BOOLEAN('P', "full-paths", &full_paths,
1629                     "Don't shorten the pathnames taking into account the cwd"),
1630         OPT_STRING('p', "parent", &parent_pattern, "regex",
1631                    "regex filter to identify parent, see: '--sort parent'"),
1632         OPT_BOOLEAN('x', "exclude-other", &exclude_other,
1633                     "Only display entries with parent-match"),
1634         OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
1635                      "Display callchains using output_type and min percent threshold. "
1636                      "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
1637         OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
1638                    "only consider symbols in these dsos"),
1639         OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
1640                    "only consider symbols in these comms"),
1641         OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
1642                    "only consider these symbols"),
1643         OPT_STRING('w', "column-widths", &col_width_list_str,
1644                    "width[,width...]",
1645                    "don't try to adjust column width, use these fixed values"),
1646         OPT_STRING('t', "field-separator", &field_sep, "separator",
1647                    "separator for columns, no spaces will be added between "
1648                    "columns '.' is reserved."),
1649         OPT_END()
1650 };
1651
1652 static void setup_sorting(void)
1653 {
1654         char *tmp, *tok, *str = strdup(sort_order);
1655
1656         for (tok = strtok_r(str, ", ", &tmp);
1657                         tok; tok = strtok_r(NULL, ", ", &tmp)) {
1658                 if (sort_dimension__add(tok) < 0) {
1659                         error("Unknown --sort key: `%s'", tok);
1660                         usage_with_options(report_usage, options);
1661                 }
1662         }
1663
1664         free(str);
1665 }
1666
1667 static void setup_list(struct strlist **list, const char *list_str,
1668                        struct sort_entry *se, const char *list_name,
1669                        FILE *fp)
1670 {
1671         if (list_str) {
1672                 *list = strlist__new(true, list_str);
1673                 if (!*list) {
1674                         fprintf(stderr, "problems parsing %s list\n",
1675                                 list_name);
1676                         exit(129);
1677                 }
1678                 if (strlist__nr_entries(*list) == 1) {
1679                         fprintf(fp, "# %s: %s\n", list_name,
1680                                 strlist__entry(*list, 0)->s);
1681                         se->elide = true;
1682                 }
1683         }
1684 }
1685
1686 int cmd_report(int argc, const char **argv, const char *prefix __used)
1687 {
1688         symbol__init();
1689
1690         page_size = getpagesize();
1691
1692         argc = parse_options(argc, argv, options, report_usage, 0);
1693
1694         setup_sorting();
1695
1696         if (parent_pattern != default_parent_pattern) {
1697                 sort_dimension__add("parent");
1698                 sort_parent.elide = 1;
1699         } else
1700                 exclude_other = 0;
1701
1702         /*
1703          * Any (unrecognized) arguments left?
1704          */
1705         if (argc)
1706                 usage_with_options(report_usage, options);
1707
1708         setup_pager();
1709
1710         setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
1711         setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
1712         setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
1713
1714         if (field_sep && *field_sep == '.') {
1715                 fputs("'.' is the only non valid --field-separator argument\n",
1716                       stderr);
1717                 exit(129);
1718         }
1719
1720         return __cmd_report();
1721 }