xref: /linux/tools/perf/util/sort.c (revision 8e947f1e84fd1588f66e5f2ea69c80647de72cd4)
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 }
1963