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