builtin-report.c 25.9 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 40
#include "util/auxtrace.h"

41
#include <dlfcn.h>
42 43
#include <linux/bitmap.h>

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

67
static int report__config(const char *var, const char *value, void *cb)
68
{
69 70
	struct report *rep = cb;

71 72 73 74
	if (!strcmp(var, "report.group")) {
		symbol_conf.event_group = perf_config_bool(var, value);
		return 0;
	}
75 76 77 78
	if (!strcmp(var, "report.percent-limit")) {
		rep->min_percent = strtof(value, NULL);
		return 0;
	}
79 80 81 82
	if (!strcmp(var, "report.children")) {
		symbol_conf.cumulate_callchain = perf_config_bool(var, value);
		return 0;
	}
83 84 85 86
	if (!strcmp(var, "report.queue-size")) {
		rep->queue_size = perf_config_u64(var, value);
		return 0;
	}
87 88 89 90

	return perf_default_config(var, value, cb);
}

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
static int hist_iter__report_callback(struct hist_entry_iter *iter,
				      struct addr_location *al, bool single,
				      void *arg)
{
	int err = 0;
	struct report *rep = arg;
	struct hist_entry *he = iter->he;
	struct perf_evsel *evsel = iter->evsel;
	struct mem_info *mi;
	struct branch_info *bi;

	if (!ui__has_annotation())
		return 0;

	if (sort__mode == SORT_MODE__BRANCH) {
		bi = he->branch_info;
		err = addr_map_symbol__inc_samples(&bi->from, evsel->idx);
		if (err)
			goto out;

		err = addr_map_symbol__inc_samples(&bi->to, evsel->idx);

	} else if (rep->mem_mode) {
		mi = he->mem_info;
		err = addr_map_symbol__inc_samples(&mi->daddr, evsel->idx);
		if (err)
			goto out;

		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);

	} else if (symbol_conf.cumulate_callchain) {
		if (single)
			err = hist_entry__inc_addr_samples(he, evsel->idx,
							   al->addr);
	} else {
		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
	}

out:
	return err;
131 132
}

133
static int process_sample_event(struct perf_tool *tool,
134
				union perf_event *event,
135
				struct perf_sample *sample,
136
				struct perf_evsel *evsel,
137
				struct machine *machine)
138
{
139
	struct report *rep = container_of(tool, struct report, tool);
140
	struct addr_location al;
141
	struct hist_entry_iter iter = {
142 143 144 145
		.evsel 			= evsel,
		.sample 		= sample,
		.hide_unresolved 	= rep->hide_unresolved,
		.add_entry_cb 		= hist_iter__report_callback,
146
	};
147
	int ret = 0;
148

149
	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
150 151
		pr_debug("problem processing %d event, skipping it.\n",
			 event->header.type);
152 153
		return -1;
	}
154

155
	if (rep->hide_unresolved && al.sym == NULL)
156
		goto out_put;
157

158
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
159
		goto out_put;
160

161 162 163 164
	if (sort__mode == SORT_MODE__BRANCH)
		iter.ops = &hist_iter_branch;
	else if (rep->mem_mode)
		iter.ops = &hist_iter_mem;
165 166
	else if (symbol_conf.cumulate_callchain)
		iter.ops = &hist_iter_cumulative;
167 168 169 170 171 172
	else
		iter.ops = &hist_iter_normal;

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

173
	ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep);
174 175
	if (ret < 0)
		pr_debug("problem adding hist entry, skipping event\n");
176 177
out_put:
	addr_location__put(&al);
178
	return ret;
179
}
I
Ingo Molnar 已提交
180

181
static int process_read_event(struct perf_tool *tool,
182
			      union perf_event *event,
183
			      struct perf_sample *sample __maybe_unused,
184
			      struct perf_evsel *evsel,
185
			      struct machine *machine __maybe_unused)
186
{
187
	struct report *rep = container_of(tool, struct report, tool);
188

189
	if (rep->show_threads) {
190
		const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
191
		perf_read_values_add_value(&rep->show_threads_values,
192 193 194 195 196 197
					   event->read.pid, event->read.tid,
					   event->read.id,
					   name,
					   event->read.value);
	}

198
	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
199
		    evsel ? perf_evsel__name(evsel) : "FAIL",
200
		    event->read.value);
