builtin-report.c 21.3 KB
Newer Older
1 2 3 4 5 6 7
/*
 * builtin-report.c
 *
 * Builtin report command: Analyze the perf.data input file,
 * look up and read DSOs and symbol information and display
 * a histogram of results, along various sorting keys.
 */
8
#include "builtin.h"
9

10
#include "util/util.h"
11
#include "util/cache.h"
12

13
#include "util/annotate.h"
14
#include "util/color.h"
15
#include <linux/list.h>
16
#include <linux/rbtree.h>
17
#include "util/symbol.h"
18
#include "util/callchain.h"
19
#include "util/strlist.h"
20
#include "util/values.h"
21

22
#include "perf.h"
23
#include "util/debug.h"
24 25
#include "util/evlist.h"
#include "util/evsel.h"
26
#include "util/header.h"
27
#include "util/session.h"
28
#include "util/tool.h"
29 30 31 32

#include "util/parse-options.h"
#include "util/parse-events.h"

33
#include "util/thread.h"
34
#include "util/sort.h"
35
#include "util/hist.h"
36
#include "util/data.h"
37
#include "arch/common.h"
38

39
#include <dlfcn.h>
40 41
#include <linux/bitmap.h>

42
struct report {
43
	struct perf_tool	tool;
44
	struct perf_session	*session;
45
	bool			force, use_tui, use_gtk, use_stdio;
46 47 48 49 50
	bool			hide_unresolved;
	bool			dont_use_callchains;
	bool			show_full_info;
	bool			show_threads;
	bool			inverted_callchain;
51
	bool			mem_mode;
52 53
	bool			header;
	bool			header_only;
54
	int			max_stack;
55 56 57
	struct perf_read_values	show_threads_values;
	const char		*pretty_printing_style;
	const char		*cpu_list;
58
	const char		*symbol_filter_str;
59
	float			min_percent;
60
	u64			nr_entries;
61
	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
62
};
63

64
static int report__config(const char *var, const char *value, void *cb)
65 66 67 68 69
{
	if (!strcmp(var, "report.group")) {
		symbol_conf.event_group = perf_config_bool(var, value);
		return 0;
	}
70
	if (!strcmp(var, "report.percent-limit")) {
71
		struct report *rep = cb;
72 73 74
		rep->min_percent = strtof(value, NULL);
		return 0;
	}
75 76 77 78

	return perf_default_config(var, value, cb);
}

79 80
static void report__inc_stats(struct report *rep,
			      struct hist_entry *he __maybe_unused)
81 82
{
	/*
83 84
	 * We cannot access @he at this time.  Just assume it's a new entry.
	 * It'll be fixed once we have a callback mechanism in hist_iter.
85
	 */
86
	rep->nr_entries++;
87 88
}

89
static int process_sample_event(struct perf_tool *tool,
90
				union perf_event *event,
91
				struct perf_sample *sample,
92
				struct perf_evsel *evsel,
93
				struct machine *machine)
94
{
95
	struct report *rep = container_of(tool, struct report, tool);
96
	struct addr_location al;
97 98 99
	struct hist_entry_iter iter = {
		.hide_unresolved = rep->hide_unresolved,
	};
100
	int ret;
101

102
	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
103 104
		pr_debug("problem processing %d event, skipping it.\n",
			 event->header.type);
105 106
		return -1;
	}
107

108
	if (rep->hide_unresolved && al.sym == NULL)
109
		return 0;
110

111
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
112 113
		return 0;

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
	if (sort__mode == SORT_MODE__BRANCH)
		iter.ops = &hist_iter_branch;
	else if (rep->mem_mode)
		iter.ops = &hist_iter_mem;
	else
		iter.ops = &hist_iter_normal;

	if (al.map != NULL)
		al.map->dso->hit = 1;

	report__inc_stats(rep, NULL);

	ret = hist_entry_iter__add(&iter, &al, evsel, sample, rep->max_stack);
	if (ret < 0)
		pr_debug("problem adding hist entry, skipping event\n");
129

130
	return ret;
131
}
I
Ingo Molnar 已提交
132

133
static int process_read_event(struct perf_tool *tool,
134
			      union perf_event *event,
135
			      struct perf_sample *sample __maybe_unused,
136
			      struct perf_evsel *evsel,
137
			      struct machine *machine __maybe_unused)
