]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - tools/perf/util/sort.c
Merge branch 'perf/urgent' into perf/core, to resolve a conflict
[karo-tx-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
8 regex_t         parent_regex;
9 const char      default_parent_pattern[] = "^sys_|^do_page_fault";
10 const char      *parent_pattern = default_parent_pattern;
11 const char      default_sort_order[] = "comm,dso,symbol";
12 const char      default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles";
13 const char      default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
14 const char      default_top_sort_order[] = "dso,symbol";
15 const char      default_diff_sort_order[] = "dso,symbol";
16 const char      *sort_order;
17 const char      *field_order;
18 regex_t         ignore_callees_regex;
19 int             have_ignore_callees = 0;
20 int             sort__need_collapse = 0;
21 int             sort__has_parent = 0;
22 int             sort__has_sym = 0;
23 int             sort__has_dso = 0;
24 int             sort__has_socket = 0;
25 enum sort_mode  sort__mode = SORT_MODE__NORMAL;
26
27
28 static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
29 {
30         int n;
31         va_list ap;
32
33         va_start(ap, fmt);
34         n = vsnprintf(bf, size, fmt, ap);
35         if (symbol_conf.field_sep && n > 0) {
36                 char *sep = bf;
37
38                 while (1) {
39                         sep = strchr(sep, *symbol_conf.field_sep);
40                         if (sep == NULL)
41                                 break;
42                         *sep = '.';
43                 }
44         }
45         va_end(ap);
46
47         if (n >= (int)size)
48                 return size - 1;
49         return n;
50 }
51
52 static int64_t cmp_null(const void *l, const void *r)
53 {
54         if (!l && !r)
55                 return 0;
56         else if (!l)
57                 return -1;
58         else
59                 return 1;
60 }
61
62 /* --sort pid */
63
64 static int64_t
65 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
66 {
67         return right->thread->tid - left->thread->tid;
68 }
69
70 static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
71                                        size_t size, unsigned int width)
72 {
73         const char *comm = thread__comm_str(he->thread);
74
75         width = max(7U, width) - 6;
76         return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
77                                width, width, comm ?: "");
78 }
79
80 struct sort_entry sort_thread = {
81         .se_header      = "  Pid:Command",
82         .se_cmp         = sort__thread_cmp,
83         .se_snprintf    = hist_entry__thread_snprintf,
84         .se_width_idx   = HISTC_THREAD,
85 };
86
87 /* --sort comm */
88
89 static int64_t
90 sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
91 {
92         /* Compare the addr that should be unique among comm */
93         return strcmp(comm__str(right->comm), comm__str(left->comm));
94 }
95
96 static int64_t
97 sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
98 {
99         /* Compare the addr that should be unique among comm */
100         return strcmp(comm__str(right->comm), comm__str(left->comm));
101 }
102
103 static int64_t
104 sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
105 {
106         return strcmp(comm__str(right->comm), comm__str(left->comm));
107 }
108
109 static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
110                                      size_t size, unsigned int width)
111 {
112         return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm));
113 }
114
115 struct sort_entry sort_comm = {
116         .se_header      = "Command",
117         .se_cmp         = sort__comm_cmp,
118         .se_collapse    = sort__comm_collapse,
119         .se_sort        = sort__comm_sort,
120         .se_snprintf    = hist_entry__comm_snprintf,
121         .se_width_idx   = HISTC_COMM,
122 };
123
124 /* --sort dso */
125
126 static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
127 {
128         struct dso *dso_l = map_l ? map_l->dso : NULL;
129         struct dso *dso_r = map_r ? map_r->dso : NULL;
130         const char *dso_name_l, *dso_name_r;
131
132         if (!dso_l || !dso_r)
133                 return cmp_null(dso_r, dso_l);
134
135         if (verbose) {
136                 dso_name_l = dso_l->long_name;
137                 dso_name_r = dso_r->long_name;
138         } else {
139                 dso_name_l = dso_l->short_name;
140                 dso_name_r = dso_r->short_name;
141         }
142
143         return strcmp(dso_name_l, dso_name_r);
144 }
145
146 static int64_t
147 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
148 {
149         return _sort__dso_cmp(right->ms.map, left->ms.map);
150 }
151
152 static int _hist_entry__dso_snprintf(struct map *map, char *bf,
153                                      size_t size, unsigned int width)
154 {
155         if (map && map->dso) {
156                 const char *dso_name = !verbose ? map->dso->short_name :
157                         map->dso->long_name;
158                 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
159         }
160
161         return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]");
162 }
163
164 static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
165                                     size_t size, unsigned int width)
166 {
167         return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
168 }
169
170 struct sort_entry sort_dso = {
171         .se_header      = "Shared Object",
172         .se_cmp         = sort__dso_cmp,
173         .se_snprintf    = hist_entry__dso_snprintf,
174         .se_width_idx   = HISTC_DSO,
175 };
176
177 /* --sort symbol */
178
179 static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
180 {
181         return (int64_t)(right_ip - left_ip);
182 }
183
184 static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
185 {
186         if (!sym_l || !sym_r)
187                 return cmp_null(sym_l, sym_r);
188
189         if (sym_l == sym_r)
190                 return 0;
191
192         if (sym_l->start != sym_r->start)
193                 return (int64_t)(sym_r->start - sym_l->start);
194
195         return (int64_t)(sym_r->end - sym_l->end);
196 }
197
198 static int64_t
199 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
200 {
201         int64_t ret;
202
203         if (!left->ms.sym && !right->ms.sym)
204                 return _sort__addr_cmp(left->ip, right->ip);
205
206         /*
207          * comparing symbol address alone is not enough since it's a
208          * relative address within a dso.
209          */
210         if (!sort__has_dso) {
211                 ret = sort__dso_cmp(left, right);
212                 if (ret != 0)
213                         return ret;
214         }
215
216         return _sort__sym_cmp(left->ms.sym, right->ms.sym);
217 }
218
219 static int64_t
220 sort__sym_sort(struct hist_entry *left, struct hist_entry *right)
221 {
222         if (!left->ms.sym || !right->ms.sym)
223                 return cmp_null(left->ms.sym, right->ms.sym);
224
225         return strcmp(right->ms.sym->name, left->ms.sym->name);
226 }
227
228 static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
229                                      u64 ip, char level, char *bf, size_t size,
230                                      unsigned int width)
231 {
232         size_t ret = 0;
233
234         if (verbose) {
235                 char o = map ? dso__symtab_origin(map->dso) : '!';
236                 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
237                                        BITS_PER_LONG / 4 + 2, ip, o);
238         }
239
240         ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
241         if (sym && map) {
242                 if (map->type == MAP__VARIABLE) {
243                         ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
244                         ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
245                                         ip - map->unmap_ip(map, sym->start));
246                         ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
247                                        width - ret, "");
248                 } else {
249                         ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
250                                                width - ret,
251                                                sym->name);
252                 }
253         } else {
254                 size_t len = BITS_PER_LONG / 4;
255                 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
256                                        len, ip);
257                 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
258                                        width - ret, "");
259         }
260
261         if (ret > width)
262                 bf[width] = '\0';
263
264         return width;
265 }
266
267 static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
268                                     size_t size, unsigned int width)
269 {
270         return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
271                                          he->level, bf, size, width);
272 }
273
274 struct sort_entry sort_sym = {
275         .se_header      = "Symbol",
276         .se_cmp         = sort__sym_cmp,
277         .se_sort        = sort__sym_sort,
278         .se_snprintf    = hist_entry__sym_snprintf,
279         .se_width_idx   = HISTC_SYMBOL,
280 };
281
282 /* --sort srcline */
283
284 static int64_t
285 sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
286 {
287         if (!left->srcline) {
288                 if (!left->ms.map)
289                         left->srcline = SRCLINE_UNKNOWN;
290                 else {
291                         struct map *map = left->ms.map;
292                         left->srcline = get_srcline(map->dso,
293                                            map__rip_2objdump(map, left->ip),
294                                                     left->ms.sym, true);
295                 }
296         }
297         if (!right->srcline) {
298                 if (!right->ms.map)
299                         right->srcline = SRCLINE_UNKNOWN;
300                 else {
301                         struct map *map = right->ms.map;
302                         right->srcline = get_srcline(map->dso,
303                                              map__rip_2objdump(map, right->ip),
304                                                      right->ms.sym, true);
305                 }
306         }
307         return strcmp(right->srcline, left->srcline);
308 }
309
310 static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
311                                         size_t size, unsigned int width)
312 {
313         return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline);
314 }
315
316 struct sort_entry sort_srcline = {
317         .se_header      = "Source:Line",
318         .se_cmp         = sort__srcline_cmp,
319         .se_snprintf    = hist_entry__srcline_snprintf,
320         .se_width_idx   = HISTC_SRCLINE,
321 };
322
323 /* --sort srcfile */
324
325 static char no_srcfile[1];
326
327 static char *get_srcfile(struct hist_entry *e)
328 {
329         char *sf, *p;
330         struct map *map = e->ms.map;
331
332         sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
333                          e->ms.sym, false, true);
334         if (!strcmp(sf, SRCLINE_UNKNOWN))
335                 return no_srcfile;
336         p = strchr(sf, ':');
337         if (p && *sf) {
338                 *p = 0;
339                 return sf;
340         }
341         free(sf);
342         return no_srcfile;
343 }
344
345 static int64_t
346 sort__srcfile_cmp(struct hist_entry *left, struct hist_entry *right)
347 {
348         if (!left->srcfile) {
349                 if (!left->ms.map)
350                         left->srcfile = no_srcfile;
351                 else
352                         left->srcfile = get_srcfile(left);
353         }
354         if (!right->srcfile) {
355                 if (!right->ms.map)
356                         right->srcfile = no_srcfile;
357                 else
358                         right->srcfile = 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         return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcfile);
367 }
368
369 struct sort_entry sort_srcfile = {
370         .se_header      = "Source File",
371         .se_cmp         = sort__srcfile_cmp,
372         .se_snprintf    = hist_entry__srcfile_snprintf,
373         .se_width_idx   = HISTC_SRCFILE,
374 };
375
376 /* --sort parent */
377
378 static int64_t
379 sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
380 {
381         struct symbol *sym_l = left->parent;
382         struct symbol *sym_r = right->parent;
383
384         if (!sym_l || !sym_r)
385                 return cmp_null(sym_l, sym_r);
386
387         return strcmp(sym_r->name, sym_l->name);
388 }
389
390 static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
391                                        size_t size, unsigned int width)
392 {
393         return repsep_snprintf(bf, size, "%-*.*s", width, width,
394                               he->parent ? he->parent->name : "[other]");
395 }
396
397 struct sort_entry sort_parent = {
398         .se_header      = "Parent symbol",
399         .se_cmp         = sort__parent_cmp,
400         .se_snprintf    = hist_entry__parent_snprintf,
401         .se_width_idx   = HISTC_PARENT,
402 };
403
404 /* --sort cpu */
405
406 static int64_t
407 sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
408 {
409         return right->cpu - left->cpu;
410 }
411
412 static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
413                                     size_t size, unsigned int width)
414 {
415         return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu);
416 }
417
418 struct sort_entry sort_cpu = {
419         .se_header      = "CPU",
420         .se_cmp         = sort__cpu_cmp,
421         .se_snprintf    = hist_entry__cpu_snprintf,
422         .se_width_idx   = HISTC_CPU,
423 };
424
425 /* --sort socket */
426
427 static int64_t
428 sort__socket_cmp(struct hist_entry *left, struct hist_entry *right)
429 {
430         return right->socket - left->socket;
431 }
432
433 static int hist_entry__socket_snprintf(struct hist_entry *he, char *bf,
434                                     size_t size, unsigned int width)
435 {
436         return repsep_snprintf(bf, size, "%*.*d", width, width-3, he->socket);
437 }
438
439 struct sort_entry sort_socket = {
440         .se_header      = "Socket",
441         .se_cmp         = sort__socket_cmp,
442         .se_snprintf    = hist_entry__socket_snprintf,
443         .se_width_idx   = HISTC_SOCKET,
444 };
445
446 /* sort keys for branch stacks */
447
448 static int64_t
449 sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
450 {
451         if (!left->branch_info || !right->branch_info)
452                 return cmp_null(left->branch_info, right->branch_info);
453
454         return _sort__dso_cmp(left->branch_info->from.map,
455                               right->branch_info->from.map);
456 }
457
458 static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
459                                     size_t size, unsigned int width)
460 {
461         if (he->branch_info)
462                 return _hist_entry__dso_snprintf(he->branch_info->from.map,
463                                                  bf, size, width);
464         else
465                 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
466 }
467
468 static int64_t
469 sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
470 {
471         if (!left->branch_info || !right->branch_info)
472                 return cmp_null(left->branch_info, right->branch_info);
473
474         return _sort__dso_cmp(left->branch_info->to.map,
475                               right->branch_info->to.map);
476 }
477
478 static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
479                                        size_t size, unsigned int width)
480 {
481         if (he->branch_info)
482                 return _hist_entry__dso_snprintf(he->branch_info->to.map,
483                                                  bf, size, width);
484         else
485                 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
486 }
487
488 static int64_t
489 sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
490 {
491         struct addr_map_symbol *from_l = &left->branch_info->from;
492         struct addr_map_symbol *from_r = &right->branch_info->from;
493
494         if (!left->branch_info || !right->branch_info)
495                 return cmp_null(left->branch_info, right->branch_info);
496
497         from_l = &left->branch_info->from;
498         from_r = &right->branch_info->from;
499
500         if (!from_l->sym && !from_r->sym)
501                 return _sort__addr_cmp(from_l->addr, from_r->addr);
502
503         return _sort__sym_cmp(from_l->sym, from_r->sym);
504 }
505
506 static int64_t
507 sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
508 {
509         struct addr_map_symbol *to_l, *to_r;
510
511         if (!left->branch_info || !right->branch_info)
512                 return cmp_null(left->branch_info, right->branch_info);
513
514         to_l = &left->branch_info->to;
515         to_r = &right->branch_info->to;
516
517         if (!to_l->sym && !to_r->sym)
518                 return _sort__addr_cmp(to_l->addr, to_r->addr);
519
520         return _sort__sym_cmp(to_l->sym, to_r->sym);
521 }
522
523 static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
524                                          size_t size, unsigned int width)
525 {
526         if (he->branch_info) {
527                 struct addr_map_symbol *from = &he->branch_info->from;
528
529                 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
530                                                  he->level, bf, size, width);
531         }
532
533         return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
534 }
535
536 static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
537                                        size_t size, unsigned int width)
538 {
539         if (he->branch_info) {
540                 struct addr_map_symbol *to = &he->branch_info->to;
541
542                 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
543                                                  he->level, bf, size, width);
544         }
545
546         return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
547 }
548
549 struct sort_entry sort_dso_from = {
550         .se_header      = "Source Shared Object",
551         .se_cmp         = sort__dso_from_cmp,
552         .se_snprintf    = hist_entry__dso_from_snprintf,
553         .se_width_idx   = HISTC_DSO_FROM,
554 };
555
556 struct sort_entry sort_dso_to = {
557         .se_header      = "Target Shared Object",
558         .se_cmp         = sort__dso_to_cmp,
559         .se_snprintf    = hist_entry__dso_to_snprintf,
560         .se_width_idx   = HISTC_DSO_TO,
561 };
562
563 struct sort_entry sort_sym_from = {
564         .se_header      = "Source Symbol",
565         .se_cmp         = sort__sym_from_cmp,
566         .se_snprintf    = hist_entry__sym_from_snprintf,
567         .se_width_idx   = HISTC_SYMBOL_FROM,
568 };
569
570 struct sort_entry sort_sym_to = {
571         .se_header      = "Target Symbol",
572         .se_cmp         = sort__sym_to_cmp,
573         .se_snprintf    = hist_entry__sym_to_snprintf,
574         .se_width_idx   = HISTC_SYMBOL_TO,
575 };
576
577 static int64_t
578 sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
579 {
580         unsigned char mp, p;
581
582         if (!left->branch_info || !right->branch_info)
583                 return cmp_null(left->branch_info, right->branch_info);
584
585         mp = left->branch_info->flags.mispred != right->branch_info->flags.mispred;
586         p  = left->branch_info->flags.predicted != right->branch_info->flags.predicted;
587         return mp || p;
588 }
589
590 static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
591                                     size_t size, unsigned int width){
592         static const char *out = "N/A";
593
594         if (he->branch_info) {
595                 if (he->branch_info->flags.predicted)
596                         out = "N";
597                 else if (he->branch_info->flags.mispred)
598                         out = "Y";
599         }
600
601         return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
602 }
603
604 static int64_t
605 sort__cycles_cmp(struct hist_entry *left, struct hist_entry *right)
606 {
607         return left->branch_info->flags.cycles -
608                 right->branch_info->flags.cycles;
609 }
610
611 static int hist_entry__cycles_snprintf(struct hist_entry *he, char *bf,
612                                     size_t size, unsigned int width)
613 {
614         if (he->branch_info->flags.cycles == 0)
615                 return repsep_snprintf(bf, size, "%-*s", width, "-");
616         return repsep_snprintf(bf, size, "%-*hd", width,
617                                he->branch_info->flags.cycles);
618 }
619
620 struct sort_entry sort_cycles = {
621         .se_header      = "Basic Block Cycles",
622         .se_cmp         = sort__cycles_cmp,
623         .se_snprintf    = hist_entry__cycles_snprintf,
624         .se_width_idx   = HISTC_CYCLES,
625 };
626
627 /* --sort daddr_sym */
628 static int64_t
629 sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
630 {
631         uint64_t l = 0, r = 0;
632
633         if (left->mem_info)
634                 l = left->mem_info->daddr.addr;
635         if (right->mem_info)
636                 r = right->mem_info->daddr.addr;
637
638         return (int64_t)(r - l);
639 }
640
641 static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
642                                     size_t size, unsigned int width)
643 {
644         uint64_t addr = 0;
645         struct map *map = NULL;
646         struct symbol *sym = NULL;
647
648         if (he->mem_info) {
649                 addr = he->mem_info->daddr.addr;
650                 map = he->mem_info->daddr.map;
651                 sym = he->mem_info->daddr.sym;
652         }
653         return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
654                                          width);
655 }
656
657 static int64_t
658 sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
659 {
660         struct map *map_l = NULL;
661         struct map *map_r = NULL;
662
663         if (left->mem_info)
664                 map_l = left->mem_info->daddr.map;
665         if (right->mem_info)
666                 map_r = right->mem_info->daddr.map;
667
668         return _sort__dso_cmp(map_l, map_r);
669 }
670
671 static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
672                                     size_t size, unsigned int width)
673 {
674         struct map *map = NULL;
675
676         if (he->mem_info)
677                 map = he->mem_info->daddr.map;
678
679         return _hist_entry__dso_snprintf(map, bf, size, width);
680 }
681
682 static int64_t
683 sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
684 {
685         union perf_mem_data_src data_src_l;
686         union perf_mem_data_src data_src_r;
687
688         if (left->mem_info)
689                 data_src_l = left->mem_info->data_src;
690         else
691                 data_src_l.mem_lock = PERF_MEM_LOCK_NA;
692
693         if (right->mem_info)
694                 data_src_r = right->mem_info->data_src;
695         else
696                 data_src_r.mem_lock = PERF_MEM_LOCK_NA;
697
698         return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
699 }
700
701 static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
702                                     size_t size, unsigned int width)
703 {
704         const char *out;
705         u64 mask = PERF_MEM_LOCK_NA;
706
707         if (he->mem_info)
708                 mask = he->mem_info->data_src.mem_lock;
709
710         if (mask & PERF_MEM_LOCK_NA)
711                 out = "N/A";
712         else if (mask & PERF_MEM_LOCK_LOCKED)
713                 out = "Yes";
714         else
715                 out = "No";
716
717         return repsep_snprintf(bf, size, "%-*s", width, out);
718 }
719
720 static int64_t
721 sort__tlb_cmp(struct hist_entry *left, struct hist_entry *right)
722 {
723         union perf_mem_data_src data_src_l;
724         union perf_mem_data_src data_src_r;
725
726         if (left->mem_info)
727                 data_src_l = left->mem_info->data_src;
728         else
729                 data_src_l.mem_dtlb = PERF_MEM_TLB_NA;
730
731         if (right->mem_info)
732                 data_src_r = right->mem_info->data_src;
733         else
734                 data_src_r.mem_dtlb = PERF_MEM_TLB_NA;
735
736         return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb);
737 }
738
739 static const char * const tlb_access[] = {
740         "N/A",
741         "HIT",
742         "MISS",
743         "L1",
744         "L2",
745         "Walker",
746         "Fault",
747 };
748 #define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
749
750 static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
751                                     size_t size, unsigned int width)
752 {
753         char out[64];
754         size_t sz = sizeof(out) - 1; /* -1 for null termination */
755         size_t l = 0, i;
756         u64 m = PERF_MEM_TLB_NA;
757         u64 hit, miss;
758
759         out[0] = '\0';
760
761         if (he->mem_info)
762                 m = he->mem_info->data_src.mem_dtlb;
763
764         hit = m & PERF_MEM_TLB_HIT;
765         miss = m & PERF_MEM_TLB_MISS;
766
767         /* already taken care of */
768         m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
769
770         for (i = 0; m && i < NUM_TLB_ACCESS; i++, m >>= 1) {
771                 if (!(m & 0x1))
772                         continue;
773                 if (l) {
774                         strcat(out, " or ");
775                         l += 4;
776                 }
777                 strncat(out, tlb_access[i], sz - l);
778                 l += strlen(tlb_access[i]);
779         }
780         if (*out == '\0')
781                 strcpy(out, "N/A");
782         if (hit)
783                 strncat(out, " hit", sz - l);
784         if (miss)
785                 strncat(out, " miss", sz - l);
786
787         return repsep_snprintf(bf, size, "%-*s", width, out);
788 }
789
790 static int64_t
791 sort__lvl_cmp(struct hist_entry *left, struct hist_entry *right)
792 {
793         union perf_mem_data_src data_src_l;
794         union perf_mem_data_src data_src_r;
795
796         if (left->mem_info)
797                 data_src_l = left->mem_info->data_src;
798         else
799                 data_src_l.mem_lvl = PERF_MEM_LVL_NA;
800
801         if (right->mem_info)
802                 data_src_r = right->mem_info->data_src;
803         else
804                 data_src_r.mem_lvl = PERF_MEM_LVL_NA;
805
806         return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl);
807 }
808
809 static const char * const mem_lvl[] = {
810         "N/A",
811         "HIT",
812         "MISS",
813         "L1",
814         "LFB",
815         "L2",
816         "L3",
817         "Local RAM",
818         "Remote RAM (1 hop)",
819         "Remote RAM (2 hops)",
820         "Remote Cache (1 hop)",
821         "Remote Cache (2 hops)",
822         "I/O",
823         "Uncached",
824 };
825 #define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
826
827 static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
828                                     size_t size, unsigned int width)
829 {
830         char out[64];
831         size_t sz = sizeof(out) - 1; /* -1 for null termination */
832         size_t i, l = 0;
833         u64 m =  PERF_MEM_LVL_NA;
834         u64 hit, miss;
835
836         if (he->mem_info)
837                 m  = he->mem_info->data_src.mem_lvl;
838
839         out[0] = '\0';
840
841         hit = m & PERF_MEM_LVL_HIT;
842         miss = m & PERF_MEM_LVL_MISS;
843
844         /* already taken care of */
845         m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
846
847         for (i = 0; m && i < NUM_MEM_LVL; i++, m >>= 1) {
848                 if (!(m & 0x1))
849                         continue;
850                 if (l) {
851                         strcat(out, " or ");
852                         l += 4;
853                 }
854                 strncat(out, mem_lvl[i], sz - l);
855                 l += strlen(mem_lvl[i]);
856         }
857         if (*out == '\0')
858                 strcpy(out, "N/A");
859         if (hit)
860                 strncat(out, " hit", sz - l);
861         if (miss)
862                 strncat(out, " miss", sz - l);
863
864         return repsep_snprintf(bf, size, "%-*s", width, out);
865 }
866
867 static int64_t
868 sort__snoop_cmp(struct hist_entry *left, struct hist_entry *right)
869 {
870         union perf_mem_data_src data_src_l;
871         union perf_mem_data_src data_src_r;
872
873         if (left->mem_info)
874                 data_src_l = left->mem_info->data_src;
875         else
876                 data_src_l.mem_snoop = PERF_MEM_SNOOP_NA;
877
878         if (right->mem_info)
879                 data_src_r = right->mem_info->data_src;
880         else
881                 data_src_r.mem_snoop = PERF_MEM_SNOOP_NA;
882
883         return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop);
884 }
885
886 static const char * const snoop_access[] = {
887         "N/A",
888         "None",
889         "Miss",
890         "Hit",
891         "HitM",
892 };
893 #define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
894
895 static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
896                                     size_t size, unsigned int width)
897 {
898         char out[64];
899         size_t sz = sizeof(out) - 1; /* -1 for null termination */
900         size_t i, l = 0;
901         u64 m = PERF_MEM_SNOOP_NA;
902
903         out[0] = '\0';
904
905         if (he->mem_info)
906                 m = he->mem_info->data_src.mem_snoop;
907
908         for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
909                 if (!(m & 0x1))
910                         continue;
911                 if (l) {
912                         strcat(out, " or ");
913                         l += 4;
914                 }
915                 strncat(out, snoop_access[i], sz - l);
916                 l += strlen(snoop_access[i]);
917         }
918
919         if (*out == '\0')
920                 strcpy(out, "N/A");
921
922         return repsep_snprintf(bf, size, "%-*s", width, out);
923 }
924
925 static inline  u64 cl_address(u64 address)
926 {
927         /* return the cacheline of the address */
928         return (address & ~(cacheline_size - 1));
929 }
930
931 static int64_t
932 sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
933 {
934         u64 l, r;
935         struct map *l_map, *r_map;
936
937         if (!left->mem_info)  return -1;
938         if (!right->mem_info) return 1;
939
940         /* group event types together */
941         if (left->cpumode > right->cpumode) return -1;
942         if (left->cpumode < right->cpumode) return 1;
943
944         l_map = left->mem_info->daddr.map;
945         r_map = right->mem_info->daddr.map;
946
947         /* if both are NULL, jump to sort on al_addr instead */
948         if (!l_map && !r_map)
949                 goto addr;
950
951         if (!l_map) return -1;
952         if (!r_map) return 1;
953
954         if (l_map->maj > r_map->maj) return -1;
955         if (l_map->maj < r_map->maj) return 1;
956
957         if (l_map->min > r_map->min) return -1;
958         if (l_map->min < r_map->min) return 1;
959
960         if (l_map->ino > r_map->ino) return -1;
961         if (l_map->ino < r_map->ino) return 1;
962
963         if (l_map->ino_generation > r_map->ino_generation) return -1;
964         if (l_map->ino_generation < r_map->ino_generation) return 1;
965
966         /*
967          * Addresses with no major/minor numbers are assumed to be
968          * anonymous in userspace.  Sort those on pid then address.
969          *
970          * The kernel and non-zero major/minor mapped areas are
971          * assumed to be unity mapped.  Sort those on address.
972          */
973
974         if ((left->cpumode != PERF_RECORD_MISC_KERNEL) &&
975             (!(l_map->flags & MAP_SHARED)) &&
976             !l_map->maj && !l_map->min && !l_map->ino &&
977             !l_map->ino_generation) {
978                 /* userspace anonymous */
979
980                 if (left->thread->pid_ > right->thread->pid_) return -1;
981                 if (left->thread->pid_ < right->thread->pid_) return 1;
982         }
983
984 addr:
985         /* al_addr does all the right addr - start + offset calculations */
986         l = cl_address(left->mem_info->daddr.al_addr);
987         r = cl_address(right->mem_info->daddr.al_addr);
988
989         if (l > r) return -1;
990         if (l < r) return 1;
991
992         return 0;
993 }
994
995 static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
996                                           size_t size, unsigned int width)
997 {
998
999         uint64_t addr = 0;
1000         struct map *map = NULL;
1001         struct symbol *sym = NULL;
1002         char level = he->level;
1003
1004         if (he->mem_info) {
1005                 addr = cl_address(he->mem_info->daddr.al_addr);
1006                 map = he->mem_info->daddr.map;
1007                 sym = he->mem_info->daddr.sym;
1008
1009                 /* print [s] for shared data mmaps */
1010                 if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
1011                      map && (map->type == MAP__VARIABLE) &&
1012                     (map->flags & MAP_SHARED) &&
1013                     (map->maj || map->min || map->ino ||
1014                      map->ino_generation))
1015                         level = 's';
1016                 else if (!map)
1017                         level = 'X';
1018         }
1019         return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size,
1020                                          width);
1021 }
1022
1023 struct sort_entry sort_mispredict = {
1024         .se_header      = "Branch Mispredicted",
1025         .se_cmp         = sort__mispredict_cmp,
1026         .se_snprintf    = hist_entry__mispredict_snprintf,
1027         .se_width_idx   = HISTC_MISPREDICT,
1028 };
1029
1030 static u64 he_weight(struct hist_entry *he)
1031 {
1032         return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
1033 }
1034
1035 static int64_t
1036 sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
1037 {
1038         return he_weight(left) - he_weight(right);
1039 }
1040
1041 static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
1042                                     size_t size, unsigned int width)
1043 {
1044         return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
1045 }
1046
1047 struct sort_entry sort_local_weight = {
1048         .se_header      = "Local Weight",
1049         .se_cmp         = sort__local_weight_cmp,
1050         .se_snprintf    = hist_entry__local_weight_snprintf,
1051         .se_width_idx   = HISTC_LOCAL_WEIGHT,
1052 };
1053
1054 static int64_t
1055 sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
1056 {
1057         return left->stat.weight - right->stat.weight;
1058 }
1059
1060 static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
1061                                               size_t size, unsigned int width)
1062 {
1063         return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
1064 }
1065
1066 struct sort_entry sort_global_weight = {
1067         .se_header      = "Weight",
1068         .se_cmp         = sort__global_weight_cmp,
1069         .se_snprintf    = hist_entry__global_weight_snprintf,
1070         .se_width_idx   = HISTC_GLOBAL_WEIGHT,
1071 };
1072
1073 struct sort_entry sort_mem_daddr_sym = {
1074         .se_header      = "Data Symbol",
1075         .se_cmp         = sort__daddr_cmp,
1076         .se_snprintf    = hist_entry__daddr_snprintf,
1077         .se_width_idx   = HISTC_MEM_DADDR_SYMBOL,
1078 };
1079
1080 struct sort_entry sort_mem_daddr_dso = {
1081         .se_header      = "Data Object",
1082         .se_cmp         = sort__dso_daddr_cmp,
1083         .se_snprintf    = hist_entry__dso_daddr_snprintf,
1084         .se_width_idx   = HISTC_MEM_DADDR_SYMBOL,
1085 };
1086
1087 struct sort_entry sort_mem_locked = {
1088         .se_header      = "Locked",
1089         .se_cmp         = sort__locked_cmp,
1090         .se_snprintf    = hist_entry__locked_snprintf,
1091         .se_width_idx   = HISTC_MEM_LOCKED,
1092 };
1093
1094 struct sort_entry sort_mem_tlb = {
1095         .se_header      = "TLB access",
1096         .se_cmp         = sort__tlb_cmp,
1097         .se_snprintf    = hist_entry__tlb_snprintf,
1098         .se_width_idx   = HISTC_MEM_TLB,
1099 };
1100
1101 struct sort_entry sort_mem_lvl = {
1102         .se_header      = "Memory access",
1103         .se_cmp         = sort__lvl_cmp,
1104         .se_snprintf    = hist_entry__lvl_snprintf,
1105         .se_width_idx   = HISTC_MEM_LVL,
1106 };
1107
1108 struct sort_entry sort_mem_snoop = {
1109         .se_header      = "Snoop",
1110         .se_cmp         = sort__snoop_cmp,
1111         .se_snprintf    = hist_entry__snoop_snprintf,
1112         .se_width_idx   = HISTC_MEM_SNOOP,
1113 };
1114
1115 struct sort_entry sort_mem_dcacheline = {
1116         .se_header      = "Data Cacheline",
1117         .se_cmp         = sort__dcacheline_cmp,
1118         .se_snprintf    = hist_entry__dcacheline_snprintf,
1119         .se_width_idx   = HISTC_MEM_DCACHELINE,
1120 };
1121
1122 static int64_t
1123 sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
1124 {
1125         if (!left->branch_info || !right->branch_info)
1126                 return cmp_null(left->branch_info, right->branch_info);
1127
1128         return left->branch_info->flags.abort !=
1129                 right->branch_info->flags.abort;
1130 }
1131
1132 static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
1133                                     size_t size, unsigned int width)
1134 {
1135         static const char *out = "N/A";
1136
1137         if (he->branch_info) {
1138                 if (he->branch_info->flags.abort)
1139                         out = "A";
1140                 else
1141                         out = ".";
1142         }
1143
1144         return repsep_snprintf(bf, size, "%-*s", width, out);
1145 }
1146
1147 struct sort_entry sort_abort = {
1148         .se_header      = "Transaction abort",
1149         .se_cmp         = sort__abort_cmp,
1150         .se_snprintf    = hist_entry__abort_snprintf,
1151         .se_width_idx   = HISTC_ABORT,
1152 };
1153
1154 static int64_t
1155 sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
1156 {
1157         if (!left->branch_info || !right->branch_info)
1158                 return cmp_null(left->branch_info, right->branch_info);
1159
1160         return left->branch_info->flags.in_tx !=
1161                 right->branch_info->flags.in_tx;
1162 }
1163
1164 static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
1165                                     size_t size, unsigned int width)
1166 {
1167         static const char *out = "N/A";
1168
1169         if (he->branch_info) {
1170                 if (he->branch_info->flags.in_tx)
1171                         out = "T";
1172                 else
1173                         out = ".";
1174         }
1175
1176         return repsep_snprintf(bf, size, "%-*s", width, out);
1177 }
1178
1179 struct sort_entry sort_in_tx = {
1180         .se_header      = "Branch in transaction",
1181         .se_cmp         = sort__in_tx_cmp,
1182         .se_snprintf    = hist_entry__in_tx_snprintf,
1183         .se_width_idx   = HISTC_IN_TX,
1184 };
1185
1186 static int64_t
1187 sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
1188 {
1189         return left->transaction - right->transaction;
1190 }
1191
1192 static inline char *add_str(char *p, const char *str)
1193 {
1194         strcpy(p, str);
1195         return p + strlen(str);
1196 }
1197
1198 static struct txbit {
1199         unsigned flag;
1200         const char *name;
1201         int skip_for_len;
1202 } txbits[] = {
1203         { PERF_TXN_ELISION,        "EL ",        0 },
1204         { PERF_TXN_TRANSACTION,    "TX ",        1 },
1205         { PERF_TXN_SYNC,           "SYNC ",      1 },
1206         { PERF_TXN_ASYNC,          "ASYNC ",     0 },
1207         { PERF_TXN_RETRY,          "RETRY ",     0 },
1208         { PERF_TXN_CONFLICT,       "CON ",       0 },
1209         { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
1210         { PERF_TXN_CAPACITY_READ,  "CAP-READ ",  0 },
1211         { 0, NULL, 0 }
1212 };
1213
1214 int hist_entry__transaction_len(void)
1215 {
1216         int i;
1217         int len = 0;
1218
1219         for (i = 0; txbits[i].name; i++) {
1220                 if (!txbits[i].skip_for_len)
1221                         len += strlen(txbits[i].name);
1222         }
1223         len += 4; /* :XX<space> */
1224         return len;
1225 }
1226
1227 static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
1228                                             size_t size, unsigned int width)
1229 {
1230         u64 t = he->transaction;
1231         char buf[128];
1232         char *p = buf;
1233         int i;
1234
1235         buf[0] = 0;
1236         for (i = 0; txbits[i].name; i++)
1237                 if (txbits[i].flag & t)
1238                         p = add_str(p, txbits[i].name);
1239         if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
1240                 p = add_str(p, "NEITHER ");
1241         if (t & PERF_TXN_ABORT_MASK) {
1242                 sprintf(p, ":%" PRIx64,
1243                         (t & PERF_TXN_ABORT_MASK) >>
1244                         PERF_TXN_ABORT_SHIFT);
1245                 p += strlen(p);
1246         }
1247
1248         return repsep_snprintf(bf, size, "%-*s", width, buf);
1249 }
1250
1251 struct sort_entry sort_transaction = {
1252         .se_header      = "Transaction                ",
1253         .se_cmp         = sort__transaction_cmp,
1254         .se_snprintf    = hist_entry__transaction_snprintf,
1255         .se_width_idx   = HISTC_TRANSACTION,
1256 };
1257
1258 struct sort_dimension {
1259         const char              *name;
1260         struct sort_entry       *entry;
1261         int                     taken;
1262 };
1263
1264 #define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
1265
1266 static struct sort_dimension common_sort_dimensions[] = {
1267         DIM(SORT_PID, "pid", sort_thread),
1268         DIM(SORT_COMM, "comm", sort_comm),
1269         DIM(SORT_DSO, "dso", sort_dso),
1270         DIM(SORT_SYM, "symbol", sort_sym),
1271         DIM(SORT_PARENT, "parent", sort_parent),
1272         DIM(SORT_CPU, "cpu", sort_cpu),
1273         DIM(SORT_SOCKET, "socket", sort_socket),
1274         DIM(SORT_SRCLINE, "srcline", sort_srcline),
1275         DIM(SORT_SRCFILE, "srcfile", sort_srcfile),
1276         DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
1277         DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
1278         DIM(SORT_TRANSACTION, "transaction", sort_transaction),
1279 };
1280
1281 #undef DIM
1282
1283 #define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) }
1284
1285 static struct sort_dimension bstack_sort_dimensions[] = {
1286         DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
1287         DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
1288         DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
1289         DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
1290         DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
1291         DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1292         DIM(SORT_ABORT, "abort", sort_abort),
1293         DIM(SORT_CYCLES, "cycles", sort_cycles),
1294 };
1295
1296 #undef DIM
1297
1298 #define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
1299
1300 static struct sort_dimension memory_sort_dimensions[] = {
1301         DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
1302         DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
1303         DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
1304         DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
1305         DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1306         DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1307         DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
1308 };
1309
1310 #undef DIM
1311
1312 struct hpp_dimension {
1313         const char              *name;
1314         struct perf_hpp_fmt     *fmt;
1315         int                     taken;
1316 };
1317
1318 #define DIM(d, n) { .name = n, .fmt = &perf_hpp__format[d], }
1319
1320 static struct hpp_dimension hpp_sort_dimensions[] = {
1321         DIM(PERF_HPP__OVERHEAD, "overhead"),
1322         DIM(PERF_HPP__OVERHEAD_SYS, "overhead_sys"),
1323         DIM(PERF_HPP__OVERHEAD_US, "overhead_us"),
1324         DIM(PERF_HPP__OVERHEAD_GUEST_SYS, "overhead_guest_sys"),
1325         DIM(PERF_HPP__OVERHEAD_GUEST_US, "overhead_guest_us"),
1326         DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"),
1327         DIM(PERF_HPP__SAMPLES, "sample"),
1328         DIM(PERF_HPP__PERIOD, "period"),
1329 };
1330
1331 #undef DIM
1332
1333 struct hpp_sort_entry {
1334         struct perf_hpp_fmt hpp;
1335         struct sort_entry *se;
1336 };
1337
1338 bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1339 {
1340         struct hpp_sort_entry *hse_a;
1341         struct hpp_sort_entry *hse_b;
1342
1343         if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b))
1344                 return false;
1345
1346         hse_a = container_of(a, struct hpp_sort_entry, hpp);
1347         hse_b = container_of(b, struct hpp_sort_entry, hpp);
1348
1349         return hse_a->se == hse_b->se;
1350 }
1351
1352 void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1353 {
1354         struct hpp_sort_entry *hse;
1355
1356         if (!perf_hpp__is_sort_entry(fmt))
1357                 return;
1358
1359         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1360         hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name));
1361 }
1362
1363 static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1364                               struct perf_evsel *evsel)
1365 {
1366         struct hpp_sort_entry *hse;
1367         size_t len = fmt->user_len;
1368
1369         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1370
1371         if (!len)
1372                 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1373
1374         return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1375 }
1376
1377 static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1378                              struct perf_hpp *hpp __maybe_unused,
1379                              struct perf_evsel *evsel)
1380 {
1381         struct hpp_sort_entry *hse;
1382         size_t len = fmt->user_len;
1383
1384         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1385
1386         if (!len)
1387                 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1388
1389         return len;
1390 }
1391
1392 static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1393                              struct hist_entry *he)
1394 {
1395         struct hpp_sort_entry *hse;
1396         size_t len = fmt->user_len;
1397
1398         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1399
1400         if (!len)
1401                 len = hists__col_len(he->hists, hse->se->se_width_idx);
1402
1403         return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1404 }
1405
1406 static int64_t __sort__hpp_cmp(struct perf_hpp_fmt *fmt,
1407                                struct hist_entry *a, struct hist_entry *b)
1408 {
1409         struct hpp_sort_entry *hse;
1410
1411         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1412         return hse->se->se_cmp(a, b);
1413 }
1414
1415 static int64_t __sort__hpp_collapse(struct perf_hpp_fmt *fmt,
1416                                     struct hist_entry *a, struct hist_entry *b)
1417 {
1418         struct hpp_sort_entry *hse;
1419         int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
1420
1421         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1422         collapse_fn = hse->se->se_collapse ?: hse->se->se_cmp;
1423         return collapse_fn(a, b);
1424 }
1425
1426 static int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt,
1427                                 struct hist_entry *a, struct hist_entry *b)
1428 {
1429         struct hpp_sort_entry *hse;
1430         int64_t (*sort_fn)(struct hist_entry *, struct hist_entry *);
1431
1432         hse = container_of(fmt, struct hpp_sort_entry, hpp);
1433         sort_fn = hse->se->se_sort ?: hse->se->se_cmp;
1434         return sort_fn(a, b);
1435 }
1436
1437 static struct hpp_sort_entry *
1438 __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1439 {
1440         struct hpp_sort_entry *hse;
1441
1442         hse = malloc(sizeof(*hse));
1443         if (hse == NULL) {
1444                 pr_err("Memory allocation failed\n");
1445                 return NULL;
1446         }
1447
1448         hse->se = sd->entry;
1449         hse->hpp.name = sd->entry->se_header;
1450         hse->hpp.header = __sort__hpp_header;
1451         hse->hpp.width = __sort__hpp_width;
1452         hse->hpp.entry = __sort__hpp_entry;
1453         hse->hpp.color = NULL;
1454
1455         hse->hpp.cmp = __sort__hpp_cmp;
1456         hse->hpp.collapse = __sort__hpp_collapse;
1457         hse->hpp.sort = __sort__hpp_sort;
1458
1459         INIT_LIST_HEAD(&hse->hpp.list);
1460         INIT_LIST_HEAD(&hse->hpp.sort_list);
1461         hse->hpp.elide = false;
1462         hse->hpp.len = 0;
1463         hse->hpp.user_len = 0;
1464
1465         return hse;
1466 }
1467
1468 bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format)
1469 {
1470         return format->header == __sort__hpp_header;
1471 }
1472
1473 static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd)
1474 {
1475         struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
1476
1477         if (hse == NULL)
1478                 return -1;
1479
1480         perf_hpp__register_sort_field(&hse->hpp);
1481         return 0;
1482 }
1483
1484 static int __sort_dimension__add_hpp_output(struct sort_dimension *sd)
1485 {
1486         struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
1487
1488         if (hse == NULL)
1489                 return -1;
1490
1491         perf_hpp__column_register(&hse->hpp);
1492         return 0;
1493 }
1494
1495 static int __sort_dimension__add(struct sort_dimension *sd)
1496 {
1497         if (sd->taken)
1498                 return 0;
1499
1500         if (__sort_dimension__add_hpp_sort(sd) < 0)
1501                 return -1;
1502
1503         if (sd->entry->se_collapse)
1504                 sort__need_collapse = 1;
1505
1506         sd->taken = 1;
1507
1508         return 0;
1509 }
1510
1511 static int __hpp_dimension__add(struct hpp_dimension *hd)
1512 {
1513         if (!hd->taken) {
1514                 hd->taken = 1;
1515
1516                 perf_hpp__register_sort_field(hd->fmt);
1517         }
1518         return 0;
1519 }
1520
1521 static int __sort_dimension__add_output(struct sort_dimension *sd)
1522 {
1523         if (sd->taken)
1524                 return 0;
1525
1526         if (__sort_dimension__add_hpp_output(sd) < 0)
1527                 return -1;
1528
1529         sd->taken = 1;
1530         return 0;
1531 }
1532
1533 static int __hpp_dimension__add_output(struct hpp_dimension *hd)
1534 {
1535         if (!hd->taken) {
1536                 hd->taken = 1;
1537
1538                 perf_hpp__column_register(hd->fmt);
1539         }
1540         return 0;
1541 }
1542
1543 int sort_dimension__add(const char *tok)
1544 {
1545         unsigned int i;
1546
1547         for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
1548                 struct sort_dimension *sd = &common_sort_dimensions[i];
1549
1550                 if (strncasecmp(tok, sd->name, strlen(tok)))
1551                         continue;
1552
1553                 if (sd->entry == &sort_parent) {
1554                         int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
1555                         if (ret) {
1556                                 char err[BUFSIZ];
1557
1558                                 regerror(ret, &parent_regex, err, sizeof(err));
1559                                 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
1560                                 return -EINVAL;
1561                         }
1562                         sort__has_parent = 1;
1563                 } else if (sd->entry == &sort_sym) {
1564                         sort__has_sym = 1;
1565                         /*
1566                          * perf diff displays the performance difference amongst
1567                          * two or more perf.data files. Those files could come
1568                          * from different binaries. So we should not compare
1569                          * their ips, but the name of symbol.
1570                          */
1571                         if (sort__mode == SORT_MODE__DIFF)
1572                                 sd->entry->se_collapse = sort__sym_sort;
1573
1574                 } else if (sd->entry == &sort_dso) {
1575                         sort__has_dso = 1;
1576                 } else if (sd->entry == &sort_socket) {
1577                         sort__has_socket = 1;
1578                 }
1579
1580                 return __sort_dimension__add(sd);
1581         }
1582
1583         for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
1584                 struct hpp_dimension *hd = &hpp_sort_dimensions[i];
1585
1586                 if (strncasecmp(tok, hd->name, strlen(tok)))
1587                         continue;
1588
1589                 return __hpp_dimension__add(hd);
1590         }
1591
1592         for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
1593                 struct sort_dimension *sd = &bstack_sort_dimensions[i];
1594
1595                 if (strncasecmp(tok, sd->name, strlen(tok)))
1596                         continue;
1597
1598                 if (sort__mode != SORT_MODE__BRANCH)
1599                         return -EINVAL;
1600
1601                 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
1602                         sort__has_sym = 1;
1603
1604                 __sort_dimension__add(sd);
1605                 return 0;
1606         }
1607
1608         for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
1609                 struct sort_dimension *sd = &memory_sort_dimensions[i];
1610
1611                 if (strncasecmp(tok, sd->name, strlen(tok)))
1612                         continue;
1613
1614                 if (sort__mode != SORT_MODE__MEMORY)
1615                         return -EINVAL;
1616
1617                 if (sd->entry == &sort_mem_daddr_sym)
1618                         sort__has_sym = 1;
1619
1620                 __sort_dimension__add(sd);
1621                 return 0;
1622         }
1623
1624         return -ESRCH;
1625 }
1626
1627 static const char *get_default_sort_order(void)
1628 {
1629         const char *default_sort_orders[] = {
1630                 default_sort_order,
1631                 default_branch_sort_order,
1632                 default_mem_sort_order,
1633                 default_top_sort_order,
1634                 default_diff_sort_order,
1635         };
1636
1637         BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
1638
1639         return default_sort_orders[sort__mode];
1640 }
1641
1642 static int setup_sort_order(void)
1643 {
1644         char *new_sort_order;
1645
1646         /*
1647          * Append '+'-prefixed sort order to the default sort
1648          * order string.
1649          */
1650         if (!sort_order || is_strict_order(sort_order))
1651                 return 0;
1652
1653         if (sort_order[1] == '\0') {
1654                 error("Invalid --sort key: `+'");
1655                 return -EINVAL;
1656         }
1657
1658         /*
1659          * We allocate new sort_order string, but we never free it,
1660          * because it's checked over the rest of the code.
1661          */
1662         if (asprintf(&new_sort_order, "%s,%s",
1663                      get_default_sort_order(), sort_order + 1) < 0) {
1664                 error("Not enough memory to set up --sort");
1665                 return -ENOMEM;
1666         }
1667
1668         sort_order = new_sort_order;
1669         return 0;
1670 }
1671
1672 static int __setup_sorting(void)
1673 {
1674         char *tmp, *tok, *str;
1675         const char *sort_keys;
1676         int ret = 0;
1677
1678         ret = setup_sort_order();
1679         if (ret)
1680                 return ret;
1681
1682         sort_keys = sort_order;
1683         if (sort_keys == NULL) {
1684                 if (is_strict_order(field_order)) {
1685                         /*
1686                          * If user specified field order but no sort order,
1687                          * we'll honor it and not add default sort orders.
1688                          */
1689                         return 0;
1690                 }
1691
1692                 sort_keys = get_default_sort_order();
1693         }
1694
1695         str = strdup(sort_keys);
1696         if (str == NULL) {
1697                 error("Not enough memory to setup sort keys");
1698                 return -ENOMEM;
1699         }
1700
1701         for (tok = strtok_r(str, ", ", &tmp);
1702                         tok; tok = strtok_r(NULL, ", ", &tmp)) {
1703                 ret = sort_dimension__add(tok);
1704                 if (ret == -EINVAL) {
1705                         error("Invalid --sort key: `%s'", tok);
1706                         break;
1707                 } else if (ret == -ESRCH) {
1708                         error("Unknown --sort key: `%s'", tok);
1709                         break;
1710                 }
1711         }
1712
1713         free(str);
1714         return ret;
1715 }
1716
1717 void perf_hpp__set_elide(int idx, bool elide)
1718 {
1719         struct perf_hpp_fmt *fmt;
1720         struct hpp_sort_entry *hse;
1721
1722         perf_hpp__for_each_format(fmt) {
1723                 if (!perf_hpp__is_sort_entry(fmt))
1724                         continue;
1725
1726                 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1727                 if (hse->se->se_width_idx == idx) {
1728                         fmt->elide = elide;
1729                         break;
1730                 }
1731         }
1732 }
1733
1734 static bool __get_elide(struct strlist *list, const char *list_name, FILE *fp)
1735 {
1736         if (list && strlist__nr_entries(list) == 1) {
1737                 if (fp != NULL)
1738                         fprintf(fp, "# %s: %s\n", list_name,
1739                                 strlist__entry(list, 0)->s);
1740                 return true;
1741         }
1742         return false;
1743 }
1744
1745 static bool get_elide(int idx, FILE *output)
1746 {
1747         switch (idx) {
1748         case HISTC_SYMBOL:
1749                 return __get_elide(symbol_conf.sym_list, "symbol", output);
1750         case HISTC_DSO:
1751                 return __get_elide(symbol_conf.dso_list, "dso", output);
1752         case HISTC_COMM:
1753                 return __get_elide(symbol_conf.comm_list, "comm", output);
1754         default:
1755                 break;
1756         }
1757
1758         if (sort__mode != SORT_MODE__BRANCH)
1759                 return false;
1760
1761         switch (idx) {
1762         case HISTC_SYMBOL_FROM:
1763                 return __get_elide(symbol_conf.sym_from_list, "sym_from", output);
1764         case HISTC_SYMBOL_TO:
1765                 return __get_elide(symbol_conf.sym_to_list, "sym_to", output);
1766         case HISTC_DSO_FROM:
1767                 return __get_elide(symbol_conf.dso_from_list, "dso_from", output);
1768         case HISTC_DSO_TO:
1769                 return __get_elide(symbol_conf.dso_to_list, "dso_to", output);
1770         default:
1771                 break;
1772         }
1773
1774         return false;
1775 }
1776
1777 void sort__setup_elide(FILE *output)
1778 {
1779         struct perf_hpp_fmt *fmt;
1780         struct hpp_sort_entry *hse;
1781
1782         perf_hpp__for_each_format(fmt) {
1783                 if (!perf_hpp__is_sort_entry(fmt))
1784                         continue;
1785
1786                 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1787                 fmt->elide = get_elide(hse->se->se_width_idx, output);
1788         }
1789
1790         /*
1791          * It makes no sense to elide all of sort entries.
1792          * Just revert them to show up again.
1793          */
1794         perf_hpp__for_each_format(fmt) {
1795                 if (!perf_hpp__is_sort_entry(fmt))
1796                         continue;
1797
1798                 if (!fmt->elide)
1799                         return;
1800         }
1801
1802         perf_hpp__for_each_format(fmt) {
1803                 if (!perf_hpp__is_sort_entry(fmt))
1804                         continue;
1805
1806                 fmt->elide = false;
1807         }
1808 }
1809
1810 static int output_field_add(char *tok)
1811 {
1812         unsigned int i;
1813
1814         for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
1815                 struct sort_dimension *sd = &common_sort_dimensions[i];
1816
1817                 if (strncasecmp(tok, sd->name, strlen(tok)))
1818                         continue;
1819
1820                 return __sort_dimension__add_output(sd);
1821         }
1822
1823         for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
1824                 struct hpp_dimension *hd = &hpp_sort_dimensions[i];
1825
1826                 if (strncasecmp(tok, hd->name, strlen(tok)))
1827                         continue;
1828
1829                 return __hpp_dimension__add_output(hd);
1830         }
1831
1832         for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
1833                 struct sort_dimension *sd = &bstack_sort_dimensions[i];
1834
1835                 if (strncasecmp(tok, sd->name, strlen(tok)))
1836                         continue;
1837
1838                 return __sort_dimension__add_output(sd);
1839         }
1840
1841         for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
1842                 struct sort_dimension *sd = &memory_sort_dimensions[i];
1843
1844                 if (strncasecmp(tok, sd->name, strlen(tok)))
1845                         continue;
1846
1847                 return __sort_dimension__add_output(sd);
1848         }
1849
1850         return -ESRCH;
1851 }
1852
1853 static void reset_dimensions(void)
1854 {
1855         unsigned int i;
1856
1857         for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++)
1858                 common_sort_dimensions[i].taken = 0;
1859
1860         for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++)
1861                 hpp_sort_dimensions[i].taken = 0;
1862
1863         for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++)
1864                 bstack_sort_dimensions[i].taken = 0;
1865
1866         for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++)
1867                 memory_sort_dimensions[i].taken = 0;
1868 }
1869
1870 bool is_strict_order(const char *order)
1871 {
1872         return order && (*order != '+');
1873 }
1874
1875 static int __setup_output_field(void)
1876 {
1877         char *tmp, *tok, *str, *strp;
1878         int ret = -EINVAL;
1879
1880         if (field_order == NULL)
1881                 return 0;
1882
1883         reset_dimensions();
1884
1885         strp = str = strdup(field_order);
1886         if (str == NULL) {
1887                 error("Not enough memory to setup output fields");
1888                 return -ENOMEM;
1889         }
1890
1891         if (!is_strict_order(field_order))
1892                 strp++;
1893
1894         if (!strlen(strp)) {
1895                 error("Invalid --fields key: `+'");
1896                 goto out;
1897         }
1898
1899         for (tok = strtok_r(strp, ", ", &tmp);
1900                         tok; tok = strtok_r(NULL, ", ", &tmp)) {
1901                 ret = output_field_add(tok);
1902                 if (ret == -EINVAL) {
1903                         error("Invalid --fields key: `%s'", tok);
1904                         break;
1905                 } else if (ret == -ESRCH) {
1906                         error("Unknown --fields key: `%s'", tok);
1907                         break;
1908                 }
1909         }
1910
1911 out:
1912         free(str);
1913         return ret;
1914 }
1915
1916 int setup_sorting(void)
1917 {
1918         int err;
1919
1920         err = __setup_sorting();
1921         if (err < 0)
1922                 return err;
1923
1924         if (parent_pattern != default_parent_pattern) {
1925                 err = sort_dimension__add("parent");
1926                 if (err < 0)
1927                         return err;
1928         }
1929
1930         reset_dimensions();
1931
1932         /*
1933          * perf diff doesn't use default hpp output fields.
1934          */
1935         if (sort__mode != SORT_MODE__DIFF)
1936                 perf_hpp__init();
1937
1938         err = __setup_output_field();
1939         if (err < 0)
1940                 return err;
1941
1942         /* copy sort keys to output fields */
1943         perf_hpp__setup_output_field();
1944         /* and then copy output fields to sort keys */
1945         perf_hpp__append_sort_keys();
1946
1947         return 0;
1948 }
1949
1950 void reset_output_field(void)
1951 {
1952         sort__need_collapse = 0;
1953         sort__has_parent = 0;
1954         sort__has_sym = 0;
1955         sort__has_dso = 0;
1956
1957         field_order = NULL;
1958         sort_order = NULL;
1959
1960         reset_dimensions();
1961         perf_hpp__reset_output_field();
1962 }