perf tools: Remove stale prototypes from builtin.h
[linux-2.6-block.git] / tools / perf / builtin-report.c
CommitLineData
bf9e1876
IM
1/*
2 * builtin-report.c
3 *
4 * Builtin report command: Analyze the perf.data input file,
5 * look up and read DSOs and symbol information and display
6 * a histogram of results, along various sorting keys.
7 */
16f762a2 8#include "builtin.h"
53cb8bc2 9
bf9e1876 10#include "util/util.h"
41840d21 11#include "util/config.h"
bf9e1876 12
78f7defe 13#include "util/annotate.h"
8fc0321f 14#include "util/color.h"
5da50258 15#include <linux/list.h>
43cbcd8a 16#include <linux/rbtree.h>
a2928c42 17#include "util/symbol.h"
f55c5552 18#include "util/callchain.h"
8d513270 19#include "util/values.h"
8fa66bdc 20
53cb8bc2 21#include "perf.h"
8f28827a 22#include "util/debug.h"
e248de33
ACM
23#include "util/evlist.h"
24#include "util/evsel.h"
7c6a1c65 25#include "util/header.h"
94c744b6 26#include "util/session.h"
45694aa7 27#include "util/tool.h"
53cb8bc2 28
4b6ab94e 29#include <subcmd/parse-options.h>
34b7b0f9 30#include <subcmd/exec-cmd.h>
53cb8bc2
IM
31#include "util/parse-events.h"
32
6baa0a5a 33#include "util/thread.h"
dd68ada2 34#include "util/sort.h"
3d1d07ec 35#include "util/hist.h"
f5fc1412 36#include "util/data.h"
68e94f4e 37#include "arch/common.h"
46690a80 38#include "util/time-utils.h"
520a2ebc 39#include "util/auxtrace.h"
58db1d6e 40#include "util/units.h"
520a2ebc 41
fc67297b 42#include <dlfcn.h>
a43783ae 43#include <errno.h>
fd20e811 44#include <inttypes.h>
1eae20c1 45#include <regex.h>
9607ad3a 46#include <signal.h>
5d67be97 47#include <linux/bitmap.h>
531d2410 48#include <linux/stringify.h>
5d67be97 49
28b21393 50struct report {
45694aa7 51 struct perf_tool tool;
d20deb64 52 struct perf_session *session;
2059fc7a 53 bool use_tui, use_gtk, use_stdio;
fa372aae
ACM
54 bool show_full_info;
55 bool show_threads;
56 bool inverted_callchain;
f4f7e28d 57 bool mem_mode;
5cfe2c82
JO
58 bool header;
59 bool header_only;
98df858e 60 bool nonany_branch_mode;
91e95617 61 int max_stack;
fa372aae
ACM
62 struct perf_read_values show_threads_values;
63 const char *pretty_printing_style;
fa372aae 64 const char *cpu_list;
b14ffaca 65 const char *symbol_filter_str;
46690a80
DA
66 const char *time_str;
67 struct perf_time_interval ptime;
064f1981 68 float min_percent;
58c311da 69 u64 nr_entries;
94786b67 70 u64 queue_size;
21394d94 71 int socket_filter;
fa372aae 72 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
d20deb64 73};
5d67be97 74
28b21393 75static int report__config(const char *var, const char *value, void *cb)
00c7e1f1 76{
94786b67
JO
77 struct report *rep = cb;
78
00c7e1f1
NK
79 if (!strcmp(var, "report.group")) {
80 symbol_conf.event_group = perf_config_bool(var, value);
81 return 0;
82 }
eec574e6 83 if (!strcmp(var, "report.percent-limit")) {
2665b452
NK
84 double pcnt = strtof(value, NULL);
85
86 rep->min_percent = pcnt;
87 callchain_param.min_percent = pcnt;
eec574e6
NK
88 return 0;
89 }
8d8e645c
NK
90 if (!strcmp(var, "report.children")) {
91 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
92 return 0;
93 }
94786b67
JO
94 if (!strcmp(var, "report.queue-size")) {
95 rep->queue_size = perf_config_u64(var, value);
96 return 0;
97 }
fa1f4565
ACM
98 if (!strcmp(var, "report.sort_order")) {
99 default_sort_order = strdup(value);
100 return 0;
101 }
00c7e1f1 102
b8cbb349 103 return 0;
00c7e1f1
NK
104}
105
9d3c02d7
NK
106static int hist_iter__report_callback(struct hist_entry_iter *iter,
107 struct addr_location *al, bool single,
108 void *arg)
109{
110 int err = 0;
111 struct report *rep = arg;
112 struct hist_entry *he = iter->he;
113 struct perf_evsel *evsel = iter->evsel;
114 struct mem_info *mi;
115 struct branch_info *bi;
116
9d3c02d7
NK
117 if (!ui__has_annotation())
118 return 0;
119
57849998
AK
120 hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
121 rep->nonany_branch_mode);
122
9d3c02d7
NK
123 if (sort__mode == SORT_MODE__BRANCH) {
124 bi = he->branch_info;
125 err = addr_map_symbol__inc_samples(&bi->from, evsel->idx);
126 if (err)
127 goto out;
128
129 err = addr_map_symbol__inc_samples(&bi->to, evsel->idx);
130
131 } else if (rep->mem_mode) {
132 mi = he->mem_info;
133 err = addr_map_symbol__inc_samples(&mi->daddr, evsel->idx);
134 if (err)
135 goto out;
136
137 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
138
139 } else if (symbol_conf.cumulate_callchain) {
140 if (single)
141 err = hist_entry__inc_addr_samples(he, evsel->idx,
142 al->addr);
143 } else {
144 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
145 }
146
147out:
148 return err;
f4f7e28d
SE
149}
150
45694aa7 151static int process_sample_event(struct perf_tool *tool,
d20deb64 152 union perf_event *event,
8115d60c 153 struct perf_sample *sample,
9e69c210 154 struct perf_evsel *evsel,
743eb868 155 struct machine *machine)
75051724 156{
28b21393 157 struct report *rep = container_of(tool, struct report, tool);
1ed091c4 158 struct addr_location al;
69bcb019 159 struct hist_entry_iter iter = {
063bd936
NK
160 .evsel = evsel,
161 .sample = sample,
b49a8fe5 162 .hide_unresolved = symbol_conf.hide_unresolved,
063bd936 163 .add_entry_cb = hist_iter__report_callback,
69bcb019 164 };
b91fc39f 165 int ret = 0;
180f95e2 166
46690a80
DA
167 if (perf_time__skip_sample(&rep->ptime, sample->time))
168 return 0;
169
bb3eb566 170 if (machine__resolve(machine, &al, sample) < 0) {
a4210141
NK
171 pr_debug("problem processing %d event, skipping it.\n",
172 event->header.type);
75051724
IM
173 return -1;
174 }
e7fb08b1 175
b49a8fe5 176 if (symbol_conf.hide_unresolved && al.sym == NULL)
b91fc39f 177 goto out_put;
7bec7a91 178
fa372aae 179 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
b91fc39f 180 goto out_put;
5d67be97 181
f86225db
AH
182 if (sort__mode == SORT_MODE__BRANCH) {
183 /*
184 * A non-synthesized event might not have a branch stack if
185 * branch stacks have been synthesized (using itrace options).
186 */
187 if (!sample->branch_stack)
188 goto out_put;
69bcb019 189 iter.ops = &hist_iter_branch;
f86225db 190 } else if (rep->mem_mode) {
69bcb019 191 iter.ops = &hist_iter_mem;
f86225db 192 } else if (symbol_conf.cumulate_callchain) {
7a13aa28 193 iter.ops = &hist_iter_cumulative;
f86225db 194 } else {
69bcb019 195 iter.ops = &hist_iter_normal;
f86225db 196 }
69bcb019
NK
197
198 if (al.map != NULL)
199 al.map->dso->hit = 1;
200
063bd936 201 ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep);
69bcb019
NK
202 if (ret < 0)
203 pr_debug("problem adding hist entry, skipping event\n");
b91fc39f
ACM
204out_put:
205 addr_location__put(&al);
27a0dcb7 206 return ret;
75051724 207}
3502973d 208
45694aa7 209static int process_read_event(struct perf_tool *tool,
d20deb64 210 union perf_event *event,
1d037ca1 211 struct perf_sample *sample __maybe_unused,
743eb868 212 struct perf_evsel *evsel,
1d037ca1 213 struct machine *machine __maybe_unused)
e9ea2fde 214{
28b21393 215 struct report *rep = container_of(tool, struct report, tool);
743eb868 216
fa372aae 217 if (rep->show_threads) {
7289f83c 218 const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
89973506 219 int err = perf_read_values_add_value(&rep->show_threads_values,
8d513270
BG
220 event->read.pid, event->read.tid,
221 event->read.id,
222 name,
223 event->read.value);
89973506
ACM
224
225 if (err)
226 return err;
8d513270
BG
227 }
228
9486aa38 229 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
7289f83c 230 evsel ? perf_evsel__name(evsel) : "FAIL",
62daacb5 231 event->read.value);
e9ea2fde
PZ
232
233 return 0;
234}
235
300aa941 236/* For pipe mode, sample_type is not currently set */
28b21393 237static int report__setup_sample_type(struct report *rep)
d80d338d 238{
c824c433
ACM
239 struct perf_session *session = rep->session;
240 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
241 bool is_pipe = perf_data_file__is_pipe(session->file);
d20deb64 242
d062ac16
AH
243 if (session->itrace_synth_opts->callchain ||
244 (!is_pipe &&
245 perf_header__has_feat(&session->header, HEADER_AUXTRACE) &&
246 !session->itrace_synth_opts->set))
247 sample_type |= PERF_SAMPLE_CALLCHAIN;
248
c7eced63
AH
249 if (session->itrace_synth_opts->last_branch)
250 sample_type |= PERF_SAMPLE_BRANCH_STACK;
251
cc9784bd 252 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
de7e6a7c 253 if (perf_hpp_list.parent) {
3780f488 254 ui__error("Selected --sort parent, but no "
00894ce9
ACM
255 "callchain data. Did you call "
256 "'perf record' without -g?\n");
d549c769 257 return -EINVAL;
91b4eaea 258 }
d599db3f 259 if (symbol_conf.use_callchain) {
fa94c36c
AK
260 ui__error("Selected -g or --branch-history but no "
261 "callchain data. Did\n"
262 "you call 'perf record' without -g?\n");
016e92fb 263 return -1;
91b4eaea 264 }
1cc83815 265 } else if (!callchain_param.enabled &&
fa372aae 266 callchain_param.mode != CHAIN_NONE &&
b9a63b9b 267 !symbol_conf.use_callchain) {
d599db3f 268 symbol_conf.use_callchain = true;
16537f13 269 if (callchain_register_param(&callchain_param) < 0) {
3780f488 270 ui__error("Can't register callchain params.\n");
d549c769 271 return -EINVAL;
b1a88349 272 }
f5970550
PZ
273 }
274
793aaaab
NK
275 if (symbol_conf.cumulate_callchain) {
276 /* Silently ignore if callchain is missing */
277 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
278 symbol_conf.cumulate_callchain = false;
279 perf_hpp__cancel_cumulate();
280 }
281 }
282
55369fc1 283 if (sort__mode == SORT_MODE__BRANCH) {
cc9784bd 284 if (!is_pipe &&
7f3be652 285 !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
3780f488
NK
286 ui__error("Selected -b but no branch data. "
287 "Did you call perf record without -b?\n");
b50311dc
RAV
288 return -1;
289 }
290 }
291
0cdccac6
NK
292 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
293 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
294 (sample_type & PERF_SAMPLE_STACK_USER))
295 callchain_param.record_mode = CALLCHAIN_DWARF;
aad2b21c
KL
296 else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
297 callchain_param.record_mode = CALLCHAIN_LBR;
0cdccac6
NK
298 else
299 callchain_param.record_mode = CALLCHAIN_FP;
300 }
98df858e
AK
301
302 /* ??? handle more cases than just ANY? */
303 if (!(perf_evlist__combined_branch_type(session->evlist) &
304 PERF_SAMPLE_BRANCH_ANY))
305 rep->nonany_branch_mode = true;
306
016e92fb
FW
307 return 0;
308}
6142f9ec 309
1d037ca1 310static void sig_handler(int sig __maybe_unused)
46656ac7
TZ
311{
312 session_done = 1;
313}
314
28b21393 315static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
c82ee828
ACM
316 const char *evname, FILE *fp)
317{
318 size_t ret;
319 char unit;
c824c433
ACM
320 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
321 u64 nr_events = hists->stats.total_period;
322 struct perf_evsel *evsel = hists_to_evsel(hists);
717e263f
NK
323 char buf[512];
324 size_t size = sizeof(buf);
84734b06 325 int socked_id = hists->socket_filter;
717e263f 326
27fafab5
NK
327 if (quiet)
328 return 0;
329
f2148330
NK
330 if (symbol_conf.filter_relative) {
331 nr_samples = hists->stats.nr_non_filtered_samples;
332 nr_events = hists->stats.total_non_filtered_period;
333 }
334
759ff497 335 if (perf_evsel__is_group_event(evsel)) {
717e263f
NK
336 struct perf_evsel *pos;
337
338 perf_evsel__group_desc(evsel, buf, size);
339 evname = buf;
340
341 for_each_group_member(pos, evsel) {
4ea062ed
ACM
342 const struct hists *pos_hists = evsel__hists(pos);
343
f2148330 344 if (symbol_conf.filter_relative) {
4ea062ed
ACM
345 nr_samples += pos_hists->stats.nr_non_filtered_samples;
346 nr_events += pos_hists->stats.total_non_filtered_period;
f2148330 347 } else {
4ea062ed
ACM
348 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
349 nr_events += pos_hists->stats.total_period;
f2148330 350 }
717e263f
NK
351 }
352 }
c82ee828 353
cc686280
AR
354 nr_samples = convert_unit(nr_samples, &unit);
355 ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
c82ee828 356 if (evname != NULL)
cc686280
AR
357 ret += fprintf(fp, " of event '%s'", evname);
358
9e207ddf
KL
359 if (symbol_conf.show_ref_callgraph &&
360 strstr(evname, "call-graph=no")) {
361 ret += fprintf(fp, ", show reference callgraph");
362 }
363
f4f7e28d
SE
364 if (rep->mem_mode) {
365 ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
228f14f2 366 ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order);
f4f7e28d
SE
367 } else
368 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
21394d94 369
84734b06
KL
370 if (socked_id > -1)
371 ret += fprintf(fp, "\n# Processor Socket: %d", socked_id);
21394d94 372
c82ee828
ACM
373 return ret + fprintf(fp, "\n#\n");
374}
375
7f0030b2 376static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
28b21393 377 struct report *rep,
7f0030b2 378 const char *help)
d67f088e 379{
e248de33 380 struct perf_evsel *pos;
d67f088e 381
27fafab5
NK
382 if (!quiet) {
383 fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n",
384 evlist->stats.total_lost_samples);
385 }
386
e5cadb93 387 evlist__for_each_entry(evlist, pos) {
4ea062ed 388 struct hists *hists = evsel__hists(pos);
7289f83c 389 const char *evname = perf_evsel__name(pos);
d67f088e 390
fc24d7c2
NK
391 if (symbol_conf.event_group &&
392 !perf_evsel__is_group_leader(pos))
393 continue;
394
28b21393 395 hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
27fafab5 396 hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout,
d05e3aae 397 symbol_conf.use_callchain);
d67f088e 398 fprintf(stdout, "\n\n");
d67f088e
ACM
399 }
400
8b53dbef 401 if (!quiet)
d67f088e
ACM
402 fprintf(stdout, "#\n# (%s)\n#\n", help);
403
021162cf
NK
404 if (rep->show_threads) {
405 bool style = !strcmp(rep->pretty_printing_style, "raw");
406 perf_read_values_display(stdout, &rep->show_threads_values,
407 style);
408 perf_read_values_destroy(&rep->show_threads_values);
d67f088e
ACM
409 }
410
411 return 0;
412}
413
fad2918e
ACM
414static void report__warn_kptr_restrict(const struct report *rep)
415{
a5e813c6 416 struct map *kernel_map = machine__kernel_map(&rep->session->machines.host);
f6fcc143 417 struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
fad2918e
ACM
418
419 if (kernel_map == NULL ||
420 (kernel_map->dso->hit &&
421 (kernel_kmap->ref_reloc_sym == NULL ||
422 kernel_kmap->ref_reloc_sym->addr == 0))) {
423 const char *desc =
424 "As no suitable kallsyms nor vmlinux was found, kernel samples\n"
425 "can't be resolved.";
426
427 if (kernel_map) {
428 const struct dso *kdso = kernel_map->dso;
429 if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) {
430 desc = "If some relocation was applied (e.g. "
431 "kexec) symbols may be misresolved.";
432 }
433 }
434
435 ui__warning(
436"Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n"
437"Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n"
438"Samples in kernel modules can't be resolved as well.\n\n",
439 desc);
440 }
441}
442
8362951b
ACM
443static int report__gtk_browse_hists(struct report *rep, const char *help)
444{
445 int (*hist_browser)(struct perf_evlist *evlist, const char *help,
446 struct hist_browser_timer *timer, float min_pcnt);
447
448 hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists");
449
450 if (hist_browser == NULL) {
451 ui__error("GTK browser not found!\n");
452 return -1;
453 }
454
455 return hist_browser(rep->session->evlist, help, NULL, rep->min_percent);
456}
457
458static int report__browse_hists(struct report *rep)
459{
460 int ret;
461 struct perf_session *session = rep->session;
462 struct perf_evlist *evlist = session->evlist;
34b7b0f9
NK
463 const char *help = perf_tip(system_path(TIPDIR));
464
465 if (help == NULL) {
466 /* fallback for people who don't install perf ;-) */
467 help = perf_tip(DOCDIR);
468 if (help == NULL)
469 help = "Cannot load tips.txt file, please install perf!";
470 }
8362951b
ACM
471
472 switch (use_browser) {
473 case 1:
474 ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
475 rep->min_percent,
476 &session->header.env);
477 /*
478 * Usually "ret" is the last pressed key, and we only
479 * care if the key notifies us to switch data file.
480 */
481 if (ret != K_SWITCH_INPUT_DATA)
482 ret = 0;
483 break;
484 case 2:
485 ret = report__gtk_browse_hists(rep, help);
486 break;
487 default:
488 ret = perf_evlist__tty_browse_hists(evlist, rep, help);
489 break;
490 }
491
492 return ret;
493}
494
5b2ea6f2 495static int report__collapse_hists(struct report *rep)
f6d8b057
ACM
496{
497 struct ui_progress prog;
498 struct perf_evsel *pos;
5b2ea6f2 499 int ret = 0;
f6d8b057 500
58c311da 501 ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
f6d8b057 502
e5cadb93 503 evlist__for_each_entry(rep->session->evlist, pos) {
4ea062ed 504 struct hists *hists = evsel__hists(pos);
f6d8b057
ACM
505
506 if (pos->idx == 0)
507 hists->symbol_filter_str = rep->symbol_filter_str;
508
21394d94
KL
509 hists->socket_filter = rep->socket_filter;
510
5b2ea6f2
NK
511 ret = hists__collapse_resort(hists, &prog);
512 if (ret < 0)
513 break;
f6d8b057
ACM
514
515 /* Non-group events are considered as leader */
516 if (symbol_conf.event_group &&
517 !perf_evsel__is_group_leader(pos)) {
4ea062ed 518 struct hists *leader_hists = evsel__hists(pos->leader);
f6d8b057
ACM
519
520 hists__match(leader_hists, hists);
521 hists__link(leader_hists, hists);
522 }
523 }
524
525 ui_progress__finish();
5b2ea6f2 526 return ret;
f6d8b057
ACM
527}
528
740b97f9
NK
529static void report__output_resort(struct report *rep)
530{
531 struct ui_progress prog;
532 struct perf_evsel *pos;
533
534 ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
535
e5cadb93 536 evlist__for_each_entry(rep->session->evlist, pos)
452ce03b 537 perf_evsel__output_resort(pos, &prog);
740b97f9
NK
538
539 ui_progress__finish();
540}
541
28b21393 542static int __cmd_report(struct report *rep)
016e92fb 543{
f6d8b057 544 int ret;
993ac88d 545 struct perf_session *session = rep->session;
e248de33 546 struct perf_evsel *pos;
cc9784bd 547 struct perf_data_file *file = session->file;
8fa66bdc 548
46656ac7
TZ
549 signal(SIGINT, sig_handler);
550
fa372aae
ACM
551 if (rep->cpu_list) {
552 ret = perf_session__cpu_bitmap(session, rep->cpu_list,
553 rep->cpu_bitmap);
25b1606b
NK
554 if (ret) {
555 ui__error("failed to set cpu bitmap\n");
d4ae0a6f 556 return ret;
25b1606b 557 }
5d67be97
AB
558 }
559
89973506
ACM
560 if (rep->show_threads) {
561 ret = perf_read_values_init(&rep->show_threads_values);
562 if (ret)
563 return ret;
564 }
f5970550 565
28b21393 566 ret = report__setup_sample_type(rep);
25b1606b
NK
567 if (ret) {
568 /* report__setup_sample_type() already showed error message */
d4ae0a6f 569 return ret;
25b1606b 570 }
d549c769 571
b7b61cbe 572 ret = perf_session__process_events(session);
25b1606b
NK
573 if (ret) {
574 ui__error("failed to process sample\n");
d4ae0a6f 575 return ret;
25b1606b 576 }
97b07b69 577
fad2918e 578 report__warn_kptr_restrict(rep);
ec80fde7 579
e5cadb93 580 evlist__for_each_entry(session->evlist, pos)
590cd344
NK
581 rep->nr_entries += evsel__hists(pos)->nr_entries;
582
150e465a
NK
583 if (use_browser == 0) {
584 if (verbose > 3)
585 perf_session__fprintf(session, stdout);
9ac99545 586
150e465a
NK
587 if (verbose > 2)
588 perf_session__fprintf_dsos(session, stdout);
16f762a2 589
150e465a
NK
590 if (dump_trace) {
591 perf_session__fprintf_nr_events(session, stdout);
2a1731fb 592 perf_evlist__fprintf_nr_events(session->evlist, stdout);
150e465a
NK
593 return 0;
594 }
71ad0f5e
JO
595 }
596
5b2ea6f2
NK
597 ret = report__collapse_hists(rep);
598 if (ret) {
599 ui__error("failed to process hist entry\n");
600 return ret;
601 }
e248de33 602
33e940a2
ACM
603 if (session_done())
604 return 0;
605
740b97f9
NK
606 /*
607 * recalculate number of entries after collapsing since it
608 * might be changed during the collapse phase.
609 */
610 rep->nr_entries = 0;
e5cadb93 611 evlist__for_each_entry(session->evlist, pos)
740b97f9
NK
612 rep->nr_entries += evsel__hists(pos)->nr_entries;
613
58c311da 614 if (rep->nr_entries == 0) {
cc9784bd 615 ui__error("The %s file has no samples!\n", file->path);
d4ae0a6f 616 return 0;
cbbc79a5
EM
617 }
618
740b97f9 619 report__output_resort(rep);
6e1f601a 620
8362951b 621 return report__browse_hists(rep);
8fa66bdc
ACM
622}
623
4eb3e478 624static int
cff6bb46 625report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
4eb3e478 626{
1cc83815 627 struct callchain_param *callchain = opt->value;
c20ab37e 628
1cc83815 629 callchain->enabled = !unset;
b9a63b9b
ACM
630 /*
631 * --no-call-graph
632 */
633 if (unset) {
1cc83815
ACM
634 symbol_conf.use_callchain = false;
635 callchain->mode = CHAIN_NONE;
b9a63b9b
ACM
636 return 0;
637 }
638
cff6bb46 639 return parse_callchain_report_opt(arg);
4eb3e478
FW
640}
641
b21484f1
GP
642int
643report_parse_ignore_callees_opt(const struct option *opt __maybe_unused,
644 const char *arg, int unset __maybe_unused)
645{
646 if (arg) {
647 int err = regcomp(&ignore_callees_regex, arg, REG_EXTENDED);
648 if (err) {
649 char buf[BUFSIZ];
650 regerror(err, &ignore_callees_regex, buf, sizeof(buf));
651 pr_err("Invalid --ignore-callees regex: %s\n%s", arg, buf);
652 return -1;
653 }
654 have_ignore_callees = 1;
655 }
656
657 return 0;
658}
659
993ac88d 660static int
7e6a7998 661parse_branch_mode(const struct option *opt,
1d037ca1 662 const char *str __maybe_unused, int unset)
993ac88d 663{
55369fc1
NK
664 int *branch_mode = opt->value;
665
666 *branch_mode = !unset;
993ac88d
SE
667 return 0;
668}
669
064f1981
NK
670static int
671parse_percent_limit(const struct option *opt, const char *str,
672 int unset __maybe_unused)
673{
28b21393 674 struct report *rep = opt->value;
2665b452 675 double pcnt = strtof(str, NULL);
064f1981 676
2665b452
NK
677 rep->min_percent = pcnt;
678 callchain_param.min_percent = pcnt;
064f1981
NK
679 return 0;
680}
681
f2af0086 682#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
76a26549
NK
683
684const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
685 CALLCHAIN_REPORT_HELP
686 "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
21cf6284 687
b0ad8ea6 688int cmd_report(int argc, const char **argv)
d20deb64 689{
993ac88d 690 struct perf_session *session;
520a2ebc 691 struct itrace_synth_opts itrace_synth_opts = { .set = 0, };
efad1415 692 struct stat st;
993ac88d 693 bool has_br_stack = false;
55369fc1 694 int branch_mode = -1;
fa94c36c 695 bool branch_call_mode = false;
76a26549 696 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
d20deb64 697 const char * const report_usage[] = {
fb2baceb 698 "perf report [<options>]",
d20deb64
ACM
699 NULL
700 };
28b21393 701 struct report report = {
45694aa7 702 .tool = {
d20deb64
ACM
703 .sample = process_sample_event,
704 .mmap = perf_event__process_mmap,
5c5e854b 705 .mmap2 = perf_event__process_mmap2,
d20deb64 706 .comm = perf_event__process_comm,
f3b3614a 707 .namespaces = perf_event__process_namespaces,
f62d3f0f
ACM
708 .exit = perf_event__process_exit,
709 .fork = perf_event__process_fork,
d20deb64
ACM
710 .lost = perf_event__process_lost,
711 .read = process_read_event,
712 .attr = perf_event__process_attr,
d20deb64
ACM
713 .tracing_data = perf_event__process_tracing_data,
714 .build_id = perf_event__process_build_id,
520a2ebc
AH
715 .id_index = perf_event__process_id_index,
716 .auxtrace_info = perf_event__process_auxtrace_info,
717 .auxtrace = perf_event__process_auxtrace,
0a8cb85c 718 .ordered_events = true,
d20deb64
ACM
719 .ordering_requires_timestamps = true,
720 },
fe176085 721 .max_stack = PERF_MAX_STACK_DEPTH,
d20deb64 722 .pretty_printing_style = "normal",
21394d94 723 .socket_filter = -1,
d20deb64
ACM
724 };
725 const struct option options[] = {
70cb4e96 726 OPT_STRING('i', "input", &input_name, "file",
53cb8bc2 727 "input file name"),
c0555642 728 OPT_INCR('v', "verbose", &verbose,
815e777f 729 "be more verbose (show symbol address, etc)"),
27fafab5 730 OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any message"),
97b07b69
IM
731 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
732 "dump raw trace in ASCII"),
b32d133a
ACM
733 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
734 "file", "vmlinux pathname"),
b226a5a7
DA
735 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
736 "file", "kallsyms pathname"),
2059fc7a 737 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
b32d133a 738 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
42976487 739 "load module symbols - WARNING: use only with -k and LIVE kernel"),
d599db3f 740 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
e3d7e183 741 "Show a column with the number of samples"),
fa372aae 742 OPT_BOOLEAN('T', "threads", &report.show_threads,
8d513270 743 "Show per-thread event counters"),
fa372aae 744 OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
9f866697 745 "pretty printing style key: normal raw"),
fa372aae 746 OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
c31a9457 747 OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
fa372aae
ACM
748 OPT_BOOLEAN(0, "stdio", &report.use_stdio,
749 "Use the stdio interface"),
5cfe2c82
JO
750 OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
751 OPT_BOOLEAN(0, "header-only", &report.header_only,
752 "Show only data header."),
63299f05 753 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
a2ce067e
NK
754 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..."
755 " Please refer the man page for the complete list."),
a7d945bc
NK
756 OPT_STRING('F', "fields", &field_order, "key[,keys...]",
757 "output field(s): overhead, period, sample plus all of sort keys"),
b272a59d 758 OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization,
a1645ce1 759 "Show sample percentage for different cpu modes"),
b272a59d
NK
760 OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
761 "Show sample percentage for different cpu modes", PARSE_OPT_HIDDEN),
b25bcf2f
IM
762 OPT_STRING('p', "parent", &parent_pattern, "regex",
763 "regex filter to identify parent, see: '--sort parent'"),
d599db3f 764 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
b8e6d829 765 "Only display entries with parent-match"),
1cc83815 766 OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
f2af0086 767 "print_type,threshold[,print_limit],order,sort_key[,branch],value",
21cf6284
NK
768 report_callchain_help, &report_parse_callchain_opt,
769 callchain_default_opt),
793aaaab
NK
770 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
771 "Accumulate callchains of children and show total overhead as well"),
91e95617
WL
772 OPT_INTEGER(0, "max-stack", &report.max_stack,
773 "Set the maximum stack depth when parsing the callchain, "
774 "anything beyond the specified depth will be ignored. "
4cb93446 775 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
fa372aae
ACM
776 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
777 "alias for inverted call graph"),
b21484f1
GP
778 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
779 "ignore callees of these functions in call graphs",
780 report_parse_ignore_callees_opt),
655000e7 781 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
25903407 782 "only consider symbols in these dsos"),
c8e66720 783 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
cc8b88b1 784 "only consider symbols in these comms"),
e03eaa40
DA
785 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
786 "only consider symbols in these pids"),
787 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
788 "only consider symbols in these tids"),
655000e7 789 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
7bec7a91 790 "only consider these symbols"),
b14ffaca
NK
791 OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
792 "only show symbols that (partially) match with this filter"),
655000e7 793 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
52d422de
ACM
794 "width[,width...]",
795 "don't try to adjust column width, use these fixed values"),
0c8c2077 796 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
52d422de
ACM
797 "separator for columns, no spaces will be added between "
798 "columns '.' is reserved."),
b49a8fe5 799 OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved,
71289be7 800 "Only display entries resolved to a symbol"),
a7066709
HK
801 OPT_CALLBACK(0, "symfs", NULL, "directory",
802 "Look for files with symbols relative to this directory",
803 symbol__config_symfs),
c8e66720 804 OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
fa372aae
ACM
805 "list of cpus to profile"),
806 OPT_BOOLEAN('I', "show-info", &report.show_full_info,
fbe96f29 807 "Display extended information about perf.data file"),
64c6f0c7
ACM
808 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
809 "Interleave source code with assembly code (default)"),
810 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
811 "Display raw encoding of assembly instructions (default)"),
f69b64f7
AK
812 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
813 "Specify disassembler style (e.g. -M intel for intel syntax)"),
3f2728bd
ACM
814 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
815 "Show a column with the sum of periods"),
01d14f16
NK
816 OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
817 "Show event group information together"),
55369fc1 818 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
fa94c36c
AK
819 "use branch records for per branch histogram filling",
820 parse_branch_mode),
821 OPT_BOOLEAN(0, "branch-history", &branch_call_mode,
822 "add last branch records to call history"),
7a4ec938
MB
823 OPT_STRING(0, "objdump", &objdump_path, "path",
824 "objdump binary to use for disassembly and annotations"),
328ccdac
NK
825 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
826 "Disable symbol demangling"),
763122ad
AK
827 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
828 "Enable kernel symbol demangling"),
f4f7e28d 829 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
064f1981
NK
830 OPT_CALLBACK(0, "percent-limit", &report, "percent",
831 "Don't show entries under that percent", parse_percent_limit),
f2148330 832 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
33db4568 833 "how to display percentage of filtered entries", parse_filter_percentage),
520a2ebc
AH
834 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
835 "Instruction Tracing options",
836 itrace_parse_synth_opts),
a9710ba0
AK
837 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
838 "Show full source file name path for source lines"),
9e207ddf
KL
839 OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph,
840 "Show callgraph from reference event"),
21394d94
KL
841 OPT_INTEGER(0, "socket-filter", &report.socket_filter,
842 "only show processor socket that match with this filter"),
053a3989
NK
843 OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
844 "Show raw trace event output (do not use print fmt or plugins)"),
4251446d
NK
845 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
846 "Show entries in a hierarchy"),
175b968b
ACM
847 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
848 "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
849 stdio__config_color, "always"),
46690a80
DA
850 OPT_STRING(0, "time", &report.time_str, "str",
851 "Time span of interest (start,stop)"),
f3a60646
JY
852 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
853 "Show inline function"),
53cb8bc2 854 OPT_END()
d20deb64 855 };
f5fc1412
JO
856 struct perf_data_file file = {
857 .mode = PERF_DATA_MODE_READ,
858 };
a635fc51
ACM
859 int ret = hists__init();
860
861 if (ret < 0)
862 return ret;
53cb8bc2 863
ecc4c561
ACM
864 ret = perf_config(report__config, &report);
865 if (ret)
866 return ret;
00c7e1f1 867
655000e7 868 argc = parse_options(argc, argv, options, report_usage, 0);
b3f38fc2
NK
869 if (argc) {
870 /*
871 * Special case: if there's an argument left then assume that
872 * it's a symbol filter:
873 */
874 if (argc > 1)
875 usage_with_options(report_usage, options);
876
877 report.symbol_filter_str = argv[0];
878 }
655000e7 879
27fafab5
NK
880 if (quiet)
881 perf_quiet_option();
882
36c8bb56
LZ
883 if (symbol_conf.vmlinux_name &&
884 access(symbol_conf.vmlinux_name, R_OK)) {
885 pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name);
886 return -EINVAL;
887 }
888 if (symbol_conf.kallsyms_name &&
889 access(symbol_conf.kallsyms_name, R_OK)) {
890 pr_err("Invalid file: %s\n", symbol_conf.kallsyms_name);
891 return -EINVAL;
892 }
893
fa372aae 894 if (report.use_stdio)
8b9e74eb 895 use_browser = 0;
fa372aae 896 else if (report.use_tui)
8b9e74eb 897 use_browser = 1;
c31a9457
PE
898 else if (report.use_gtk)
899 use_browser = 2;
8b9e74eb 900
fa372aae 901 if (report.inverted_callchain)
d797fdc5 902 callchain_param.order = ORDER_CALLER;
792aeafa
NK
903 if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
904 callchain_param.order = ORDER_CALLER;
d797fdc5 905
188bb5e2
AH
906 if (itrace_synth_opts.callchain &&
907 (int)itrace_synth_opts.callchain_sz > report.max_stack)
908 report.max_stack = itrace_synth_opts.callchain_sz;
909
70cb4e96 910 if (!input_name || !strlen(input_name)) {
efad1415 911 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
70cb4e96 912 input_name = "-";
efad1415 913 else
70cb4e96 914 input_name = "perf.data";
efad1415 915 }
ad0de097 916
f5fc1412 917 file.path = input_name;
2059fc7a 918 file.force = symbol_conf.force;
f5fc1412 919
ad0de097 920repeat:
f5fc1412 921 session = perf_session__new(&file, false, &report.tool);
993ac88d 922 if (session == NULL)
52e02834 923 return -1;
993ac88d 924
94786b67
JO
925 if (report.queue_size) {
926 ordered_events__set_alloc_size(&session->ordered_events,
927 report.queue_size);
928 }
929
520a2ebc
AH
930 session->itrace_synth_opts = &itrace_synth_opts;
931
993ac88d
SE
932 report.session = session;
933
934 has_br_stack = perf_header__has_feat(&session->header,
935 HEADER_BRANCH_STACK);
efad1415 936
fb9fab66
AH
937 if (itrace_synth_opts.last_branch)
938 has_br_stack = true;
939
f9a7be7c
JY
940 if (has_br_stack && branch_call_mode)
941 symbol_conf.show_branchflag_count = true;
942
fa94c36c
AK
943 /*
944 * Branch mode is a tristate:
945 * -1 means default, so decide based on the file having branch data.
946 * 0/1 means the user chose a mode.
947 */
948 if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
fefd2d96 949 !branch_call_mode) {
55369fc1 950 sort__mode = SORT_MODE__BRANCH;
793aaaab
NK
951 symbol_conf.cumulate_callchain = false;
952 }
fa94c36c 953 if (branch_call_mode) {
09a6a1b0 954 callchain_param.key = CCKEY_ADDRESS;
fa94c36c
AK
955 callchain_param.branch_callstack = 1;
956 symbol_conf.use_callchain = true;
957 callchain_register_param(&callchain_param);
958 if (sort_order == NULL)
959 sort_order = "srcline,symbol,dso";
960 }
993ac88d 961
f4f7e28d 962 if (report.mem_mode) {
55369fc1 963 if (sort__mode == SORT_MODE__BRANCH) {
a4210141 964 pr_err("branch and mem mode incompatible\n");
f4f7e28d
SE
965 goto error;
966 }
afab87b9 967 sort__mode = SORT_MODE__MEMORY;
793aaaab 968 symbol_conf.cumulate_callchain = false;
f4f7e28d 969 }
a68c2c58 970
4251446d
NK
971 if (symbol_conf.report_hierarchy) {
972 /* disable incompatible options */
4251446d
NK
973 symbol_conf.cumulate_callchain = false;
974
975 if (field_order) {
976 pr_err("Error: --hierarchy and --fields options cannot be used together\n");
977 parse_options_usage(report_usage, options, "F", 1);
978 parse_options_usage(NULL, options, "hierarchy", 0);
979 goto error;
980 }
981
52225036 982 perf_hpp_list.need_collapse = true;
4251446d
NK
983 }
984
b138f42e
NK
985 /* Force tty output for header output and per-thread stat. */
986 if (report.header || report.header_only || report.show_threads)
5cfe2c82
JO
987 use_browser = 0;
988
4bceffbc
NK
989 if (strcmp(input_name, "-") != 0)
990 setup_browser(true);
22af969e 991 else
4bceffbc 992 use_browser = 0;
4bceffbc 993
9887804d
JO
994 if (setup_sorting(session->evlist) < 0) {
995 if (sort_order)
996 parse_options_usage(report_usage, options, "s", 1);
997 if (field_order)
998 parse_options_usage(sort_order ? NULL : report_usage,
999 options, "F", 1);
1000 goto error;
1001 }
1002
27fafab5 1003 if ((report.header || report.header_only) && !quiet) {
5cfe2c82
JO
1004 perf_session__fprintf_info(session, stdout,
1005 report.show_full_info);
07a716ff
TS
1006 if (report.header_only) {
1007 ret = 0;
1008 goto error;
1009 }
27fafab5 1010 } else if (use_browser == 0 && !quiet) {
5cfe2c82
JO
1011 fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
1012 stdout);
1013 }
1014
ef7b93a1 1015 /*
6692c262 1016 * Only in the TUI browser we are doing integrated annotation,
ef7b93a1
ACM
1017 * so don't allocate extra space that won't be used in the stdio
1018 * implementation.
1019 */
b9ce0c99 1020 if (ui__has_annotation()) {
b01141f4
ACM
1021 ret = symbol__annotation_init();
1022 if (ret < 0)
1023 goto error;
80d50cae
ACM
1024 /*
1025 * For searching by name on the "Browse map details".
1026 * providing it only in verbose mode not to bloat too
1027 * much struct symbol.
1028 */
bb963e16 1029 if (verbose > 0) {
80d50cae
ACM
1030 /*
1031 * XXX: Need to provide a less kludgy way to ask for
1032 * more space per symbol, the u32 is for the index on
1033 * the ui browser.
1034 * See symbol__browser_index.
1035 */
1036 symbol_conf.priv_size += sizeof(u32);
1037 symbol_conf.sort_by_name = true;
1038 }
1039 }
655000e7 1040
0a7e6d1b 1041 if (symbol__init(&session->header.env) < 0)
993ac88d 1042 goto error;
53cb8bc2 1043
46690a80
DA
1044 if (perf_time__parse_str(&report.ptime, report.time_str) != 0) {
1045 pr_err("Invalid time string\n");
1046 return -EINVAL;
1047 }
1048
08e71542 1049 sort__setup_elide(stdout);
25903407 1050
993ac88d 1051 ret = __cmd_report(&report);
ad0de097
FT
1052 if (ret == K_SWITCH_INPUT_DATA) {
1053 perf_session__delete(session);
1054 goto repeat;
1055 } else
1056 ret = 0;
1057
993ac88d
SE
1058error:
1059 perf_session__delete(session);
1060 return ret;
53cb8bc2 1061}