138
{
139
	struct report *rep = container_of(tool, struct report, tool);
140

141
	if (rep->show_threads) {
142
		const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
143
		perf_read_values_add_value(&rep->show_threads_values,
144 145 146 147 148 149
					   event->read.pid, event->read.tid,
					   event->read.id,
					   name,
					   event->read.value);
	}

150
	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
151
		    evsel ? perf_evsel__name(evsel) : "FAIL",
152
		    event->read.value);
153 154 155 156

	return 0;
}

157
/* For pipe mode, sample_type is not currently set */
158
static int report__setup_sample_type(struct report *rep)
159
{
160 161 162
	struct perf_session *session = rep->session;
	u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
	bool is_pipe = perf_data_file__is_pipe(session->file);
163

164
	if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
165
		if (sort__has_parent) {
166
			ui__error("Selected --sort parent, but no "
167 168
				    "callchain data. Did you call "
				    "'perf record' without -g?\n");
169
			return -EINVAL;
170
		}
171
		if (symbol_conf.use_callchain) {
172
			ui__error("Selected -g but no callchain data. Did "
173
				    "you call 'perf record' without -g?\n");
174
			return -1;
175
		}
176 177
	} else if (!rep->dont_use_callchains &&
		   callchain_param.mode != CHAIN_NONE &&
178
		   !symbol_conf.use_callchain) {
179
			symbol_conf.use_callchain = true;
180
			if (callchain_register_param(&callchain_param) < 0) {
181
				ui__error("Can't register callchain params.\n");
182
				return -EINVAL;
183
			}
184 185
	}

186
	if (sort__mode == SORT_MODE__BRANCH) {
187
		if (!is_pipe &&
188
		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
189 190
			ui__error("Selected -b but no branch data. "
				  "Did you call perf record without -b?\n");
191 192 193 194
			return -1;
		}
	}

195 196
	return 0;
}
197

198
static void sig_handler(int sig __maybe_unused)
199 200 201 202
{
	session_done = 1;
}

203
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
204 205 206 207
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
208 209 210
	unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
	u64 nr_events = hists->stats.total_period;
	struct perf_evsel *evsel = hists_to_evsel(hists);
211 212 213
	char buf[512];
	size_t size = sizeof(buf);

214 215 216 217 218
	if (symbol_conf.filter_relative) {
		nr_samples = hists->stats.nr_non_filtered_samples;
		nr_events = hists->stats.total_non_filtered_period;
	}

219
	if (perf_evsel__is_group_event(evsel)) {
220 221 222 223 224 225
		struct perf_evsel *pos;

		perf_evsel__group_desc(evsel, buf, size);
		evname = buf;

		for_each_group_member(pos, evsel) {
226 227 228 229 230 231 232
			if (symbol_conf.filter_relative) {
				nr_samples += pos->hists.stats.nr_non_filtered_samples;
				nr_events += pos->hists.stats.total_non_filtered_period;
			} else {
				nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
				nr_events += pos->hists.stats.total_period;
			}
233 234
		}
	}
235

236 237
	nr_samples = convert_unit(nr_samples, &unit);
	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
238
	if (evname != NULL)
239 240
		ret += fprintf(fp, " of event '%s'", evname);

241 242 243 244 245
	if (rep->mem_mode) {
		ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
		ret += fprintf(fp, "\n# Sort order   : %s", sort_order);
	} else
		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
246 247 248
	return ret + fprintf(fp, "\n#\n");
}

249
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
250
					 struct report *rep,
251
					 const char *help)
252
{
253
	struct perf_evsel *pos;
254

255
	evlist__for_each(evlist, pos) {
256
		struct hists *hists = &pos->hists;
257
		const char *evname = perf_evsel__name(pos);
258

259 260 261 262
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

263
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
264
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
265 266 267 268 269 270 271
		fprintf(stdout, "\n\n");
	}

	if (sort_order == default_sort_order &&
	    parent_pattern == default_parent_pattern) {
		fprintf(stdout, "#\n# (%s)\n#\n", help);

272 273 274
		if (rep->show_threads) {
			bool style = !strcmp(rep->pretty_printing_style, "raw");
			perf_read_values_display(stdout, &rep->show_threads_values,
275
						 style);
276
			perf_read_values_destroy(&rep->show_threads_values);
277 278 279 280 281 282
		}
	}

	return 0;
}