201 202 203 204

	return 0;
}

205
/* For pipe mode, sample_type is not currently set */
206
static int report__setup_sample_type(struct report *rep)
207
{
208 209 210
	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);
211

212
	if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
213
		if (sort__has_parent) {
214
			ui__error("Selected --sort parent, but no "
215 216
				    "callchain data. Did you call "
				    "'perf record' without -g?\n");
217
			return -EINVAL;
218
		}
219
		if (symbol_conf.use_callchain) {
220 221 222
			ui__error("Selected -g or --branch-history but no "
				  "callchain data. Did\n"
				  "you call 'perf record' without -g?\n");
223
			return -1;
224
		}
225 226
	} else if (!rep->dont_use_callchains &&
		   callchain_param.mode != CHAIN_NONE &&
227
		   !symbol_conf.use_callchain) {
228
			symbol_conf.use_callchain = true;
229
			if (callchain_register_param(&callchain_param) < 0) {
230
				ui__error("Can't register callchain params.\n");
231
				return -EINVAL;
232
			}
233 234
	}

235 236 237 238 239 240 241 242
	if (symbol_conf.cumulate_callchain) {
		/* Silently ignore if callchain is missing */
		if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
			symbol_conf.cumulate_callchain = false;
			perf_hpp__cancel_cumulate();
		}
	}

243
	if (sort__mode == SORT_MODE__BRANCH) {
244
		if (!is_pipe &&
245
		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
246 247
			ui__error("Selected -b but no branch data. "
				  "Did you call perf record without -b?\n");
248 249 250 251
			return -1;
		}
	}

252 253 254 255
	if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
		if ((sample_type & PERF_SAMPLE_REGS_USER) &&
		    (sample_type & PERF_SAMPLE_STACK_USER))
			callchain_param.record_mode = CALLCHAIN_DWARF;
256 257
		else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
			callchain_param.record_mode = CALLCHAIN_LBR;
258 259 260
		else
			callchain_param.record_mode = CALLCHAIN_FP;
	}
261 262
	return 0;
}
263

264
static void sig_handler(int sig __maybe_unused)
265 266 267 268
{
	session_done = 1;
}

269
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
270 271 272 273
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
274 275 276
	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);
277 278 279
	char buf[512];
	size_t size = sizeof(buf);

280 281 282 283 284
	if (symbol_conf.filter_relative) {
		nr_samples = hists->stats.nr_non_filtered_samples;
		nr_events = hists->stats.total_non_filtered_period;
	}

285
	if (perf_evsel__is_group_event(evsel)) {
286 287 288 289 290 291
		struct perf_evsel *pos;

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

		for_each_group_member(pos, evsel) {
292 293
			const struct hists *pos_hists = evsel__hists(pos);

294
			if (symbol_conf.filter_relative) {
295 296
				nr_samples += pos_hists->stats.nr_non_filtered_samples;
				nr_events += pos_hists->stats.total_non_filtered_period;
297
			} else {
298 299
				nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
				nr_events += pos_hists->stats.total_period;
300
			}
301 302
		}
	}
303

304 305
	nr_samples = convert_unit(nr_samples, &unit);
	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
306
	if (evname != NULL)
307 308
		ret += fprintf(fp, " of event '%s'", evname);

309 310
	if (rep->mem_mode) {
		ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
311
		ret += fprintf(fp, "\n# Sort order   : %s", sort_order ? : default_mem_sort_order);
312 313
	} else
		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
314 315 316
	return ret + fprintf(fp, "\n#\n");
}

317
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
318
					 struct report *rep,
319
					 const char *help)
320
{
321
	struct perf_evsel *pos;
322

323
	fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples);
324
	evlist__for_each(evlist, pos) {
325
		struct hists *hists = evsel__hists(pos);
326
		const char *evname = perf_evsel__name(pos);
327

328 329 330 331
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

332
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
333
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
334 335 336
		fprintf(stdout, "\n\n");
	}

337
	if (sort_order == NULL &&
338
	    parent_pattern == default_parent_pattern)
339 340
		fprintf(stdout, "#\n# (%s)\n#\n", help);

