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