160df202c34f8ae4e39f8155c750925f27c1f7af
[cascardo/linux.git] / tools / perf / util / sort.c
1 #include <sys/mman.h>
2 #include "sort.h"
3 #include "hist.h"
4 #include "comm.h"
5 #include "symbol.h"
6 #include "evsel.h"
7 #include "evlist.h"
8 #include <traceevent/event-parse.h>
9 #include "mem-events.h"
10
11 regex_t         parent_regex;
12 const char      default_parent_pattern[] = "^sys_|^do_page_fault";
13 const char      *parent_pattern = default_parent_pattern;
14 const char      default_sort_order[] = "comm,dso,symbol";
15 const char      default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles";
16 const char      default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
17 const char      default_top_sort_order[] = "dso,symbol";
18 const char      default_diff_sort_order[] = "dso,symbol";
19 const char      default_tracepoint_sort_order[] = "trace";
20 const char      *sort_order;
21 const char      *field_order;
22 regex_t         ignore_callees_regex;
23 int             have_ignore_callees = 0;
24 int             sort__need_collapse = 0;
25 int             sort__has_parent = 0;
26 int             sort__has_sym = 0;
27 int             sort__has_dso = 0;
28 int             sort__has_socket = 0;
29 int             sort__has_thread = 0;
30 enum sort_mode  sort__mode = SORT_MODE__NORMAL;
31
32 /*
33  * Replaces all occurrences of a char used with the:
34  *
35  * -t, --field-separator
36  *
37  * option, that uses a special separator character and don't pad with spaces,
38  * replacing all occurances of this separator in symbol names (and other
39  * output) with a '.' character, that thus it's the only non valid separator.
40 */
41 static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
42 {
43         int n;
44         va_list ap;
45
46         va_start(ap, fmt);
47         n = vsnprintf(bf, size, fmt, ap);
48         if (symbol_conf.field_sep && n > 0) {
49                 char *sep = bf;
50
51                 while (1) {
52                         sep = strchr(sep, *symbol_conf.field_sep);
53                         if (sep == NULL)
54                                 break;
55                         *sep = '.';
56                 }
57         }
58         va_end(ap);
59
60         if (n >= (int)size)
61                 return size - 1;
62         return n;
63 }
64
65 static int64_t cmp_null(const void *l, const void *r)
66 {
67         if (!l && !r)
68                 return 0;
69         else if (!l)
70                 return -1;
71         else
72                 return 1;
73 }
74
75 /* --sort pid */
76
77 static int64_t
78 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
79 {
80         return right->thread->tid - left->thread->tid;
81 }
82
83 static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
84                                        size_t size, unsigned int width)
85 {
86         const char *comm = thread__comm_str(he->thread);
87
88         width = max(7U, width) - 6;
89         return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
90                                width, width, comm ?: "");
91 }
92
93 struct sort_entry sort_thread = {
94         .se_header      = "  Pid:Command",
95         .se_cmp         = sort__thread_cmp,
96         .se_snprintf    = hist_entry__thread_snprintf,
97         .se_width_idx   = HISTC_THREAD,
98 };
99
100 /* --sort comm */
101
102 static int64_t
103 sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
104 {
105         /* Compare the addr that should be unique among comm */
106         return strcmp(comm__str(right->comm), comm__str(left->comm));
107 }
108
109 static int64_t
110 sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
111 {
112         /* Compare the addr that should be unique among comm */
113         return strcmp(comm__str(right->comm), comm__str(left->comm));
114 }
115
116 static int64_t
117 sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
118 {
119         return strcmp(comm__str(right->comm), comm__str(left->comm));
120 }
121
122 static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
123                                      size_t size, unsigned int width)
124 {
125         return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm));
126 }
127
128 struct sort_entry sort_comm = {
129         .se_header      = "Command",
130         .se_cmp         = sort__comm_cmp,
131         .se_collapse    = sort__comm_collapse,
132         .se_sort        = sort__comm_sort,
133         .se_snprintf    = hist_entry__comm_snprintf,
134         .se_width_idx   = HISTC_COMM,
135 };
136
137 /* --sort dso */
138
139 static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
140 {
141         struct dso *dso_l = map_l ? map_l->dso : NULL;
142         struct dso *dso_r = map_r ? map_r->dso : NULL;
143         const char *dso_name_l, *dso_name_r;
144
145         if (!dso_l || !dso_r)
146                 return cmp_null(dso_r, dso_l);
147
148         if (verbose) {
149                 dso_name_l = dso_l->long_name;
150                 dso_name_r = dso_r->long_name;
151         } else {
152                 dso_name_l = dso_l->short_name;
153                 dso_name_r = dso_r->short_name;
154         }
155
156         return strcmp(dso_name_l, dso_name_r);
157 }
158
159 static int64_t
160 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
161 {
162         return _sort__dso_cmp(right->ms.map, left->ms.map);
163 }
164
165 static int _hist_entry__dso_snprintf(struct map *map, char *bf,
166                                      size_t size, unsigned int width)
167 {
168         if (map && map->dso) {
169                 const char *dso_name = !verbose ? map->dso->short_name :
170                         map->dso->long_name;
171                 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
172         }
173
174         return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]");
175 }
176
177 static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
178                                     size_t size, unsigned int width)
179 {
180         return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
181 }
182
183 struct sort_entry sort_dso = {
184         .se_header      = "Shared Object",
185         .se_cmp         = sort__dso_cmp,
186         .se_snprintf    = hist_entry__dso_snprintf,
187         .se_width_idx   = HISTC_DSO,
188 };
189
190 /* --sort symbol */
191
192 static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
193 {
194         return (int64_t)(right_ip - left_ip);
195 }
196
197 static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
198 {
199         if (!sym_l || !sym_r)
200                 return cmp_null(sym_l, sym_r);
201
202         if (sym_l == sym_r)
203                 return 0;
204
205         if (sym_l->start != sym_r->start)
206                 return (int64_t)(sym_r->start - sym_l->start);
207
208         return (int64_t)(sym_r->end - sym_l->end);
209 }
210
211 static int64_t
212 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
213 {
214         int64_t ret;
215
216         if (!left->ms.sym && !right->ms.sym)
217                 return _sort__addr_cmp(left->ip, right->ip);
218
219         /*
220          * comparing symbol address alone is not enough since it's a
221          * relative address within a dso.
222          */
223         if (!sort__has_dso) {
224                 ret = sort__dso_cmp(left, right);
225                 if (ret != 0)
226                         return ret;
227         }
228
229         return _sort__sym_cmp(left->ms.sym, right->ms.sym);
230 }
231
232 static int64_t
233 sort__sym_sort(struct hist_entry *left, struct hist_entry *right)
234 {
235         if (!left->ms.sym || !right->ms.sym)
236                 return cmp_null(left->ms.sym, right->ms.sym);
237
238         return strcmp(right->ms.sym->name, left->ms.sym->name);
239 }
240
241 static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
242                                      u64 ip, char level, char *bf, size_t size,
243                                      unsigned int width)
244 {
245         size_t ret = 0;
246
247         if (verbose) {
248                 char o = map ? dso__symtab_origin(map->dso) : '!';
249                 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
250                                        BITS_PER_LONG / 4 + 2, ip, o);
251         }
252
253         ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
254         if (sym && map) {
255                 if (map->type == MAP__VARIABLE) {
256                         ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
257                         ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
258                                         ip - map->unmap_ip(map, sym->start));
259                 } else {
260                         ret += repsep_snprintf(bf + ret, size - ret, "%.*s",
261                                                width - ret,
262                                                sym->name);
263                 }
264         } else {
265                 size_t len = BITS_PER_LONG / 4;
266                 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
267                                        len, ip);
268         }
269
270         return ret;
271 }
272
273 static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
274                                     size_t size, unsigned int width)
275 {
276         return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
277                                          he->level, bf, size, width);
278 }
279
280 struct sort_entry sort_sym = {
281         .se_header      = "Symbol",
282         .se_cmp         = sort__sym_cmp,
283         .se_sort        = sort__sym_sort,
284         .se_snprintf    = hist_entry__sym_snprintf,
285         .se_width_idx   = HISTC_SYMBOL,
286 };
287
288 /* --sort srcline */
289
290 static char *hist_entry__get_srcline(struct hist_entry *he)
291 {
292         struct map *map = he->ms.map;
293
294         if (!map)
295                 return SRCLINE_UNKNOWN;
296
297         return get_srcline(map->dso, map__rip_2objdump(map, he->ip),
298                            he->ms.sym, true);
299 }
300
301 static int64_t
302 sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
303 {
304         if (!left->srcline)
305                 left->srcline = hist_entry__get_srcline(left);
306         if (!right->srcline)
307                 right->srcline = hist_entry__get_srcline(right);
308
309         return strcmp(right->srcline, left->srcline);
310 }
311
312 static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
313                                         size_t size, unsigned int width)
314 {
315         if (!he->srcline)
316                 he->srcline = hist_entry__get_srcline(he);
317
318         return repsep_snprintf(bf, size, "%-.*s", width, he->srcline);
319 }
320
321 struct sort_entry sort_srcline = {
322         .se_header      = "Source:Line",
323         .se_cmp         = sort__srcline_cmp,
324         .se_snprintf    = hist_entry__srcline_snprintf,
325         .se_width_idx   = HISTC_SRCLINE,
326 };
327
328 /* --sort srcfile */
329
330 static char no_srcfile[1];
331
332 static char *hist_entry__get_srcfile(struct hist_entry *e)
333 {
334         char *sf, *p;
335         struct map *map = e->ms.map;
336
337         if (!map)
338                 return no_srcfile;
339
340         sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
341                          e->ms.sym, false, true);
342         if (!strcmp(sf, SRCLINE_UNKNOWN))
343                 return no_srcfile;
344         p = strchr(sf, ':');
345         if (p && *sf) {
346                 *p = 0;
347                 return sf;
348         }
349         free(sf);
350         return no_srcfile;
351 }
352
353 static int64_t
354 sort__srcfile_cmp(struct hist_entry *left, struct hist_entry *right)
355 {
356         if (!left->srcfile)
357                 left->srcfile = hist_entry__get_srcfile(left);
358         if (!right->srcfile)
359                 right->srcfile = hist_entry__get_srcfile(right);
360
361         return strcmp(right->srcfile, left->srcfile);
362 }
363
364 static int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf,
365                                         size_t size, unsigned int width)
366 {
367         if (!he->srcfile)
368                 he->srcfile = hist_entry__get_srcfile(he);
369
370         return repsep_snprintf(bf, size, "%-.*s", width, he->srcfile);
371 }
372
373 struct sort_entry sort_srcfile = {
374         .se_header      = "Source File",
375         .se_cmp         = sort__srcfile_cmp,
376         .se_snprintf    = hist_entry__srcfile_snprintf,
377         .se_width_idx   = HISTC_SRCFILE,
378 };
379
380 /* --sort parent */
381
382 static int64_t
383 sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
384 {
385         struct symbol *sym_l = left->parent;
386         struct symbol *sym_r = right->parent;
387
388         if (!sym_l || !sym_r)
389                 return cmp_null(sym_l, sym_r);
390
391         return strcmp(sym_r->name, sym_l->name);
392 }
393
394 static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
395                                        size_t size, unsigned int width)
396 {
397         return repsep_snprintf(bf, size, "%-*.*s", width, width,
398                               he->parent ? he->parent->name : "[other]");
399 }
400
401 struct sort_entry sort_parent = {
402         .se_header      = "Parent symbol",
403         .se_cmp         = sort__parent_cmp,
404         .se_snprintf    = hist_entry__parent_snprintf,
405         .se_width_idx   = HISTC_PARENT,
406 };
407
408 /* --sort cpu */
409
410 static int64_t
411 sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
412 {
413         return right->cpu - left->cpu;
414 }
415
416 static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
417                                     size_t size, unsigned int width)
418 {
419         return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu);
420 }
421
422 struct sort_entry sort_cpu = {
423         .se_header      = "CPU",
424         .se_cmp         = sort__cpu_cmp,
425         .se_snprintf    = hist_entry__cpu_snprintf,
426         .se_width_idx   = HISTC_CPU,
427 };
428
429 /* --sort socket */
430
431 static int64_t
432 sort__socket_cmp(struct hist_entry *left, struct hist_entry *right)
433 {
434         return right->socket - left->socket;
435 }
436
437 static int hist_entry__socket_snprintf(struct hist_entry *he, char *bf,
438                                     size_t size, unsigned int width)
439 {
440         return repsep_snprintf(bf, size, "%*.*d", width, width-3, he->socket);
441 }
442
443 struct sort_entry sort_socket = {
444         .se_header      = "Socket",
445         .se_cmp         = sort__socket_cmp,
446         .se_snprintf    = hist_entry__socket_snprintf,
447         .se_width_idx   = HISTC_SOCKET,
448 };
449
450 /* --sort trace */
451
452 static char *get_trace_output(struct hist_entry *he)
453 {
454         struct trace_seq seq;
455         struct perf_evsel *evsel;
456         struct pevent_record rec = {
457                 .data = he->raw_data,
458                 .size = he->raw_size,
459         };
460
461         evsel = hists_to_evsel(he->hists);
462
463         trace_seq_init(&seq);
464         if (symbol_conf.raw_trace) {
465                 pevent_print_fields(&seq, he->raw_data, he->raw_size,
466                                     evsel->tp_format);
467         } else {
468                 pevent_event_info(&seq, evsel->tp_format, &rec);
469         }
470         return seq.buffer;
471 }
472
473 static int64_t
474 sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
475 {
476         struct perf_evsel *evsel;
477
478         evsel = hists_to_evsel(left->hists);
479         if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
480                 return 0;
481
482         if (left->trace_output == NULL)
483                 left->trace_output = get_trace_output(left);
484         if (right->trace_output == NULL)
485                 right->trace_output = get_trace_output(right);
486
487         return strcmp(right->trace_output, left->trace_output);
488 }
489
490 static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf,
491                                     size_t size, unsigned int width)
492 {
493         struct perf_evsel *evsel;
494
495         evsel = hists_to_evsel(he->hists);
496         if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
497                 return scnprintf(bf, size, "%-.*s", width, "N/A");
498
499         if (he->trace_output == NULL)
500                 he->trace_output = get_trace_output(he);
501         return repsep_snprintf(bf, size, "%-.*s", width, he->trace_output);
502 }
503
504 struct sort_entry sort_trace = {
505         .se_header      = "Trace output",
506         .se_cmp         = sort__trace_cmp,
507         .se_snprintf    = hist_entry__trace_snprintf,
508         .se_width_idx   = HISTC_TRACE,
509 };
510
511 /* sort keys for branch stacks */
512
513 static int64_t
514 sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
515 {
516         if (!left->branch_info || !right->branch_info)
517                 return cmp_null(left->branch_info, right->branch_info);
518
519         return _sort__dso_cmp(left->branch_info->from.map,
520                               right->branch_info->from.map);
521 }
522
523 static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
524                                     size_t size, unsigned int width)
525 {
526         if (he->branch_info)
527                 return _hist_entry__dso_snprintf(he->branch_info->from.map,
528                                                  bf, size, width);
529         else
530                 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
531 }
532
533 static int64_t
534 sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
535 {
536         if (!left->branch_info || !right->branch_info)
537                 return cmp_null(left->branch_info, right->branch_info);
538
539         return _sort__dso_cmp(left->branch_info->to.map,
540                               right->branch_info->to.map);
541 }
542
543 static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
544                                        size_t size, unsigned int width)
545 {
546         if (he->branch_info)
547                 return _hist_entry__dso_snprintf(he->branch_info->to.map,
548                                                  bf, size, width);
549         else
550                 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
551 }
552
553 static int64_t
554 sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
555 {
556         struct addr_map_symbol *from_l = &left->branch_info->from;
557         struct addr_map_symbol *from_r = &right->branch_info->from;
558
559         if (!left->branch_info || !right->branch_info)
560                 return cmp_null(left->branch_info, right->branch_info);
561
562         from_l = &left->branch_info->from;
563         from_r = &right->branch_info->from;
564
565         if (!from_l->sym && !from_r->sym)
566                 return _sort__addr_cmp(from_l->addr, from_r->addr);
567
568         return _sort__sym_cmp(from_l->sym, from_r->sym);
569 }
570
571 static int64_t
572 sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
573 {
574         struct addr_map_symbol *to_l, *to_r;
575
576         if (!left->branch_info || !right->branch_info)
577                 return cmp_null(left->branch_info, right->branch_info);
578
579         to_l = &left->branch_info->to;
580         to_r = &right->branch_info->to;
581
582         if (!to_l->sym && !to_r->sym)
583                 return _sort__addr_cmp(to_l->addr, to_r->addr);
584
585         return _sort__sym_cmp(to_l->sym, to_r->sym);
586 }
587
588 static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
589                                          size_t size, unsigned int width)
590 {
591         if (he->branch_info) {
592                 struct addr_map_symbol *from = &he->branch_info->from;
593
594                 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
595                                                  he->level, bf, size, width);
596         }
597
598         return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
599 }
600
601 static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
602                                        size_t size, unsigned int width)
603 {
604         if (he->branch_info) {
605                 struct addr_map_symbol *to = &he->branch_info->to;
606
607                 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
608                                                  he->level, bf, size, width);
609         }
610
611         return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
612 }
613
614 struct sort_entry sort_dso_from = {
615         .se_header      = "Source Shared Object",
616         .se_cmp         = sort__dso_from_cmp,
617         .se_snprintf    = hist_entry__dso_from_snprintf,
618         .se_width_idx   = HISTC_DSO_FROM,
619 };
620
621 struct sort_entry sort_dso_to = {
622         .se_header      = "Target Shared Object",
623         .se_cmp         = sort__dso_to_cmp,
624         .se_snprintf    = hist_entry__dso_to_snprintf,
625         .se_width_idx   = HISTC_DSO_TO,
626 };
627
628 struct sort_entry sort_sym_from = {
629         .se_header      = "Source Symbol",
630         .se_cmp         = sort__sym_from_cmp,
631         .se_snprintf    = hist_entry__sym_from_snprintf,
632         .se_width_idx   = HISTC_SYMBOL_FROM,
633 };
634
635 struct sort_entry sort_sym_to = {
636         .se_header      = "Target Symbol",
637         .se_cmp         = sort__sym_to_cmp,
638         .se_snprintf    = hist_entry__sym_to_snprintf,
639         .se_width_idx   = HISTC_SYMBOL_TO,
640 };
641
642 static int64_t
643 sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
644 {
645         unsigned char mp, p;
646
647         if (!left->branch_info || !right->branch_info)
648                 return cmp_null(left->branch_info, right->branch_info);
649
650         mp = left->branch_info->flags.mispred != right->branch_info->flags.mispred;
651         p  = left->branch_info->flags.predicted != right->branch_info->flags.predicted;
652         return mp || p;
653 }
654
655 static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
656                                     size_t size, unsigned int width){
657         static const char *out = "N/A";
658
659         if (he->branch_info) {
660                 if (he->branch_info->flags.predicted)
661                         out = "N";
662                 else if (he->branch_info->flags.mispred)
663                         out = "Y";
664         }
665
666         return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
667 }
668
669 static int64_t
670 sort__cycles_cmp(struct hist_entry *left, struct hist_entry *right)
671 {
672         return left->branch_info->flags.cycles -
673                 right->branch_info->flags.cycles;
674 }
675
676 static int hist_entry__cycles_snprintf(struct hist_entry *he, char *bf,
677                                     size_t size, unsigned int width)
678 {
679         if (he->branch_info->flags.cycles == 0)
680                 return repsep_snprintf(bf, size, "%-*s", width, "-");
681         return repsep_snprintf(bf, size, "%-*hd", width,
682                                he->branch_info->flags.cycles);
683 }
684
685 struct sort_entry sort_cycles = {
686         .se_header      = "Basic Block Cycles",
687         .se_cmp         = sort__cycles_cmp,
688         .se_snprintf    = hist_entry__cycles_snprintf,
689         .se_width_idx   = HISTC_CYCLES,
690 };
691
692 /* --sort daddr_sym */
693 static int64_t
694 sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
695 {
696         uint64_t l = 0, r = 0;
697
698         if (left->mem_info)
699                 l = left->mem_info->daddr.addr;
700         if (right->mem_info)
701                 r = right->mem_info->daddr.addr;
702
703         return (int64_t)(r - l);
704 }
705
706 static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
707                                     size_t size, unsigned int width)
708 {
709         uint64_t addr = 0;
710         struct map *map = NULL;
711         struct symbol *sym = NULL;
712
713         if (he->mem_info) {
714                 addr = he->mem_info->daddr.addr;
715                 map = he->mem_info->daddr.map;
716                 sym = he->mem_info->daddr.sym;
717         }
718         return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
719                                          width);
720 }
721
722 static int64_t
723 sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right)
724 {
725         uint64_t l = 0, r = 0;
726
727         if (left->mem_info)
728                 l = left->mem_info->iaddr.addr;
729         if (right->mem_info)
730                 r = right->mem_info->iaddr.addr;
731
732         return (int64_t)(r - l);
733 }
734
735 static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf,
736                                     size_t size, unsigned int width)
737 {
738         uint64_t addr = 0;
739         struct map *map = NULL;
740         struct symbol *sym = NULL;
741
742         if (he->mem_info) {
743                 addr = he->mem_info->iaddr.addr;
744                 map  = he->mem_info->iaddr.map;
745                 sym  = he->mem_info->iaddr.sym;
746         }
747         return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
748                                          width);
749 }
750
751 static int64_t
752 sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
753 {
754         struct map *map_l = NULL;
755         struct map *map_r = NULL;
756
757         if (left->mem_info)
758                 map_l = left->mem_info->daddr.map;
759         if (right->mem_info)
760                 map_r = right->mem_info->daddr.map;
761
762         return _sort__dso_cmp(map_l, map_r);
763 }
764
765 static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
766                                     size_t size, unsigned int width)
767 {
768         struct map *map = NULL;
769
770         if (he->mem_info)
771                 map = he->mem_info->daddr.map;
772
773         return _hist_entry__dso_snprintf(map, bf, size, width);
774 }
775
776 static int64_t
777 sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
778 {
779         union perf_mem_data_src data_src_l;
780         union perf_mem_data_src data_src_r;
781
782         if (left->mem_info)
783                 data_src_l = left->mem_info->data_src;
784         else
785                 data_src_l.mem_lock = PERF_MEM_LOCK_NA;
786
787         if (right->mem_info)
788                 data_src_r = right->mem_info->data_src;
789         else
790                 data_src_r.mem_lock = PERF_MEM_LOCK_NA;
791
792         return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
793 }
794
795 static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
796                                     size_t size, unsigned int width)
797 {
798         const char *out;
799         u64 mask = PERF_MEM_LOCK_NA;
800
801         if (he->mem_info)
802                 mask = he->mem_info->data_src.mem_lock;
803
804         if (mask & PERF_MEM_LOCK_NA)
805                 out = "N/A";
806         else if (mask & PERF_MEM_LOCK_LOCKED)
807                 out = "Yes";
808         else
809                 out = "No";
810
811         return repsep_snprintf(bf, size, "%.*s", width, out);
812 }
813
814 static int64_t
815 sort__tlb_cmp(struct hist_entry *left, struct hist_entry *right)
816 {
817         union perf_mem_data_src data_src_l;
818         union perf_mem_data_src data_src_r;
819
820         if (left->mem_info)
821                 data_src_l = left->mem_info->data_src;
822         else
823                 data_src_l.mem_dtlb = PERF_MEM_TLB_NA;
824
825         if (right->mem_info)
826                 data_src_r = right->mem_info->data_src;
827         else
828                 data_src_r.mem_dtlb = PERF_MEM_TLB_NA;
829
830         return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb);
831 }
832
833 static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
834                                     size_t size, unsigned int width)
835 {
836         char out[64];
837
838         perf_mem__tlb_scnprintf(out, sizeof(out), he->mem_info);
839         return repsep_snprintf(bf, size, "%-*s", width, out);
840 }
841
842 static int64_t
843 sort__lvl_cmp(struct hist_entry *left, struct hist_entry *right)
844 {
845         union perf_mem_data_src data_src_l;
846         union perf_mem_data_src data_src_r;
847
848         if (left->mem_info)
849                 data_src_l = left->mem_info->data_src;
850         else
851                 data_src_l.mem_lvl = PERF_MEM_LVL_NA;
852
853         if (right->mem_info)
854                 data_src_r = right->mem_info->data_src;
855         else
856                 data_src_r.mem_lvl = PERF_MEM_LVL_NA;
857
858         return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl);
859 }
860
861 static const char * const mem_lvl[] = {
862         "N/A",
863         "HIT",
864         "MISS",
865         "L1",
866         "LFB",
867         "L2",
868         "L3",
869         "Local RAM",
870         "Remote RAM (1 hop)",
871         "Remote RAM (2 hops)",
872         "Remote Cache (1 hop)",
873         "Remote Cache (2 hops)",
874         "I/O",
875         "Uncached",
876 };
877
878 static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
879                                     size_t size, unsigned int width)
880 {
881         char out[64];
882         size_t sz = sizeof(out) - 1; /* -1 for null termination */
883         size_t i, l = 0;
884         u64 m =  PERF_MEM_LVL_NA;
885         u64 hit, miss;
886
887         if (he->mem_info)
888                 m  = he->mem_info->data_src.mem_lvl;
889
890         out[0] = '\0';
891
892         hit = m & PERF_MEM_LVL_HIT;
893         miss = m & PERF_MEM_LVL_MISS;
894
895         /* already taken care of */
896         m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
897
898         for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
899                 if (!(m & 0x1))
900                         continue;
901                 if (l) {
902                         strcat(out, " or ");
903                         l += 4;
904                 }
905                 strncat(out, mem_lvl[i], sz - l);
906                 l += strlen(mem_lvl[i]);
907         }
908         if (*out == '\0')
909                 strcpy(out, "N/A");
910         if (hit)
911                 strncat(out, " hit", sz - l);
912         if (miss)
913                 strncat(out, " miss", sz - l);
914
915         return repsep_snprintf(bf, size, "%-*s", width, out);
916 }
917
918 static int64_t
919 sort__snoop_cmp(struct hist_entry *left, struct hist_entry *right)
920 {
921         union perf_mem_data_src data_src_l;
922         union perf_mem_data_src data_src_r;
923
924         if (left->mem_info)
925                 data_src_l = left->mem_info->data_src;
926         else
927                 data_src_l.mem_snoop = PERF_MEM_SNOOP_NA;
928
929         if (right->mem_info)
930                 data_src_r = right->mem_info->data_src;
931         else
932                 data_src_r.mem_snoop = PERF_MEM_SNOOP_NA;
933
934         return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop);
935 }
936
937 static const char * const snoop_access[] = {
938         "N/A",
939         "None",
940         "Miss",
941         "Hit",
942         "HitM",
943 };
944
945 static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
946                                     size_t size, unsigned int width)
947 {
948         char out[64];
949         size_t sz = sizeof(out) - 1; /* -1 for null termination */
950         size_t i, l = 0;
951         u64 m = PERF_MEM_SNOOP_NA;
952
953         out[0] = '\0';
954
955         if (he->mem_info)
956                 m = he->mem_info->data_src.mem_snoop;
957
958         for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) {
959                 if (!(m & 0x1))
960                         continue;
961                 if (l) {
962                         strcat(out, " or ");
963                         l += 4;
964                 }
965                 strncat(out, snoop_access[i], sz - l);
966                 l += strlen(snoop_access[i]);
967         }
968
969         if (*out == '\0')
970                 strcpy(out, "N/A");
971
972         return repsep_snprintf(bf, size, "%-*s", width, out);
973 }
974
975 static int64_t
976 sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
977 {
978         u64 l, r;
979         struct map *l_map, *r_map;
980
981         if (!left->mem_info)  return -1;
982         if (!right->mem_info) return 1;
983
984         /* group event types together */
985         if (left->cpumode > right->cpumode) return -1;
986         if (left->cpumode < right->cpumode) return 1;
987
988         l_map = left->mem_info->daddr.map;
989         r_map = right->mem_info->daddr.map;
990
991         /* if both are NULL, jump to sort on al_addr instead */
992         if (!l_map && !r_map)
993                 goto addr;
994
995         if (!l_map) return -1;
996         if (!r_map) return 1;
997
998         if (l_map->maj > r_map->maj) return -1;
999         if (l_map->maj < r_map->maj) return 1;
1000
1001         if (l_map->min > r_map->min) return -1;
1002         if (l_map->min < r_map->min) return 1;
1003
1004         if (l_map->ino > r_map->ino) return -1;
1005         if (l_map->ino < r_map->ino) return 1;
1006
1007         if (l_map->ino_generation > r_map->ino_generation) return -1;
1008         if (l_map->ino_generation < r_map->ino_generation) return 1;
1009
1010         /*
1011          * Addresses with no major/minor numbers are assumed to be
1012          * anonymous in userspace.  Sort those on pid then address.
1013          *
1014          * The kernel and non-zero major/minor mapped areas are
1015          * assumed to be unity mapped.  Sort those on address.
1016          */
1017
1018         if ((left->cpumode != PERF_RECORD_MISC_KERNEL) &&
1019             (!(l_map->flags & MAP_SHARED)) &&
1020             !l_map->maj && !l_map->min && !l_map->ino &&
1021             !l_map->ino_generation) {
1022                 /* userspace anonymous */
1023
1024                 if (left->thread->pid_ > right->thread->pid_) return -1;
1025                 if (left->thread->pid_ < right->thread->pid_) return 1;
1026         }
1027
1028 addr:
1029         /* al_addr does all the right addr - start + offset calculations */
1030         l = cl_address(left->mem_info->daddr.al_addr);
1031         r = cl_address(right->mem_info->daddr.al_addr);
1032
1033         if (l > r) return -1;
1034         if (l < r) return 1;
1035
1036         return 0;
1037 }
1038
1039 static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
1040                                           size_t size, unsigned int width)
1041 {
1042
1043         uint64_t addr = 0;
1044         struct map *map = NULL;
1045         struct symbol *sym = NULL;
1046         char level = he->level;
1047
1048         if (he->mem_info) {
1049                 addr = cl_address(he->mem_info->daddr.al_addr);
1050                 map = he->mem_info->daddr.map;
1051                 sym = he->mem_info->daddr.sym;
1052
1053                 /* print [s] for shared data mmaps */
1054                 if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
1055                      map && (map->type == MAP__VARIABLE) &&
1056                     (map->flags & MAP_SHARED) &&
1057                     (map->maj || map->min || map->ino ||
1058                      map->ino_generation))
1059                         level = 's';
1060                 else if (!map)
1061                         level = 'X';
1062         }
1063         return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size,
1064                                          width);
1065 }
1066
1067 struct sort_entry sort_mispredict = {
1068         .se_header      = "Branch Mispredicted",
1069         .se_cmp         = sort__mispredict_cmp,
1070         .se_snprintf    = hist_entry__mispredict_snprintf,
1071         .se_width_idx   = HISTC_MISPREDICT,
1072 };
1073
1074 static u64 he_weight(struct hist_entry *he)
1075 {
1076         return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
1077 }
1078
1079 static int64_t
1080 sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
1081 {
1082         return he_weight(left) - he_weight(right);
1083 }
1084
1085 static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
1086                                     size_t size, unsigned int width)
1087 {
1088         return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
1089 }
1090
1091 struct sort_entry sort_local_weight = {
1092         .se_header      = "Local Weight",
1093         .se_cmp         = sort__local_weight_cmp,
1094         .se_snprintf    = hist_entry__local_weight_snprintf,
1095         .se_width_idx   = HISTC_LOCAL_WEIGHT,
1096 };
1097
1098 static int64_t
1099 sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
1100 {
1101         return left->stat.weight - right->stat.weight;
1102 }
1103
1104 static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
1105                                               size_t size, unsigned int width)
1106 {
1107         return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
1108 }
1109
1110 struct sort_entry sort_global_weight = {
1111         .se_header      = "Weight",
1112         .se_cmp         = sort__global_weight_cmp,
1113         .se_snprintf    = hist_entry__global_weight_snprintf,
1114         .se_width_idx   = HISTC_GLOBAL_WEIGHT,
1115 };
1116
1117 struct sort_entry sort_mem_daddr_sym = {
1118         .se_header      = "Data Symbol",
1119         .se_cmp         = sort__daddr_cmp,
1120         .se_snprintf    = hist_entry__daddr_snprintf,
1121         .se_width_idx   = HISTC_MEM_DADDR_SYMBOL,
1122 };
1123
1124 struct sort_entry sort_mem_iaddr_sym = {
1125         .se_header      = "Code Symbol",
1126         .se_cmp         = sort__iaddr_cmp,
1127         .se_snprintf    = hist_entry__iaddr_snprintf,
1128         .se_width_idx   = HISTC_MEM_IADDR_SYMBOL,
1129 };
1130
1131 struct sort_entry sort_mem_daddr_dso = {
1132         .se_header      = "Data Object",
1133         .se_cmp         = sort__dso_daddr_cmp,
1134         .se_snprintf    = hist_entry__dso_daddr_snprintf,
1135         .se_width_idx   = HISTC_MEM_DADDR_SYMBOL,
1136 };
1137
1138 struct sort_entry sort_mem_locked = {
1139         .se_header      = "Locked",
1140         .se_cmp         = sort__locked_cmp,
1141         .se_snprintf    = hist_entry__locked_snprintf,
1142         .se_width_idx   = HISTC_MEM_LOCKED,
1143 };
1144
1145 struct sort_entry sort_mem_tlb = {
1146         .se_header      = "TLB access",
1147         .se_cmp         = sort__tlb_cmp,
1148         .se_snprintf    = hist_entry__tlb_snprintf,
1149         .se_width_idx   = HISTC_MEM_TLB,
1150 };
1151
1152 struct sort_entry sort_mem_lvl = {
1153         .se_header      = "Memory access",
1154         .se_cmp         = sort__lvl_cmp,
1155         .se_snprintf    = hist_entry__lvl_snprintf,
1156         .se_width_idx   = HISTC_MEM_LVL,
1157 };
1158
1159 struct sort_entry sort_mem_snoop = {
1160         .se_header      = "Snoop",
1161         .se_cmp         = sort__snoop_cmp,
1162         .se_snprintf    = hist_entry__snoop_snprintf,
1163         .se_width_idx   = HISTC_MEM_SNOOP,
1164 };
1165
1166 struct sort_entry sort_mem_dcacheline = {
1167         .se_header      = "Data Cacheline",
1168         .se_cmp         = sort__dcacheline_cmp,
1169         .se_snprintf    = hist_entry__dcacheline_snprintf,
1170         .se_width_idx   = HISTC_MEM_DCACHELINE,
1171 };
1172
1173 static int64_t
1174 sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
1175 {
1176         if (!left->branch_info || !right->branch_info)
1177                 return cmp_null(left->branch_info, right->branch_info);
1178
1179         return left->branch_info->flags.abort !=
1180                 right->branch_info->flags.abort;
1181 }
1182
1183 static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
1184                                     size_t size, unsigned int width)
1185 {
1186         static const char *out = "N/A";
1187
1188         if (he->branch_info) {
1189                 if (he->branch_info->flags.abort)
1190                         out = "A";
1191                 else
1192                         out = ".";
1193         }
1194
1195         return repsep_snprintf(bf, size, "%-*s", width, out);
1196 }
1197
1198 struct sort_entry sort_abort = {
1199         .se_header      = "Transaction abort",
1200         .se_cmp         = sort__abort_cmp,
1201         .se_snprintf    = hist_entry__abort_snprintf,
1202         .se_width_idx   = HISTC_ABORT,
1203 };
1204
1205 static int64_t
1206 sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
1207 {
1208         if (!left->branch_info || !right->branch_info)
1209                 return cmp_null(left->branch_info, right->branch_info);
1210
1211         return left->branch_info->flags.in_tx !=
1212                 right->branch_info->flags.in_tx;
1213 }
1214
1215 static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
1216                                     size_t size, unsigned int width)
1217 {
1218         static const char *out = "N/A";
1219
1220         if (he->branch_info) {
1221                 if (he->branch_info->flags.in_tx)
1222                         out = "T";
1223                 else
1224                         out = ".";
1225         }
1226
1227         return repsep_snprintf(bf, size, "%-*s", width, out);
1228 }
1229
1230 struct sort_entry sort_in_tx = {
1231         .se_header      = "Branch in transaction",
1232         .se_cmp         = sort__in_tx_cmp,
1233         .se_snprintf    = hist_entry__in_tx_snprintf,
1234         .se_width_idx   = HISTC_IN_TX,
1235 };
1236
1237 static int64_t
1238 sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
1239 {
1240         return left->transaction - right->transaction;
1241 }
1242
1243 static inline char *add_str(char *p, const char *str)
1244 {
1245         strcpy(p, str);
1246         return p + strlen(str);
1247 }
1248
1249 static struct txbit {
1250         unsigned flag;
1251         const char *name;
1252         int skip_for_len;
1253 } txbits[] = {
1254         { PERF_TXN_ELISION,        "EL ",        0 },
1255         { PERF_TXN_TRANSACTION,    "TX ",        1 },
1256         { PERF_TXN_SYNC,           "SYNC ",      1 },
1257         { PERF_TXN_ASYNC,          "ASYNC ",     0 },
1258         { PERF_TXN_RETRY,          "RETRY ",     0 },
1259         { PERF_TXN_CONFLICT,       "CON ",       0 },
1260         { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
1261         { PERF_TXN_CAPACITY_READ,  "CAP-READ ",  0 },
1262         { 0, NULL, 0 }
1263 };
1264
1265 int hist_entry__transaction_len(void)
1266 {
1267         int i;
1268         int len = 0;
1269
1270         for (i = 0; txbits[i].name; i++) {
1271                 if (!txbits[i].skip_for_len)
1272                         len += strlen(txbits[i].name);
1273         }
1274         len += 4; /* :XX<space> */
1275         return len;
1276 }
1277
1278 static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
1279                                             size_t size, unsigned int width)
1280 {
1281         u64 t = he->transaction;
1282         char buf[128];
1283         char *p = buf;
1284         int i;
1285
1286         buf[0] = 0;
1287         for (i = 0; txbits[i].name; i++)
1288                 if (txbits[i].flag & t)
1289                         p = add_str(p, txbits[i].name);
1290         if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
1291                 p = add_str(p, "NEITHER ");
1292         if (t & PERF_TXN_ABORT_MASK) {
1293                 sprintf(p, ":%" PRIx64,
1294                         (t & PERF_TXN_ABORT_MASK) >>
1295                         PERF_TXN_ABORT_SHIFT);
1296                 p += strlen(p);
1297         }
1298
1299         return repsep_snprintf(bf, size, "%-*s", width, buf);
1300 }
1301
1302 struct sort_entry sort_transaction = {
1303         .se_header      = "Transaction                ",
1304         .se_cmp         = sort__transaction_cmp,
1305         .se_snprintf    = hist_entry__transaction_snprintf,
1306         .se_width_idx   = HISTC_TRANSACTION,
1307 };
1308
1309 struct sort_dimension {
1310         const char              *name;
1311         struct sort_entry       *entry;
1312         int                     taken;
1313 };
1314
1315 #define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
1316
1317 static struct sort_dimension common_sort_dimensions[] = {
1318         DIM(SORT_PID, "pid", sort_thread),
1319         DIM(SORT_COMM, "comm", sort_comm),
1320         DIM(SORT_DSO, "dso", sort_dso),
1321         DIM(SORT_SYM, "symbol", sort_sym),
1322         DIM(SORT_PARENT, "parent", sort_parent),
1323         DIM(SORT_CPU, "cpu", sort_cpu),
1324         DIM(SORT_SOCKET, "socket", sort_socket),
1325         DIM(SORT_SRCLINE, "srcline", sort_srcline),
1326         DIM(SORT_SRCFILE, "srcfile", sort_srcfile),
1327         DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
1328         DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
1329         DIM(SORT_TRANSACTION, "transaction", sort_transaction),
1330         DIM(SORT_TRACE, "trace", sort_trace),
1331 };
1332
1333 #undef DIM
1334
1335 #define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) }
1336
1337 static struct sort_dimension bstack_sort_dimensions[] = {
1338         DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
1339         DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
1340         DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
1341         DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
1342         DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
1343         DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1344         DIM(SORT_ABORT, "abort", sort_abort),
1345         DIM(SORT_CYCLES, "cycles", sort_cycles),
1346 };
1347
1348 #undef DIM
1349
1350 #define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
1351
1352 static struct sort_dimension memory_sort_dimensions[] = {
1353         DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
1354         DIM(SORT_MEM_IADDR_SYMBOL, "symbol_iaddr", sort_mem_iaddr_sym),
1355         DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
1356         DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
1357         DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
1358         DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1359         DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1360         DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
1361 };
1362
1363 #undef DIM
1364
1365 struct hpp_dimension {
1366         const char              *name;
1367         struct perf_hpp_fmt     *fmt;
1368         int                     taken;
1369 };
1370
1371 #define DIM(d, n) { .name = n, .fmt = &perf_hpp__format[d], }
1372
1373 static struct hpp_dimension hpp_sort_dimensions[] = {
1374         DIM(PERF_HPP__OVERHEAD, "overhead"),
1375         DIM(PERF_HPP__OVERHEAD_SYS, "overhead_sys"),
1376         DIM(PERF_HPP__OVERHEAD_US, "overhead_us"),
1377         DIM(PERF_HPP__OVERHEAD_GUEST_SYS, "overhead_guest_sys"),
1378         DIM(PERF_HPP__OVERHEAD_GUEST_US, "overhead_guest_us"),
1379         DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"),
1380         DIM(PERF_HPP__SAMPLES, "sample"),
1381         DIM(PERF_HPP__PERIOD, "period"),
1382 };
1383
1384 #undef DIM
1385
1386 struct hpp_sort_entry {
1387         struct perf_hpp_fmt hpp;
1388         struct sort_entry *se;
1389 };
1390
1391 void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1392 {
1393         struct hpp_sort_entry *hse;
1394
1395         if (!perf_hpp__is_sort_entry(fmt))
1396                 return;
1397
1398         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1399         hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name));
1400 }
1401
1402 static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1403                               struct perf_evsel *evsel)
1404 {
1405         struct hpp_sort_entry *hse;
1406         size_t len = fmt->user_len;
1407
1408         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1409
1410         if (!len)
1411                 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1412
1413         return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1414 }
1415
1416 static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1417                              struct perf_hpp *hpp __maybe_unused,
1418                              struct perf_evsel *evsel)
1419 {
1420         struct hpp_sort_entry *hse;
1421         size_t len = fmt->user_len;
1422
1423         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1424
1425         if (!len)
1426                 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1427
1428         return len;
1429 }
1430
1431 static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1432                              struct hist_entry *he)
1433 {
1434         struct hpp_sort_entry *hse;
1435         size_t len = fmt->user_len;
1436
1437         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1438
1439         if (!len)
1440                 len = hists__col_len(he->hists, hse->se->se_width_idx);
1441
1442         return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1443 }
1444
1445 static int64_t __sort__hpp_cmp(struct perf_hpp_fmt *fmt,
1446                                struct hist_entry *a, struct hist_entry *b)
1447 {
1448         struct hpp_sort_entry *hse;
1449
1450         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1451         return hse->se->se_cmp(a, b);
1452 }
1453
1454 static int64_t __sort__hpp_collapse(struct perf_hpp_fmt *fmt,
1455                                     struct hist_entry *a, struct hist_entry *b)
1456 {
1457         struct hpp_sort_entry *hse;
1458         int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
1459
1460         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1461         collapse_fn = hse->se->se_collapse ?: hse->se->se_cmp;
1462         return collapse_fn(a, b);
1463 }
1464
1465 static int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt,
1466                                 struct hist_entry *a, struct hist_entry *b)
1467 {
1468         struct hpp_sort_entry *hse;
1469         int64_t (*sort_fn)(struct hist_entry *, struct hist_entry *);
1470
1471         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1472         sort_fn = hse->se->se_sort ?: hse->se->se_cmp;
1473         return sort_fn(a, b);
1474 }
1475
1476 bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format)
1477 {
1478         return format->header == __sort__hpp_header;
1479 }
1480
1481 static bool __sort__hpp_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1482 {
1483         struct hpp_sort_entry *hse_a;
1484         struct hpp_sort_entry *hse_b;
1485
1486         if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b))
1487                 return false;
1488
1489         hse_a = container_of(a, struct hpp_sort_entry, hpp);
1490         hse_b = container_of(b, struct hpp_sort_entry, hpp);
1491
1492         return hse_a->se == hse_b->se;
1493 }
1494
1495 static void hse_free(struct perf_hpp_fmt *fmt)
1496 {
1497         struct hpp_sort_entry *hse;
1498
1499         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1500         free(hse);
1501 }
1502
1503 static struct hpp_sort_entry *
1504 __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1505 {
1506         struct hpp_sort_entry *hse;
1507
1508         hse = malloc(sizeof(*hse));
1509         if (hse == NULL) {
1510                 pr_err("Memory allocation failed\n");
1511                 return NULL;
1512         }
1513
1514         hse->se = sd->entry;
1515         hse->hpp.name = sd->entry->se_header;
1516         hse->hpp.header = __sort__hpp_header;
1517         hse->hpp.width = __sort__hpp_width;
1518         hse->hpp.entry = __sort__hpp_entry;
1519         hse->hpp.color = NULL;
1520
1521         hse->hpp.cmp = __sort__hpp_cmp;
1522         hse->hpp.collapse = __sort__hpp_collapse;
1523         hse->hpp.sort = __sort__hpp_sort;
1524         hse->hpp.equal = __sort__hpp_equal;
1525         hse->hpp.free = hse_free;
1526
1527         INIT_LIST_HEAD(&hse->hpp.list);
1528         INIT_LIST_HEAD(&hse->hpp.sort_list);
1529         hse->hpp.elide = false;
1530         hse->hpp.len = 0;
1531         hse->hpp.user_len = 0;
1532
1533         return hse;
1534 }
1535
1536 static void hpp_free(struct perf_hpp_fmt *fmt)
1537 {
1538         free(fmt);
1539 }
1540
1541 static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd)
1542 {
1543         struct perf_hpp_fmt *fmt;
1544
1545         fmt = memdup(hd->fmt, sizeof(*fmt));
1546         if (fmt) {
1547                 INIT_LIST_HEAD(&fmt->list);
1548                 INIT_LIST_HEAD(&fmt->sort_list);
1549                 fmt->free = hpp_free;
1550         }
1551
1552         return fmt;
1553 }
1554
1555 static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd)
1556 {
1557         struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
1558
1559         if (hse == NULL)
1560                 return -1;
1561
1562         perf_hpp__register_sort_field(&hse->hpp);
1563         return 0;
1564 }
1565
1566 static int __sort_dimension__add_hpp_output(struct perf_hpp_list *list,
1567                                             struct sort_dimension *sd)
1568 {
1569         struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
1570
1571         if (hse == NULL)
1572                 return -1;
1573
1574         perf_hpp_list__column_register(list, &hse->hpp);
1575         return 0;
1576 }
1577
1578 struct hpp_dynamic_entry {
1579         struct perf_hpp_fmt hpp;
1580         struct perf_evsel *evsel;
1581         struct format_field *field;
1582         unsigned dynamic_len;
1583         bool raw_trace;
1584 };
1585
1586 static int hde_width(struct hpp_dynamic_entry *hde)
1587 {
1588         if (!hde->hpp.len) {
1589                 int len = hde->dynamic_len;
1590                 int namelen = strlen(hde->field->name);
1591                 int fieldlen = hde->field->size;
1592
1593                 if (namelen > len)
1594                         len = namelen;
1595
1596                 if (!(hde->field->flags & FIELD_IS_STRING)) {
1597                         /* length for print hex numbers */
1598                         fieldlen = hde->field->size * 2 + 2;
1599                 }
1600                 if (fieldlen > len)
1601                         len = fieldlen;
1602
1603                 hde->hpp.len = len;
1604         }
1605         return hde->hpp.len;
1606 }
1607
1608 static void update_dynamic_len(struct hpp_dynamic_entry *hde,
1609                                struct hist_entry *he)
1610 {
1611         char *str, *pos;
1612         struct format_field *field = hde->field;
1613         size_t namelen;
1614         bool last = false;
1615
1616         if (hde->raw_trace)
1617                 return;
1618
1619         /* parse pretty print result and update max length */
1620         if (!he->trace_output)
1621                 he->trace_output = get_trace_output(he);
1622
1623         namelen = strlen(field->name);
1624         str = he->trace_output;
1625
1626         while (str) {
1627                 pos = strchr(str, ' ');
1628                 if (pos == NULL) {
1629                         last = true;
1630                         pos = str + strlen(str);
1631                 }
1632
1633                 if (!strncmp(str, field->name, namelen)) {
1634                         size_t len;
1635
1636                         str += namelen + 1;
1637                         len = pos - str;
1638
1639                         if (len > hde->dynamic_len)
1640                                 hde->dynamic_len = len;
1641                         break;
1642                 }
1643
1644                 if (last)
1645                         str = NULL;
1646                 else
1647                         str = pos + 1;
1648         }
1649 }
1650
1651 static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1652                               struct perf_evsel *evsel __maybe_unused)
1653 {
1654         struct hpp_dynamic_entry *hde;
1655         size_t len = fmt->user_len;
1656
1657         hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1658
1659         if (!len)
1660                 len = hde_width(hde);
1661
1662         return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, hde->field->name);
1663 }
1664
1665 static int __sort__hde_width(struct perf_hpp_fmt *fmt,
1666                              struct perf_hpp *hpp __maybe_unused,
1667                              struct perf_evsel *evsel __maybe_unused)
1668 {
1669         struct hpp_dynamic_entry *hde;
1670         size_t len = fmt->user_len;
1671
1672         hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1673
1674         if (!len)
1675                 len = hde_width(hde);
1676
1677         return len;
1678 }
1679
1680 bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists)
1681 {
1682         struct hpp_dynamic_entry *hde;
1683
1684         hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1685
1686         return hists_to_evsel(hists) == hde->evsel;
1687 }
1688
1689 static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1690                              struct hist_entry *he)
1691 {
1692         struct hpp_dynamic_entry *hde;
1693         size_t len = fmt->user_len;
1694         char *str, *pos;
1695         struct format_field *field;
1696         size_t namelen;
1697         bool last = false;
1698         int ret;
1699
1700         hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1701
1702         if (!len)
1703                 len = hde_width(hde);
1704
1705         if (hde->raw_trace)
1706                 goto raw_field;
1707
1708         field = hde->field;
1709         namelen = strlen(field->name);
1710         str = he->trace_output;
1711
1712         while (str) {
1713                 pos = strchr(str, ' ');
1714                 if (pos == NULL) {
1715                         last = true;
1716                         pos = str + strlen(str);
1717                 }
1718
1719                 if (!strncmp(str, field->name, namelen)) {
1720                         str += namelen + 1;
1721                         str = strndup(str, pos - str);
1722
1723                         if (str == NULL)
1724                                 return scnprintf(hpp->buf, hpp->size,
1725                                                  "%*.*s", len, len, "ERROR");
1726                         break;
1727                 }
1728
1729                 if (last)
1730                         str = NULL;
1731                 else
1732                         str = pos + 1;
1733         }
1734
1735         if (str == NULL) {
1736                 struct trace_seq seq;
1737 raw_field:
1738                 trace_seq_init(&seq);
1739                 pevent_print_field(&seq, he->raw_data, hde->field);
1740                 str = seq.buffer;
1741         }
1742
1743         ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, str);
1744         free(str);
1745         return ret;
1746 }
1747
1748 static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
1749                                struct hist_entry *a, struct hist_entry *b)
1750 {
1751         struct hpp_dynamic_entry *hde;
1752         struct format_field *field;
1753         unsigned offset, size;
1754
1755         hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1756
1757         field = hde->field;
1758         if (field->flags & FIELD_IS_DYNAMIC) {
1759                 unsigned long long dyn;
1760
1761                 pevent_read_number_field(field, a->raw_data, &dyn);
1762                 offset = dyn & 0xffff;
1763                 size = (dyn >> 16) & 0xffff;
1764
1765                 /* record max width for output */
1766                 if (size > hde->dynamic_len)
1767                         hde->dynamic_len = size;
1768         } else {
1769                 offset = field->offset;
1770                 size = field->size;
1771
1772                 update_dynamic_len(hde, a);
1773                 update_dynamic_len(hde, b);
1774         }
1775
1776         return memcmp(a->raw_data + offset, b->raw_data + offset, size);
1777 }
1778
1779 bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt)
1780 {
1781         return fmt->cmp == __sort__hde_cmp;
1782 }
1783
1784 static bool __sort__hde_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1785 {
1786         struct hpp_dynamic_entry *hde_a;
1787         struct hpp_dynamic_entry *hde_b;
1788
1789         if (!perf_hpp__is_dynamic_entry(a) || !perf_hpp__is_dynamic_entry(b))
1790                 return false;
1791
1792         hde_a = container_of(a, struct hpp_dynamic_entry, hpp);
1793         hde_b = container_of(b, struct hpp_dynamic_entry, hpp);
1794
1795         return hde_a->field == hde_b->field;
1796 }
1797
1798 static void hde_free(struct perf_hpp_fmt *fmt)
1799 {
1800         struct hpp_dynamic_entry *hde;
1801
1802         hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1803         free(hde);
1804 }
1805
1806 static struct hpp_dynamic_entry *
1807 __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
1808 {
1809         struct hpp_dynamic_entry *hde;
1810
1811         hde = malloc(sizeof(*hde));
1812         if (hde == NULL) {
1813                 pr_debug("Memory allocation failed\n");
1814                 return NULL;
1815         }
1816
1817         hde->evsel = evsel;
1818         hde->field = field;
1819         hde->dynamic_len = 0;
1820
1821         hde->hpp.name = field->name;
1822         hde->hpp.header = __sort__hde_header;
1823         hde->hpp.width  = __sort__hde_width;
1824         hde->hpp.entry  = __sort__hde_entry;
1825         hde->hpp.color  = NULL;
1826
1827         hde->hpp.cmp = __sort__hde_cmp;
1828         hde->hpp.collapse = __sort__hde_cmp;
1829         hde->hpp.sort = __sort__hde_cmp;
1830         hde->hpp.equal = __sort__hde_equal;
1831         hde->hpp.free = hde_free;
1832
1833         INIT_LIST_HEAD(&hde->hpp.list);
1834         INIT_LIST_HEAD(&hde->hpp.sort_list);
1835         hde->hpp.elide = false;
1836         hde->hpp.len = 0;
1837         hde->hpp.user_len = 0;
1838
1839         return hde;
1840 }
1841
1842 static int parse_field_name(char *str, char **event, char **field, char **opt)
1843 {
1844         char *event_name, *field_name, *opt_name;
1845
1846         event_name = str;
1847         field_name = strchr(str, '.');
1848
1849         if (field_name) {
1850                 *field_name++ = '\0';
1851         } else {
1852                 event_name = NULL;
1853                 field_name = str;
1854         }
1855
1856         opt_name = strchr(field_name, '/');
1857         if (opt_name)
1858                 *opt_name++ = '\0';
1859
1860         *event = event_name;
1861         *field = field_name;
1862         *opt   = opt_name;
1863
1864         return 0;
1865 }
1866
1867 /* find match evsel using a given event name.  The event name can be:
1868  *   1. '%' + event index (e.g. '%1' for first event)
1869  *   2. full event name (e.g. sched:sched_switch)
1870  *   3. partial event name (should not contain ':')
1871  */
1872 static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
1873 {
1874         struct perf_evsel *evsel = NULL;
1875         struct perf_evsel *pos;
1876         bool full_name;
1877
1878         /* case 1 */
1879         if (event_name[0] == '%') {
1880                 int nr = strtol(event_name+1, NULL, 0);
1881
1882                 if (nr > evlist->nr_entries)
1883                         return NULL;
1884
1885                 evsel = perf_evlist__first(evlist);
1886                 while (--nr > 0)
1887                         evsel = perf_evsel__next(evsel);
1888
1889                 return evsel;
1890         }
1891
1892         full_name = !!strchr(event_name, ':');
1893         evlist__for_each(evlist, pos) {
1894                 /* case 2 */
1895                 if (full_name && !strcmp(pos->name, event_name))
1896                         return pos;
1897                 /* case 3 */
1898                 if (!full_name && strstr(pos->name, event_name)) {
1899                         if (evsel) {
1900                                 pr_debug("'%s' event is ambiguous: it can be %s or %s\n",
1901                                          event_name, evsel->name, pos->name);
1902                                 return NULL;
1903                         }
1904                         evsel = pos;
1905                 }
1906         }
1907
1908         return evsel;
1909 }
1910
1911 static int __dynamic_dimension__add(struct perf_evsel *evsel,
1912                                     struct format_field *field,
1913                                     bool raw_trace)
1914 {
1915         struct hpp_dynamic_entry *hde;
1916
1917         hde = __alloc_dynamic_entry(evsel, field);
1918         if (hde == NULL)
1919                 return -ENOMEM;
1920
1921         hde->raw_trace = raw_trace;
1922
1923         perf_hpp__register_sort_field(&hde->hpp);
1924         return 0;
1925 }
1926
1927 static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
1928 {
1929         int ret;
1930         struct format_field *field;
1931
1932         field = evsel->tp_format->format.fields;
1933         while (field) {
1934                 ret = __dynamic_dimension__add(evsel, field, raw_trace);
1935                 if (ret < 0)
1936                         return ret;
1937
1938                 field = field->next;
1939         }
1940         return 0;
1941 }
1942
1943 static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
1944 {
1945         int ret;
1946         struct perf_evsel *evsel;
1947
1948         evlist__for_each(evlist, evsel) {
1949                 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
1950                         continue;
1951
1952                 ret = add_evsel_fields(evsel, raw_trace);
1953                 if (ret < 0)
1954                         return ret;
1955         }
1956         return 0;
1957 }
1958
1959 static int add_all_matching_fields(struct perf_evlist *evlist,
1960                                    char *field_name, bool raw_trace)
1961 {
1962         int ret = -ESRCH;
1963         struct perf_evsel *evsel;
1964         struct format_field *field;
1965
1966         evlist__for_each(evlist, evsel) {
1967                 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
1968                         continue;
1969
1970                 field = pevent_find_any_field(evsel->tp_format, field_name);
1971                 if (field == NULL)
1972                         continue;
1973
1974                 ret = __dynamic_dimension__add(evsel, field, raw_trace);
1975                 if (ret < 0)
1976                         break;
1977         }
1978         return ret;
1979 }
1980
1981 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
1982 {
1983         char *str, *event_name, *field_name, *opt_name;
1984         struct perf_evsel *evsel;
1985         struct format_field *field;
1986         bool raw_trace = symbol_conf.raw_trace;
1987         int ret = 0;
1988
1989         if (evlist == NULL)
1990                 return -ENOENT;
1991
1992         str = strdup(tok);
1993         if (str == NULL)
1994                 return -ENOMEM;
1995
1996         if (parse_field_name(str, &event_name, &field_name, &opt_name) < 0) {
1997                 ret = -EINVAL;
1998                 goto out;
1999         }
2000
2001         if (opt_name) {
2002                 if (strcmp(opt_name, "raw")) {
2003                         pr_debug("unsupported field option %s\n", opt_name);
2004                         ret = -EINVAL;
2005                         goto out;
2006                 }
2007                 raw_trace = true;
2008         }
2009
2010         if (!strcmp(field_name, "trace_fields")) {
2011                 ret = add_all_dynamic_fields(evlist, raw_trace);
2012                 goto out;
2013         }
2014
2015         if (event_name == NULL) {
2016                 ret = add_all_matching_fields(evlist, field_name, raw_trace);
2017                 goto out;
2018         }
2019
2020         evsel = find_evsel(evlist, event_name);
2021         if (evsel == NULL) {
2022                 pr_debug("Cannot find event: %s\n", event_name);
2023                 ret = -ENOENT;
2024                 goto out;
2025         }
2026
2027         if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2028                 pr_debug("%s is not a tracepoint event\n", event_name);
2029                 ret = -EINVAL;
2030                 goto out;
2031         }
2032
2033         if (!strcmp(field_name, "*")) {
2034                 ret = add_evsel_fields(evsel, raw_trace);
2035         } else {
2036                 field = pevent_find_any_field(evsel->tp_format, field_name);
2037                 if (field == NULL) {
2038                         pr_debug("Cannot find event field for %s.%s\n",
2039                                  event_name, field_name);
2040                         return -ENOENT;
2041                 }
2042
2043                 ret = __dynamic_dimension__add(evsel, field, raw_trace);
2044         }
2045
2046 out:
2047         free(str);
2048         return ret;
2049 }
2050
2051 static int __sort_dimension__add(struct sort_dimension *sd)
2052 {
2053         if (sd->taken)
2054                 return 0;
2055
2056         if (__sort_dimension__add_hpp_sort(sd) < 0)
2057                 return -1;
2058
2059         if (sd->entry->se_collapse)
2060                 sort__need_collapse = 1;
2061
2062         sd->taken = 1;
2063
2064         return 0;
2065 }
2066
2067 static int __hpp_dimension__add(struct hpp_dimension *hd)
2068 {
2069         struct perf_hpp_fmt *fmt;
2070
2071         if (hd->taken)
2072                 return 0;
2073
2074         fmt = __hpp_dimension__alloc_hpp(hd);
2075         if (!fmt)
2076                 return -1;
2077
2078         hd->taken = 1;
2079         perf_hpp__register_sort_field(fmt);
2080         return 0;
2081 }
2082
2083 static int __sort_dimension__add_output(struct perf_hpp_list *list,
2084                                         struct sort_dimension *sd)
2085 {
2086         if (sd->taken)
2087                 return 0;
2088
2089         if (__sort_dimension__add_hpp_output(list, sd) < 0)
2090                 return -1;
2091
2092         sd->taken = 1;
2093         return 0;
2094 }
2095
2096 static int __hpp_dimension__add_output(struct perf_hpp_list *list,
2097                                        struct hpp_dimension *hd)
2098 {
2099         struct perf_hpp_fmt *fmt;
2100
2101         if (hd->taken)
2102                 return 0;
2103
2104         fmt = __hpp_dimension__alloc_hpp(hd);
2105         if (!fmt)
2106                 return -1;
2107
2108         hd->taken = 1;
2109         perf_hpp_list__column_register(list, fmt);
2110         return 0;
2111 }
2112
2113 int hpp_dimension__add_output(unsigned col)
2114 {
2115         BUG_ON(col >= PERF_HPP__MAX_INDEX);
2116         return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]);
2117 }
2118
2119 static int sort_dimension__add(const char *tok,
2120                                struct perf_evlist *evlist __maybe_unused)
2121 {
2122         unsigned int i;
2123
2124         for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
2125                 struct sort_dimension *sd = &common_sort_dimensions[i];
2126
2127                 if (strncasecmp(tok, sd->name, strlen(tok)))
2128                         continue;
2129
2130                 if (sd->entry == &sort_parent) {
2131                         int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
2132                         if (ret) {
2133                                 char err[BUFSIZ];
2134
2135                                 regerror(ret, &parent_regex, err, sizeof(err));
2136                                 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
2137                                 return -EINVAL;
2138                         }
2139                         sort__has_parent = 1;
2140                 } else if (sd->entry == &sort_sym) {
2141                         sort__has_sym = 1;
2142                         /*
2143                          * perf diff displays the performance difference amongst
2144                          * two or more perf.data files. Those files could come
2145                          * from different binaries. So we should not compare
2146                          * their ips, but the name of symbol.
2147                          */
2148                         if (sort__mode == SORT_MODE__DIFF)
2149                                 sd->entry->se_collapse = sort__sym_sort;
2150
2151                 } else if (sd->entry == &sort_dso) {
2152                         sort__has_dso = 1;
2153                 } else if (sd->entry == &sort_socket) {
2154                         sort__has_socket = 1;
2155                 } else if (sd->entry == &sort_thread) {
2156                         sort__has_thread = 1;
2157                 }
2158
2159                 return __sort_dimension__add(sd);
2160         }
2161
2162         for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
2163                 struct hpp_dimension *hd = &hpp_sort_dimensions[i];
2164
2165                 if (strncasecmp(tok, hd->name, strlen(tok)))
2166                         continue;
2167
2168                 return __hpp_dimension__add(hd);
2169         }
2170
2171         for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
2172                 struct sort_dimension *sd = &bstack_sort_dimensions[i];
2173
2174                 if (strncasecmp(tok, sd->name, strlen(tok)))
2175                         continue;
2176
2177                 if (sort__mode != SORT_MODE__BRANCH)
2178                         return -EINVAL;
2179
2180                 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
2181                         sort__has_sym = 1;
2182
2183                 __sort_dimension__add(sd);
2184                 return 0;
2185         }
2186
2187         for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
2188                 struct sort_dimension *sd = &memory_sort_dimensions[i];
2189
2190                 if (strncasecmp(tok, sd->name, strlen(tok)))
2191                         continue;
2192
2193                 if (sort__mode != SORT_MODE__MEMORY)
2194                         return -EINVAL;
2195
2196                 if (sd->entry == &sort_mem_daddr_sym)
2197                         sort__has_sym = 1;
2198
2199                 __sort_dimension__add(sd);
2200                 return 0;
2201         }
2202
2203         if (!add_dynamic_entry(evlist, tok))
2204                 return 0;
2205
2206         return -ESRCH;
2207 }
2208
2209 static int setup_sort_list(char *str, struct perf_evlist *evlist)
2210 {
2211         char *tmp, *tok;
2212         int ret = 0;
2213
2214         for (tok = strtok_r(str, ", ", &tmp);
2215                         tok; tok = strtok_r(NULL, ", ", &tmp)) {
2216                 ret = sort_dimension__add(tok, evlist);
2217                 if (ret == -EINVAL) {
2218                         error("Invalid --sort key: `%s'", tok);
2219                         break;
2220                 } else if (ret == -ESRCH) {
2221                         error("Unknown --sort key: `%s'", tok);
2222                         break;
2223                 }
2224         }
2225
2226         return ret;
2227 }
2228
2229 static const char *get_default_sort_order(struct perf_evlist *evlist)
2230 {
2231         const char *default_sort_orders[] = {
2232                 default_sort_order,
2233                 default_branch_sort_order,
2234                 default_mem_sort_order,
2235                 default_top_sort_order,
2236                 default_diff_sort_order,
2237                 default_tracepoint_sort_order,
2238         };
2239         bool use_trace = true;
2240         struct perf_evsel *evsel;
2241
2242         BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
2243
2244         if (evlist == NULL)
2245                 goto out_no_evlist;
2246
2247         evlist__for_each(evlist, evsel) {
2248                 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2249                         use_trace = false;
2250                         break;
2251                 }
2252         }
2253
2254         if (use_trace) {
2255                 sort__mode = SORT_MODE__TRACEPOINT;
2256                 if (symbol_conf.raw_trace)
2257                         return "trace_fields";
2258         }
2259 out_no_evlist:
2260         return default_sort_orders[sort__mode];
2261 }
2262
2263 static int setup_sort_order(struct perf_evlist *evlist)
2264 {
2265         char *new_sort_order;
2266
2267         /*
2268          * Append '+'-prefixed sort order to the default sort
2269          * order string.
2270          */
2271         if (!sort_order || is_strict_order(sort_order))
2272                 return 0;
2273
2274         if (sort_order[1] == '\0') {
2275                 error("Invalid --sort key: `+'");
2276                 return -EINVAL;
2277         }
2278
2279         /*
2280          * We allocate new sort_order string, but we never free it,
2281          * because it's checked over the rest of the code.
2282          */
2283         if (asprintf(&new_sort_order, "%s,%s",
2284                      get_default_sort_order(evlist), sort_order + 1) < 0) {
2285                 error("Not enough memory to set up --sort");
2286                 return -ENOMEM;
2287         }
2288
2289         sort_order = new_sort_order;
2290         return 0;
2291 }
2292
2293 /*
2294  * Adds 'pre,' prefix into 'str' is 'pre' is
2295  * not already part of 'str'.
2296  */
2297 static char *prefix_if_not_in(const char *pre, char *str)
2298 {
2299         char *n;
2300
2301         if (!str || strstr(str, pre))
2302                 return str;
2303
2304         if (asprintf(&n, "%s,%s", pre, str) < 0)
2305                 return NULL;
2306
2307         free(str);
2308         return n;
2309 }
2310
2311 static char *setup_overhead(char *keys)
2312 {
2313         keys = prefix_if_not_in("overhead", keys);
2314
2315         if (symbol_conf.cumulate_callchain)
2316                 keys = prefix_if_not_in("overhead_children", keys);
2317
2318         return keys;
2319 }
2320
2321 static int __setup_sorting(struct perf_evlist *evlist)
2322 {
2323         char *str;
2324         const char *sort_keys;
2325         int ret = 0;
2326
2327         ret = setup_sort_order(evlist);
2328         if (ret)
2329                 return ret;
2330
2331         sort_keys = sort_order;
2332         if (sort_keys == NULL) {
2333                 if (is_strict_order(field_order)) {
2334                         /*
2335                          * If user specified field order but no sort order,
2336                          * we'll honor it and not add default sort orders.
2337                          */
2338                         return 0;
2339                 }
2340
2341                 sort_keys = get_default_sort_order(evlist);
2342         }
2343
2344         str = strdup(sort_keys);
2345         if (str == NULL) {
2346                 error("Not enough memory to setup sort keys");
2347                 return -ENOMEM;
2348         }
2349
2350         /*
2351          * Prepend overhead fields for backward compatibility.
2352          */
2353         if (!is_strict_order(field_order)) {
2354                 str = setup_overhead(str);
2355                 if (str == NULL) {
2356                         error("Not enough memory to setup overhead keys");
2357                         return -ENOMEM;
2358                 }
2359         }
2360
2361         ret = setup_sort_list(str, evlist);
2362
2363         free(str);
2364         return ret;
2365 }
2366
2367 void perf_hpp__set_elide(int idx, bool elide)
2368 {
2369         struct perf_hpp_fmt *fmt;
2370         struct hpp_sort_entry *hse;
2371
2372         perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
2373                 if (!perf_hpp__is_sort_entry(fmt))
2374                         continue;
2375
2376                 hse = container_of(fmt, struct hpp_sort_entry, hpp);
2377                 if (hse->se->se_width_idx == idx) {
2378                         fmt->elide = elide;
2379                         break;
2380                 }
2381         }
2382 }
2383
2384 static bool __get_elide(struct strlist *list, const char *list_name, FILE *fp)
2385 {
2386         if (list && strlist__nr_entries(list) == 1) {
2387                 if (fp != NULL)
2388                         fprintf(fp, "# %s: %s\n", list_name,
2389                                 strlist__entry(list, 0)->s);
2390                 return true;
2391         }
2392         return false;
2393 }
2394
2395 static bool get_elide(int idx, FILE *output)
2396 {
2397         switch (idx) {
2398         case HISTC_SYMBOL:
2399                 return __get_elide(symbol_conf.sym_list, "symbol", output);
2400         case HISTC_DSO:
2401                 return __get_elide(symbol_conf.dso_list, "dso", output);
2402         case HISTC_COMM:
2403                 return __get_elide(symbol_conf.comm_list, "comm", output);
2404         default:
2405                 break;
2406         }
2407
2408         if (sort__mode != SORT_MODE__BRANCH)
2409                 return false;
2410
2411         switch (idx) {
2412         case HISTC_SYMBOL_FROM:
2413                 return __get_elide(symbol_conf.sym_from_list, "sym_from", output);
2414         case HISTC_SYMBOL_TO:
2415                 return __get_elide(symbol_conf.sym_to_list, "sym_to", output);
2416         case HISTC_DSO_FROM:
2417                 return __get_elide(symbol_conf.dso_from_list, "dso_from", output);
2418         case HISTC_DSO_TO:
2419                 return __get_elide(symbol_conf.dso_to_list, "dso_to", output);
2420         default:
2421                 break;
2422         }
2423
2424         return false;
2425 }
2426
2427 void sort__setup_elide(FILE *output)
2428 {
2429         struct perf_hpp_fmt *fmt;
2430         struct hpp_sort_entry *hse;
2431
2432         perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
2433                 if (!perf_hpp__is_sort_entry(fmt))
2434                         continue;
2435
2436                 hse = container_of(fmt, struct hpp_sort_entry, hpp);
2437                 fmt->elide = get_elide(hse->se->se_width_idx, output);
2438         }
2439
2440         /*
2441          * It makes no sense to elide all of sort entries.
2442          * Just revert them to show up again.
2443          */
2444         perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
2445                 if (!perf_hpp__is_sort_entry(fmt))
2446                         continue;
2447
2448                 if (!fmt->elide)
2449                         return;
2450         }
2451
2452         perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
2453                 if (!perf_hpp__is_sort_entry(fmt))
2454                         continue;
2455
2456                 fmt->elide = false;
2457         }
2458 }
2459
2460 static int output_field_add(struct perf_hpp_list *list, char *tok)
2461 {
2462         unsigned int i;
2463
2464         for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
2465                 struct sort_dimension *sd = &common_sort_dimensions[i];
2466
2467                 if (strncasecmp(tok, sd->name, strlen(tok)))
2468                         continue;
2469
2470                 return __sort_dimension__add_output(list, sd);
2471         }
2472
2473         for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
2474                 struct hpp_dimension *hd = &hpp_sort_dimensions[i];
2475
2476                 if (strncasecmp(tok, hd->name, strlen(tok)))
2477                         continue;
2478
2479                 return __hpp_dimension__add_output(list, hd);
2480         }
2481
2482         for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
2483                 struct sort_dimension *sd = &bstack_sort_dimensions[i];
2484
2485                 if (strncasecmp(tok, sd->name, strlen(tok)))
2486                         continue;
2487
2488                 return __sort_dimension__add_output(list, sd);
2489         }
2490
2491         for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
2492                 struct sort_dimension *sd = &memory_sort_dimensions[i];
2493
2494                 if (strncasecmp(tok, sd->name, strlen(tok)))
2495                         continue;
2496
2497                 return __sort_dimension__add_output(list, sd);
2498         }
2499
2500         return -ESRCH;
2501 }
2502
2503 static int setup_output_list(struct perf_hpp_list *list, char *str)
2504 {
2505         char *tmp, *tok;
2506         int ret = 0;
2507
2508         for (tok = strtok_r(str, ", ", &tmp);
2509                         tok; tok = strtok_r(NULL, ", ", &tmp)) {
2510                 ret = output_field_add(list, tok);
2511                 if (ret == -EINVAL) {
2512                         error("Invalid --fields key: `%s'", tok);
2513                         break;
2514                 } else if (ret == -ESRCH) {
2515                         error("Unknown --fields key: `%s'", tok);
2516                         break;
2517                 }
2518         }
2519
2520         return ret;
2521 }
2522
2523 static void reset_dimensions(void)
2524 {
2525         unsigned int i;
2526
2527         for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++)
2528                 common_sort_dimensions[i].taken = 0;
2529
2530         for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++)
2531                 hpp_sort_dimensions[i].taken = 0;
2532
2533         for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++)
2534                 bstack_sort_dimensions[i].taken = 0;
2535
2536         for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++)
2537                 memory_sort_dimensions[i].taken = 0;
2538 }
2539
2540 bool is_strict_order(const char *order)
2541 {
2542         return order && (*order != '+');
2543 }
2544
2545 static int __setup_output_field(void)
2546 {
2547         char *str, *strp;
2548         int ret = -EINVAL;
2549
2550         if (field_order == NULL)
2551                 return 0;
2552
2553         strp = str = strdup(field_order);
2554         if (str == NULL) {
2555                 error("Not enough memory to setup output fields");
2556                 return -ENOMEM;
2557         }
2558
2559         if (!is_strict_order(field_order))
2560                 strp++;
2561
2562         if (!strlen(strp)) {
2563                 error("Invalid --fields key: `+'");
2564                 goto out;
2565         }
2566
2567         ret = setup_output_list(&perf_hpp_list, strp);
2568
2569 out:
2570         free(str);
2571         return ret;
2572 }
2573
2574 int setup_sorting(struct perf_evlist *evlist)
2575 {
2576         int err;
2577
2578         err = __setup_sorting(evlist);
2579         if (err < 0)
2580                 return err;
2581
2582         if (parent_pattern != default_parent_pattern) {
2583                 err = sort_dimension__add("parent", evlist);
2584                 if (err < 0)
2585                         return err;
2586         }
2587
2588         reset_dimensions();
2589
2590         /*
2591          * perf diff doesn't use default hpp output fields.
2592          */
2593         if (sort__mode != SORT_MODE__DIFF)
2594                 perf_hpp__init();
2595
2596         err = __setup_output_field();
2597         if (err < 0)
2598                 return err;
2599
2600         /* copy sort keys to output fields */
2601         perf_hpp__setup_output_field(&perf_hpp_list);
2602         /* and then copy output fields to sort keys */
2603         perf_hpp__append_sort_keys(&perf_hpp_list);
2604
2605         return 0;
2606 }
2607
2608 void reset_output_field(void)
2609 {
2610         sort__need_collapse = 0;
2611         sort__has_parent = 0;
2612         sort__has_sym = 0;
2613         sort__has_dso = 0;
2614
2615         field_order = NULL;
2616         sort_order = NULL;
2617
2618         reset_dimensions();
2619         perf_hpp__reset_output_field(&perf_hpp_list);
2620 }