341 342 343 344 345
	if (rep->show_threads) {
		bool style = !strcmp(rep->pretty_printing_style, "raw");
		perf_read_values_display(stdout, &rep->show_threads_values,
					 style);
		perf_read_values_destroy(&rep->show_threads_values);
346 347 348 349 350
	}

	return 0;
}

351 352 353
static void report__warn_kptr_restrict(const struct report *rep)
{
	struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
354
	struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379

	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);
	}
}

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
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;
}

425
static void report__collapse_hists(struct report *rep)
426 427 428 429
{
	struct ui_progress prog;
	struct perf_evsel *pos;

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

432
	evlist__for_each(rep->session->evlist, pos) {
433
		struct hists *hists = evsel__hists(pos);
434 435 436 437 438 439 440 441 442

		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)) {
443
			struct hists *leader_hists = evsel__hists(pos->leader);
444 445 446 447 448 449 450 451 452

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

	ui_progress__finish();
}

453 454 455 456 457 458 459 460 461 462 463 464 465
static void report__output_resort(struct report *rep)
{
	struct ui_progress prog;
	struct perf_evsel *pos;

	ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");

	evlist__for_each(rep->session->evlist, pos)
		hists__output_resort(evsel__hists(pos), &prog);

	ui_progress__finish();
}

466
static int __cmd_report(struct report *rep)
467
{
468
	int ret;
469
	struct perf_session *session = rep->session;
470
	struct perf_evsel *pos;
471
	struct perf_data_file *file = session->file;
472

473 474
	signal(SIGINT, sig_handler);

475 476 477
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
478
		if (ret)
479
			return ret;
480 481
	}

482 483
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
484

485
	ret = report__setup_sample_type(rep);
486
	if (ret)
487
		return ret;
488

489
	ret = perf_session__process_events(session);
490
	if (ret)
491
		return ret;
492

493
	report__warn_kptr_restrict(rep);
494

495 496 497
	evlist__for_each(session->evlist, pos)
		rep->nr_entries += evsel__hists(pos)->nr_entries;

498 499 500
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
501

502 503
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
504

505 506
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
507
			perf_evlist__fprintf_nr_events(session->evlist, stdout);
508 509
			return 0;
		}
510 511
	}

512
	report__collapse_hists(rep);
513

514 515 516
	if (session_done())
		return 0;

517 518 519 520 521 522 523 524
	/*
	 * recalculate number of entries after collapsing since it
	 * might be changed during the collapse phase.
	 */
	rep->nr_entries = 0;
	evlist__for_each(session->evlist, pos)
		rep->nr_entries += evsel__hists(pos)->nr_entries;

525
	if (rep->nr_entries == 0) {
526
		ui__error("The %s file has no samples!\n", file->path);
527
		return 0;
528 529
	}

530
	report__output_resort(rep);
531

532
	return report__browse_hists(rep);
533 534
}

535
static int
536
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
537
{
538
	struct report *rep = (struct report *)opt->value;
539

540 541 542 543
	/*
	 * --no-call-graph
	 */
	if (unset) {
544
		rep->dont_use_callchains = true;
545 546 547
		return 0;
	}

548
	return parse_callchain_report_opt(arg);
549 550
}

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
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;
}

569
static int
570 571
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
572
{
573 574 575
	int *branch_mode = opt->value;

	*branch_mode = !unset;
576 577 578
	return 0;
}

579 580 581 582
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
583
	struct report *rep = opt->value;
584 585 586 587 588

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