283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
static void report__warn_kptr_restrict(const struct report *rep)
{
	struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
	struct kmap *kernel_kmap = map__kmap(kernel_map);

	if (kernel_map == NULL ||
	    (kernel_map->dso->hit &&
	     (kernel_kmap->ref_reloc_sym == NULL ||
	      kernel_kmap->ref_reloc_sym->addr == 0))) {
		const char *desc =
		    "As no suitable kallsyms nor vmlinux was found, kernel samples\n"
		    "can't be resolved.";

		if (kernel_map) {
			const struct dso *kdso = kernel_map->dso;
			if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) {
				desc = "If some relocation was applied (e.g. "
				       "kexec) symbols may be misresolved.";
			}
		}

		ui__warning(
"Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n"
"Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n"
"Samples in kernel modules can't be resolved as well.\n\n",
		desc);
	}
}

312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
static int report__gtk_browse_hists(struct report *rep, const char *help)
{
	int (*hist_browser)(struct perf_evlist *evlist, const char *help,
			    struct hist_browser_timer *timer, float min_pcnt);

	hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists");

	if (hist_browser == NULL) {
		ui__error("GTK browser not found!\n");
		return -1;
	}

	return hist_browser(rep->session->evlist, help, NULL, rep->min_percent);
}

static int report__browse_hists(struct report *rep)
{
	int ret;
	struct perf_session *session = rep->session;
	struct perf_evlist *evlist = session->evlist;
	const char *help = "For a higher level overview, try: perf report --sort comm,dso";

	switch (use_browser) {
	case 1:
		ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
						    rep->min_percent,
						    &session->header.env);
		/*
		 * Usually "ret" is the last pressed key, and we only
		 * care if the key notifies us to switch data file.
		 */
		if (ret != K_SWITCH_INPUT_DATA)
			ret = 0;
		break;
	case 2:
		ret = report__gtk_browse_hists(rep, help);
		break;
	default:
		ret = perf_evlist__tty_browse_hists(evlist, rep, help);
		break;
	}

	return ret;
}

357
static void report__collapse_hists(struct report *rep)
358 359 360 361
{
	struct ui_progress prog;
	struct perf_evsel *pos;

362
	ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
363

364
	evlist__for_each(rep->session->evlist, pos) {
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
		struct hists *hists = &pos->hists;

		if (pos->idx == 0)
			hists->symbol_filter_str = rep->symbol_filter_str;

		hists__collapse_resort(hists, &prog);

		/* Non-group events are considered as leader */
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos)) {
			struct hists *leader_hists = &pos->leader->hists;

			hists__match(leader_hists, hists);
			hists__link(leader_hists, hists);
		}
	}

	ui_progress__finish();
}

385
static int __cmd_report(struct report *rep)
386
{
387
	int ret;
388
	struct perf_session *session = rep->session;
389
	struct perf_evsel *pos;
390
	struct perf_data_file *file = session->file;
391

392 393
	signal(SIGINT, sig_handler);

394 395 396
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
397
		if (ret)
398
			return ret;
399 400
	}

401 402
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
403

404
	ret = report__setup_sample_type(rep);
405
	if (ret)
406
		return ret;
407

408
	ret = perf_session__process_events(session, &rep->tool);
409
	if (ret)
410
		return ret;
411

412
	report__warn_kptr_restrict(rep);
413

414 415 416
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
417

418 419
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
420

421 422 423 424
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
			return 0;
		}
425 426
	}

427
	report__collapse_hists(rep);
428

429 430 431
	if (session_done())
		return 0;

432
	if (rep->nr_entries == 0) {
433
		ui__error("The %s file has no samples!\n", file->path);
434
		return 0;
435 436
	}

437
	evlist__for_each(session->evlist, pos)
438 439
		hists__output_resort(&pos->hists);

440
	return report__browse_hists(rep);
441 442
}

443
static int
444
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
445
{
446
	struct report *rep = (struct report *)opt->value;
447

448 449 450 451
	/*
	 * --no-call-graph
	 */
	if (unset) {
452
		rep->dont_use_callchains = true;
453 454 455
		return 0;
	}

456
	return parse_callchain_report_opt(arg);
457 458
}

459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
int
report_parse_ignore_callees_opt(const struct option *opt __maybe_unused,
				const char *arg, int unset __maybe_unused)
{
	if (arg) {
		int err = regcomp(&ignore_callees_regex, arg, REG_EXTENDED);
		if (err) {
			char buf[BUFSIZ];
			regerror(err, &ignore_callees_regex, buf, sizeof(buf));
			pr_err("Invalid --ignore-callees regex: %s\n%s", arg, buf);
			return -1;
		}
		have_ignore_callees = 1;
	}

	return 0;
}

