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