589
int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
590
{
591
	struct perf_session *session;
592
	struct itrace_synth_opts itrace_synth_opts = { .set = 0, };
593
	struct stat st;
594
	bool has_br_stack = false;
595
	int branch_mode = -1;
596
	bool branch_call_mode = false;
597 598
	char callchain_default_opt[] = "fractal,0.5,callee";
	const char * const report_usage[] = {
N
Namhyung Kim 已提交
599
		"perf report [<options>]",
600 601
		NULL
	};
602
	struct report report = {
603
		.tool = {
604 605
			.sample		 = process_sample_event,
			.mmap		 = perf_event__process_mmap,
606
			.mmap2		 = perf_event__process_mmap2,
607
			.comm		 = perf_event__process_comm,
608 609
			.exit		 = perf_event__process_exit,
			.fork		 = perf_event__process_fork,
610 611 612 613 614
			.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,
615 616 617
			.id_index	 = perf_event__process_id_index,
			.auxtrace_info	 = perf_event__process_auxtrace_info,
			.auxtrace	 = perf_event__process_auxtrace,
618
			.ordered_events	 = true,
619 620
			.ordering_requires_timestamps = true,
		},
621
		.max_stack		 = PERF_MAX_STACK_DEPTH,
622 623 624
		.pretty_printing_style	 = "normal",
	};
	const struct option options[] = {
625
	OPT_STRING('i', "input", &input_name, "file",
626
		    "input file name"),
627
	OPT_INCR('v', "verbose", &verbose,
628
		    "be more verbose (show symbol address, etc)"),
629 630
	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
		    "dump raw trace in ASCII"),
631 632
	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
		   "file", "vmlinux pathname"),
633 634
	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
		   "file", "kallsyms pathname"),
635
	OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"),
636
	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
637
		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
638
	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
639
		    "Show a column with the number of samples"),
640
	OPT_BOOLEAN('T', "threads", &report.show_threads,
641
		    "Show per-thread event counters"),
642
	OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
643
		   "pretty printing style key: normal raw"),
644
	OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
645
	OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
646 647
	OPT_BOOLEAN(0, "stdio", &report.use_stdio,
		    "Use the stdio interface"),
648 649 650
	OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
	OPT_BOOLEAN(0, "header-only", &report.header_only,
		    "Show only data header."),
651
	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
652 653
		   "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..."
		   " Please refer the man page for the complete list."),
654 655
	OPT_STRING('F', "fields", &field_order, "key[,keys...]",
		   "output field(s): overhead, period, sample plus all of sort keys"),
656 657
	OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
		    "Show sample percentage for different cpu modes"),
658 659
	OPT_STRING('p', "parent", &parent_pattern, "regex",
		   "regex filter to identify parent, see: '--sort parent'"),
660
	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
661
		    "Only display entries with parent-match"),
662 663
	OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]",
		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. "
664
		     "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt),
665 666
	OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
		    "Accumulate callchains of children and show total overhead as well"),
667 668 669 670
	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)),
671 672
	OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
		    "alias for inverted call graph"),
673 674 675
	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
		   "ignore callees of these functions in call graphs",
		   report_parse_ignore_callees_opt),
676
	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
677
		   "only consider symbols in these dsos"),
678
	OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
679
		   "only consider symbols in these comms"),
680 681 682 683
	OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
		   "only consider symbols in these pids"),
	OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
		   "only consider symbols in these tids"),
684
	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
685
		   "only consider these symbols"),
686 687
	OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
		   "only show symbols that (partially) match with this filter"),
688
	OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
689 690
		   "width[,width...]",
		   "don't try to adjust column width, use these fixed values"),
691
	OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
692 693
		   "separator for columns, no spaces will be added between "
		   "columns '.' is reserved."),
694
	OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
695
		    "Only display entries resolved to a symbol"),
696 697
	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
		    "Look for files with symbols relative to this directory"),
698
	OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
699 700
		   "list of cpus to profile"),
	OPT_BOOLEAN('I', "show-info", &report.show_full_info,
701
		    "Display extended information about perf.data file"),
702 703 704 705
	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)"),
706 707
	OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
708 709
	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
		    "Show a column with the sum of periods"),
N
Namhyung Kim 已提交
710 711
	OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
		    "Show event group information together"),
712
	OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
713 714 715 716
		    "use branch records for per branch histogram filling",
		    parse_branch_mode),
	OPT_BOOLEAN(0, "branch-history", &branch_call_mode,
		    "add last branch records to call history"),
717 718
	OPT_STRING(0, "objdump", &objdump_path, "path",
		   "objdump binary to use for disassembly and annotations"),
719 720
	OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
		    "Disable symbol demangling"),
721 722
	OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
		    "Enable kernel symbol demangling"),
723
	OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
724 725
	OPT_CALLBACK(0, "percent-limit", &report, "percent",
		     "Don't show entries under that percent", parse_percent_limit),