477
static int
478 479
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
480
{
481 482 483
	int *branch_mode = opt->value;

	*branch_mode = !unset;
484 485 486
	return 0;
}

487 488 489 490
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
491
	struct report *rep = opt->value;
492 493 494 495 496

	rep->min_percent = strtof(str, NULL);
	return 0;
}

497
int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
498
{
499
	struct perf_session *session;
500
	struct stat st;
501
	bool has_br_stack = false;
502
	int branch_mode = -1;
503
	int ret = -1;
504 505
	char callchain_default_opt[] = "fractal,0.5,callee";
	const char * const report_usage[] = {
N
Namhyung Kim 已提交
506
		"perf report [<options>]",
507 508
		NULL
	};
509
	struct report report = {
510
		.tool = {
511 512
			.sample		 = process_sample_event,
			.mmap		 = perf_event__process_mmap,
513
			.mmap2		 = perf_event__process_mmap2,
514
			.comm		 = perf_event__process_comm,
515 516
			.exit		 = perf_event__process_exit,
			.fork		 = perf_event__process_fork,
517 518 519 520 521 522 523 524
			.lost		 = perf_event__process_lost,
			.read		 = process_read_event,
			.attr		 = perf_event__process_attr,
			.tracing_data	 = perf_event__process_tracing_data,
			.build_id	 = perf_event__process_build_id,
			.ordered_samples = true,
			.ordering_requires_timestamps = true,
		},
525
		.max_stack		 = PERF_MAX_STACK_DEPTH,
526 527 528
		.pretty_printing_style	 = "normal",
	};
	const struct option options[] = {
529
	OPT_STRING('i', "input", &input_name, "file",
530
		    "input file name"),
531
	OPT_INCR('v', "verbose", &verbose,
532
		    "be more verbose (show symbol address, etc)"),
533 534
	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
		    "dump raw trace in ASCII"),
535 536
	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
		   "file", "vmlinux pathname"),
537 538
	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
		   "file", "kallsyms pathname"),
539
	OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"),
540
	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
541
		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
542
	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
543
		    "Show a column with the number of samples"),
544
	OPT_BOOLEAN('T', "threads", &report.show_threads,
545
		    "Show per-thread event counters"),
546
	OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
547
		   "pretty printing style key: normal raw"),
548
	OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
549
	OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
550 551
	OPT_BOOLEAN(0, "stdio", &report.use_stdio,
		    "Use the stdio interface"),
552 553 554
	OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
	OPT_BOOLEAN(0, "header-only", &report.header_only,
		    "Show only data header."),
555
	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
556 557
		   "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..."
		   " Please refer the man page for the complete list."),
558 559
	OPT_STRING('F', "fields", &field_order, "key[,keys...]",
		   "output field(s): overhead, period, sample plus all of sort keys"),
560 561
	OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
		    "Show sample percentage for different cpu modes"),
562 563
	OPT_STRING('p', "parent", &parent_pattern, "regex",
		   "regex filter to identify parent, see: '--sort parent'"),
564
	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
565
		    "Only display entries with parent-match"),
566
	OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
567
		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
568
		     "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt),
569 570 571 572
	OPT_INTEGER(0, "max-stack", &report.max_stack,
		    "Set the maximum stack depth when parsing the callchain, "
		    "anything beyond the specified depth will be ignored. "
		    "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
573 574
	OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
		    "alias for inverted call graph"),
575 576 577
	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
		   "ignore callees of these functions in call graphs",
		   report_parse_ignore_callees_opt),
578
	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
579
		   "only consider symbols in these dsos"),
580
	OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
581
		   "only consider symbols in these comms"),
582
	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
583
		   "only consider these symbols"),
584 585
	OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
		   "only show symbols that (partially) match with this filter"),
586
	OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
587 588
		   "width[,width...]",
		   "don't try to adjust column width, use these fixed values"),
589
	OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
590 591
		   "separator for columns, no spaces will be added between "
		   "columns '.' is reserved."),
592
	OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
593
		    "Only display entries resolved to a symbol"),
594 595
	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
		    "Look for files with symbols relative to this directory"),
596
	OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
597 598
		   "list of cpus to profile"),
	OPT_BOOLEAN('I', "show-info", &report.show_full_info,
599
		    "Display extended information about perf.data file"),
