18 static int repsep_snprintf(
char *
bf,
size_t size,
const char *
fmt, ...)
42 static int64_t cmp_null(
void *
l,
void *
r)
60 static int hist_entry__thread_snprintf(
struct hist_entry *
self,
char *bf,
61 size_t size,
unsigned int width)
63 return repsep_snprintf(bf, size,
"%*s:%5d", width,
64 self->thread->comm ?:
"", self->thread->pid);
68 .se_header =
"Command: Pid",
69 .se_cmp = sort__thread_cmp,
70 .se_snprintf = hist_entry__thread_snprintf,
85 char *comm_l = left->
thread->comm;
86 char *comm_r = right->
thread->comm;
88 if (!comm_l || !comm_r)
89 return cmp_null(comm_l, comm_r);
91 return strcmp(comm_l, comm_r);
94 static int hist_entry__comm_snprintf(
struct hist_entry *
self,
char *bf,
95 size_t size,
unsigned int width)
97 return repsep_snprintf(bf, size,
"%*s", width, self->thread->comm);
100 static int64_t _sort__dso_cmp(
struct map *map_l,
struct map *map_r)
102 struct dso *dso_l = map_l ? map_l->
dso :
NULL;
103 struct dso *dso_r = map_r ? map_r->
dso :
NULL;
104 const char *dso_name_l, *dso_name_r;
106 if (!dso_l || !dso_r)
107 return cmp_null(dso_l, dso_r);
117 return strcmp(dso_name_l, dso_name_r);
121 .se_header =
"Command",
122 .se_cmp = sort__comm_cmp,
123 .se_collapse = sort__comm_collapse,
124 .se_snprintf = hist_entry__comm_snprintf,
133 return _sort__dso_cmp(left->
ms.map, right->
ms.map);
137 static int64_t _sort__sym_cmp(
struct symbol *sym_l,
struct symbol *sym_r,
140 if (!sym_l || !sym_r)
141 return cmp_null(sym_l, sym_r);
151 return (int64_t)(ip_r - ip_l);
154 static int _hist_entry__dso_snprintf(
struct map *
map,
char *bf,
155 size_t size,
unsigned int width)
157 if (map && map->
dso) {
158 const char *dso_name = !
verbose ? map->
dso->short_name :
160 return repsep_snprintf(bf, size,
"%-*s", width, dso_name);
163 return repsep_snprintf(bf, size,
"%-*s", width,
"[unknown]");
166 static int hist_entry__dso_snprintf(
struct hist_entry *
self,
char *bf,
167 size_t size,
unsigned int width)
169 return _hist_entry__dso_snprintf(self->ms.map, bf, size, width);
172 static int _hist_entry__sym_snprintf(
struct map *map,
struct symbol *sym,
180 ret += repsep_snprintf(bf, size,
"%-#*llx %c ",
184 ret += repsep_snprintf(bf + ret, size - ret,
"[%c] ", level);
186 ret += repsep_snprintf(bf + ret, size - ret,
"%-*s",
191 ret += repsep_snprintf(bf + ret, size - ret,
"%-#.*llx",
193 ret += repsep_snprintf(bf + ret, size - ret,
"%-*s",
202 .se_header =
"Shared Object",
203 .se_cmp = sort__dso_cmp,
204 .se_snprintf = hist_entry__dso_snprintf,
208 static int hist_entry__sym_snprintf(
struct hist_entry *
self,
char *bf,
210 unsigned int width __maybe_unused)
212 return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip,
213 self->level, bf, size, width);
222 if (!left->
ms.sym && !right->
ms.sym)
225 if (!left->
ms.sym || !right->
ms.sym)
226 return cmp_null(left->
ms.sym, right->
ms.sym);
228 if (left->
ms.sym == right->
ms.sym)
231 ip_l = left->
ms.sym->start;
232 ip_r = right->
ms.sym->start;
234 return _sort__sym_cmp(left->
ms.sym, right->
ms.sym, ip_l, ip_r);
238 .se_header =
"Symbol",
239 .se_cmp = sort__sym_cmp,
240 .se_snprintf = hist_entry__sym_snprintf,
249 return (int64_t)(right->
ip - left->
ip);
252 static int hist_entry__srcline_snprintf(
struct hist_entry *
self,
char *bf,
254 unsigned int width __maybe_unused)
266 if (!
strncmp(self->ms.map->dso->long_name,
"/tmp/perf-", 10))
270 self->ms.map->dso->long_name, self->ip);
271 fp = popen(cmd,
"r");
275 if (getline(&path, &line_len, fp) < 0 || !line_len)
278 self->srcline = strdup(path);
279 if (self->srcline ==
NULL)
282 nl =
strchr(self->srcline,
'\n');
285 path =
self->srcline;
287 return repsep_snprintf(bf, size,
"%s", path);
289 return repsep_snprintf(bf, size,
"%-#*llx",
BITS_PER_LONG / 4, self->ip);
293 .se_header =
"Source:Line",
294 .se_cmp = sort__srcline_cmp,
295 .se_snprintf = hist_entry__srcline_snprintf,
307 if (!sym_l || !sym_r)
308 return cmp_null(sym_l, sym_r);
313 static int hist_entry__parent_snprintf(
struct hist_entry *
self,
char *bf,
314 size_t size,
unsigned int width)
316 return repsep_snprintf(bf, size,
"%-*s", width,
317 self->parent ? self->parent->name :
"[other]");
321 .se_header =
"Parent symbol",
322 .se_cmp = sort__parent_cmp,
323 .se_snprintf = hist_entry__parent_snprintf,
332 return right->
cpu - left->
cpu;
335 static int hist_entry__cpu_snprintf(
struct hist_entry *
self,
char *bf,
336 size_t size,
unsigned int width)
338 return repsep_snprintf(bf, size,
"%-*d", width, self->cpu);
343 .se_cmp = sort__cpu_cmp,
344 .se_snprintf = hist_entry__cpu_snprintf,
355 static int hist_entry__dso_from_snprintf(
struct hist_entry *
self,
char *bf,
356 size_t size,
unsigned int width)
358 return _hist_entry__dso_snprintf(self->branch_info->from.map,
363 .se_header =
"Source Shared Object",
364 .se_cmp = sort__dso_from_cmp,
365 .se_snprintf = hist_entry__dso_from_snprintf,
376 static int hist_entry__dso_to_snprintf(
struct hist_entry *
self,
char *bf,
377 size_t size,
unsigned int width)
379 return _hist_entry__dso_snprintf(self->branch_info->to.map,
389 if (!from_l->
sym && !from_r->
sym)
392 return _sort__sym_cmp(from_l->
sym, from_r->
sym, from_l->
addr,
402 if (!to_l->
sym && !to_r->
sym)
405 return _sort__sym_cmp(to_l->
sym, to_r->
sym, to_l->
addr, to_r->
addr);
408 static int hist_entry__sym_from_snprintf(
struct hist_entry *
self,
char *bf,
410 unsigned int width __maybe_unused)
413 return _hist_entry__sym_snprintf(from->
map, from->
sym, from->
addr,
414 self->level, bf, size, width);
418 static int hist_entry__sym_to_snprintf(
struct hist_entry *
self,
char *bf,
420 unsigned int width __maybe_unused)
423 return _hist_entry__sym_snprintf(to->
map, to->
sym, to->
addr,
424 self->level, bf, size, width);
429 .se_header =
"Target Shared Object",
430 .se_cmp = sort__dso_to_cmp,
431 .se_snprintf = hist_entry__dso_to_snprintf,
436 .se_header =
"Source Symbol",
437 .se_cmp = sort__sym_from_cmp,
438 .se_snprintf = hist_entry__sym_from_snprintf,
443 .se_header =
"Target Symbol",
444 .se_cmp = sort__sym_to_cmp,
445 .se_snprintf = hist_entry__sym_to_snprintf,
454 const unsigned char p = left->
branch_info->flags.predicted !=
460 static int hist_entry__mispredict_snprintf(
struct hist_entry *
self,
char *bf,
461 size_t size,
unsigned int width){
462 static const char *
out =
"N/A";
464 if (self->branch_info->flags.predicted)
466 else if (self->branch_info->flags.mispred)
469 return repsep_snprintf(bf, size,
"%-*s", width, out);
473 .se_header =
"Branch Mispredicted",
474 .se_cmp = sort__mispredict_cmp,
475 .se_snprintf = hist_entry__mispredict_snprintf,
485 #define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
506 for (i = 0; i <
ARRAY_SIZE(sort_dimensions); i++) {
511 if (sd->
entry == &sort_parent) {
521 }
else if (sd->
entry == &sort_sym ||
522 sd->
entry == &sort_sym_from ||
523 sd->
entry == &sort_sym_to) {
530 if (sd->
entry->se_collapse)
570 for (tok = strtok_r(str,
", ", &tmp);
571 tok; tok = strtok_r(
NULL,
", ", &tmp)) {
573 error(
"Unknown --sort key: `%s'", tok);
582 const char *list_name, FILE *fp)
584 if (list && strlist__nr_entries(list) == 1) {
586 fprintf(fp,
"# %s: %s\n", list_name,