726
	OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
N
Namhyung Kim 已提交
727
		     "how to display percentage of filtered entries", parse_filter_percentage),
728 729 730
	OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
			    "Instruction Tracing options",
			    itrace_parse_synth_opts),
731
	OPT_END()
732
	};
733 734 735
	struct perf_data_file file = {
		.mode  = PERF_DATA_MODE_READ,
	};
736 737 738 739
	int ret = hists__init();

	if (ret < 0)
		return ret;
740

741
	perf_config(report__config, &report);
742

743 744
	argc = parse_options(argc, argv, options, report_usage, 0);

745 746 747 748 749 750 751 752 753 754 755
	if (symbol_conf.vmlinux_name &&
	    access(symbol_conf.vmlinux_name, R_OK)) {
		pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name);
		return -EINVAL;
	}
	if (symbol_conf.kallsyms_name &&
	    access(symbol_conf.kallsyms_name, R_OK)) {
		pr_err("Invalid file: %s\n", symbol_conf.kallsyms_name);
		return -EINVAL;
	}

756
	if (report.use_stdio)
757
		use_browser = 0;
758
	else if (report.use_tui)
759
		use_browser = 1;
760 761
	else if (report.use_gtk)
		use_browser = 2;
762

763
	if (report.inverted_callchain)
764 765
		callchain_param.order = ORDER_CALLER;

766
	if (!input_name || !strlen(input_name)) {
767
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
768
			input_name = "-";
769
		else
770
			input_name = "perf.data";
771
	}
772

773 774 775
	file.path  = input_name;
	file.force = report.force;

776
repeat:
777
	session = perf_session__new(&file, false, &report.tool);
778
	if (session == NULL)
779
		return -1;
780

781 782 783 784 785
	if (report.queue_size) {
		ordered_events__set_alloc_size(&session->ordered_events,
					       report.queue_size);
	}

786 787
	session->itrace_synth_opts = &itrace_synth_opts;

788 789 790 791
	report.session = session;

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

793 794 795 796 797 798
	/*
	 * Branch mode is a tristate:
	 * -1 means default, so decide based on the file having branch data.
	 * 0/1 means the user chose a mode.
	 */
	if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
799
	    !branch_call_mode) {
800
		sort__mode = SORT_MODE__BRANCH;
801 802
		symbol_conf.cumulate_callchain = false;
	}
803
	if (branch_call_mode) {
804
		callchain_param.key = CCKEY_ADDRESS;
805 806 807 808 809 810
		callchain_param.branch_callstack = 1;
		symbol_conf.use_callchain = true;
		callchain_register_param(&callchain_param);
		if (sort_order == NULL)
			sort_order = "srcline,symbol,dso";
	}
811

812
	if (report.mem_mode) {
813
		if (sort__mode == SORT_MODE__BRANCH) {
814
			pr_err("branch and mem mode incompatible\n");
815 816
			goto error;
		}
817
		sort__mode = SORT_MODE__MEMORY;
818
		symbol_conf.cumulate_callchain = false;
819
	}
820

821
	if (setup_sorting() < 0) {
822 823 824 825 826
		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);
827 828
		goto error;
	}
829

830 831
	/* Force tty output for header output and per-thread stat. */
	if (report.header || report.header_only || report.show_threads)
832 833
		use_browser = 0;

834 835
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
836
	else
837 838
		use_browser = 0;

839 840 841 842 843 844 845 846 847 848
	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);
	}

849
	/*
850
	 * Only in the TUI browser we are doing integrated annotation,
851 852 853
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
854
	if (ui__has_annotation()) {
855
		symbol_conf.priv_size = sizeof(struct annotation);
856 857
		machines__set_symbol_filter(&session->machines,
					    symbol__annotate_init);
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
		/*
 		 * 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;
		}
	}
874

875
	if (symbol__init(&session->header.env) < 0)
876
		goto error;
877

878 879 880 881 882 883 884 885 886 887
	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];
	}
888

889
	sort__setup_elide(stdout);
890

891
	ret = __cmd_report(&report);
892 893 894 895 896 897
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

898 899 900
error:
	perf_session__delete(session);
	return ret;
901
}