600 601 602 603
	OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
		    "Interleave source code with assembly code (default)"),
	OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
		    "Display raw encoding of assembly instructions (default)"),
604 605
	OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
606 607
	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
		    "Show a column with the sum of periods"),
N
Namhyung Kim 已提交
608 609
	OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
		    "Show event group information together"),
610
	OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
611
		    "use branch records for histogram filling", parse_branch_mode),
612 613
	OPT_STRING(0, "objdump", &objdump_path, "path",
		   "objdump binary to use for disassembly and annotations"),
614 615
	OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
		    "Disable symbol demangling"),
616
	OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
617 618
	OPT_CALLBACK(0, "percent-limit", &report, "percent",
		     "Don't show entries under that percent", parse_percent_limit),
619
	OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
N
Namhyung Kim 已提交
620
		     "how to display percentage of filtered entries", parse_filter_percentage),
621
	OPT_END()
622
	};
623 624 625
	struct perf_data_file file = {
		.mode  = PERF_DATA_MODE_READ,
	};
626

627
	perf_config(report__config, &report);
628

629 630
	argc = parse_options(argc, argv, options, report_usage, 0);

631
	if (report.use_stdio)
632
		use_browser = 0;
633
	else if (report.use_tui)
634
		use_browser = 1;
635 636
	else if (report.use_gtk)
		use_browser = 2;
637

638
	if (report.inverted_callchain)
639 640
		callchain_param.order = ORDER_CALLER;

641
	if (!input_name || !strlen(input_name)) {
642
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
643
			input_name = "-";
644
		else
645
			input_name = "perf.data";
646
	}
647

648 649 650
	file.path  = input_name;
	file.force = report.force;

651
repeat:
652
	session = perf_session__new(&file, false, &report.tool);
653 654 655 656 657 658 659
	if (session == NULL)
		return -ENOMEM;

	report.session = session;

	has_br_stack = perf_header__has_feat(&session->header,
					     HEADER_BRANCH_STACK);
660

661 662
	if (branch_mode == -1 && has_br_stack)
		sort__mode = SORT_MODE__BRANCH;
663

664
	if (report.mem_mode) {
665
		if (sort__mode == SORT_MODE__BRANCH) {
666
			pr_err("branch and mem mode incompatible\n");
667 668
			goto error;
		}
669
		sort__mode = SORT_MODE__MEMORY;
670
	}
671

672
	if (setup_sorting() < 0) {
673 674 675 676 677
		if (sort_order)
			parse_options_usage(report_usage, options, "s", 1);
		if (field_order)
			parse_options_usage(sort_order ? NULL : report_usage,
					    options, "F", 1);
678 679
		goto error;
	}
680

681 682 683 684
	/* Force tty output for header output. */
	if (report.header || report.header_only)
		use_browser = 0;

685 686
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
687
	else
688 689
		use_browser = 0;

690 691 692 693 694 695 696 697 698 699
	if (report.header || report.header_only) {
		perf_session__fprintf_info(session, stdout,
					   report.show_full_info);
		if (report.header_only)
			return 0;
	} else if (use_browser == 0) {
		fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
		      stdout);
	}

700
	/*
701
	 * Only in the TUI browser we are doing integrated annotation,
702 703 704
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
705
	if (ui__has_annotation()) {
706
		symbol_conf.priv_size = sizeof(struct annotation);
707 708
		machines__set_symbol_filter(&session->machines,
					    symbol__annotate_init);
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
		/*
 		 * For searching by name on the "Browse map details".
 		 * providing it only in verbose mode not to bloat too
 		 * much struct symbol.
 		 */
		if (verbose) {
			/*
			 * XXX: Need to provide a less kludgy way to ask for
			 * more space per symbol, the u32 is for the index on
			 * the ui browser.
			 * See symbol__browser_index.
			 */
			symbol_conf.priv_size += sizeof(u32);
			symbol_conf.sort_by_name = true;
		}
	}
725

726
	if (symbol__init() < 0)
727
		goto error;
728

729 730 731 732 733 734 735 736 737 738
	if (argc) {
		/*
		 * Special case: if there's an argument left then assume that
		 * it's a symbol filter:
		 */
		if (argc > 1)
			usage_with_options(report_usage, options);

		report.symbol_filter_str = argv[0];
	}
739

740
	sort__setup_elide(stdout);
741

742
	ret = __cmd_report(&report);
743 744 745 746 747 748
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

749 750 751
error:
	perf_session__delete(session);
	return ret;
752
}