builtin-report.c 26.2 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
	bool			nonany_branch_mode;
57
	int			max_stack;
58 59 60
	struct perf_read_values	show_threads_values;
	const char		*pretty_printing_style;
	const char		*cpu_list;
61
	const char		*symbol_filter_str;
62
	float			min_percent;
63
	u64			nr_entries;
64
	u64			queue_size;
65
	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
66
};
67

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

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

	return perf_default_config(var, value, cb);
}

92 93 94 95 96 97 98 99 100 101 102 103 104 105
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;

106 107 108
	hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
			     rep->nonany_branch_mode);

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
	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;
135 136
}

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

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

159
	if (rep->hide_unresolved && al.sym == NULL)
160
		goto out_put;
161

162
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
163
		goto out_put;
164

165 166 167 168
	if (sort__mode == SORT_MODE__BRANCH)
		iter.ops = &hist_iter_branch;
	else if (rep->mem_mode)
		iter.ops = &hist_iter_mem;
169 170
	else if (symbol_conf.cumulate_callchain)
		iter.ops = &hist_iter_cumulative;
171 172 173 174 175 176
	else
		iter.ops = &hist_iter_normal;

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

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

185
static int process_read_event(struct perf_tool *tool,
186
			      union perf_event *event,
187
			      struct perf_sample *sample __maybe_unused,
188
			      struct perf_evsel *evsel,
189
			      struct machine *machine __maybe_unused)
190
{
191
	struct report *rep = container_of(tool, struct report, tool);
192

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

202
	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
203
		    evsel ? perf_evsel__name(evsel) : "FAIL",
204
		    event->read.value);
205 206 207 208

	return 0;
}

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

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

239 240 241 242 243 244 245 246
	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();
		}
	}

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

256 257 258 259
	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;
260 261
		else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
			callchain_param.record_mode = CALLCHAIN_LBR;
262 263 264
		else
			callchain_param.record_mode = CALLCHAIN_FP;
	}
265 266 267 268 269 270

	/* ??? handle more cases than just ANY? */
	if (!(perf_evlist__combined_branch_type(session->evlist) &
				PERF_SAMPLE_BRANCH_ANY))
		rep->nonany_branch_mode = true;

271 272
	return 0;
}
273

274
static void sig_handler(int sig __maybe_unused)
275 276 277 278
{
	session_done = 1;
}

279
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
280 281 282 283
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
284 285 286
	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);
287 288 289
	char buf[512];
	size_t size = sizeof(buf);

290 291 292 293 294
	if (symbol_conf.filter_relative) {
		nr_samples = hists->stats.nr_non_filtered_samples;
		nr_events = hists->stats.total_non_filtered_period;
	}

295
	if (perf_evsel__is_group_event(evsel)) {
296 297 298 299 300 301
		struct perf_evsel *pos;

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

		for_each_group_member(pos, evsel) {
302 303
			const struct hists *pos_hists = evsel__hists(pos);

304
			if (symbol_conf.filter_relative) {
305 306
				nr_samples += pos_hists->stats.nr_non_filtered_samples;
				nr_events += pos_hists->stats.total_non_filtered_period;
307
			} else {
308 309
				nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
				nr_events += pos_hists->stats.total_period;
310
			}
311 312
		}
	}
313

314 315
	nr_samples = convert_unit(nr_samples, &unit);
	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
316
	if (evname != NULL)
317 318
		ret += fprintf(fp, " of event '%s'", evname);

319 320
	if (rep->mem_mode) {
		ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
321
		ret += fprintf(fp, "\n# Sort order   : %s", sort_order ? : default_mem_sort_order);
322 323
	} else
		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
324 325 326
	return ret + fprintf(fp, "\n#\n");
}

327
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
328
					 struct report *rep,
329
					 const char *help)
330
{
331
	struct perf_evsel *pos;
332

333
	fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples);
334
	evlist__for_each(evlist, pos) {
335
		struct hists *hists = evsel__hists(pos);
336
		const char *evname = perf_evsel__name(pos);
337

338 339 340 341
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

342
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
343
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
344 345 346
		fprintf(stdout, "\n\n");
	}

347
	if (sort_order == NULL &&
348
	    parent_pattern == default_parent_pattern)
349 350
		fprintf(stdout, "#\n# (%s)\n#\n", help);

351 352 353 354 355
	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);
356 357 358 359 360
	}

	return 0;
}

361 362 363
static void report__warn_kptr_restrict(const struct report *rep)
{
	struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
364
	struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389

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

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 425 426 427 428 429 430 431 432 433 434
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;
}

435
static void report__collapse_hists(struct report *rep)
436 437 438 439
{
	struct ui_progress prog;
	struct perf_evsel *pos;

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

442
	evlist__for_each(rep->session->evlist, pos) {
443
		struct hists *hists = evsel__hists(pos);
444 445 446 447 448 449 450 451 452

		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)) {
453
			struct hists *leader_hists = evsel__hists(pos->leader);
454 455 456 457 458 459 460 461 462

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

	ui_progress__finish();
}

463 464 465 466 467 468 469 470 471 472 473 474 475
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();
}

476
static int __cmd_report(struct report *rep)
477
{
478
	int ret;
479
	struct perf_session *session = rep->session;
480
	struct perf_evsel *pos;
481
	struct perf_data_file *file = session->file;
482

483 484
	signal(SIGINT, sig_handler);

485 486 487
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
488
		if (ret)
489
			return ret;
490 491
	}

492 493
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
494

495
	ret = report__setup_sample_type(rep);
496
	if (ret)
497
		return ret;
498

499
	ret = perf_session__process_events(session);
500
	if (ret)
501
		return ret;
502

503
	report__warn_kptr_restrict(rep);
504

505 506 507
	evlist__for_each(session->evlist, pos)
		rep->nr_entries += evsel__hists(pos)->nr_entries;

508 509 510
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
511

512 513
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
514

515 516
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
517
			perf_evlist__fprintf_nr_events(session->evlist, stdout);
518 519
			return 0;
		}
520 521
	}

522
	report__collapse_hists(rep);
523

524 525 526
	if (session_done())
		return 0;

527 528 529 530 531 532 533 534
	/*
	 * 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;

535
	if (rep->nr_entries == 0) {
536
		ui__error("The %s file has no samples!\n", file->path);
537
		return 0;
538 539
	}

540
	report__output_resort(rep);
541

542
	return report__browse_hists(rep);
543 544
}

545
static int
546
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
547
{
548
	struct report *rep = (struct report *)opt->value;
549

550 551 552 553
	/*
	 * --no-call-graph
	 */
	if (unset) {
554
		rep->dont_use_callchains = true;
555 556 557
		return 0;
	}

558
	return parse_callchain_report_opt(arg);
559 560
}

561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
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;
}

579
static int
580 581
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
582
{
583 584 585
	int *branch_mode = opt->value;

	*branch_mode = !unset;
586 587 588
	return 0;
}

589 590 591 592
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
593
	struct report *rep = opt->value;
594 595 596 597 598

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

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

	if (ret < 0)
		return ret;
750

751
	perf_config(report__config, &report);
752

753 754
	argc = parse_options(argc, argv, options, report_usage, 0);

755 756 757 758 759 760 761 762 763 764 765
	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;
	}

766
	if (report.use_stdio)
767
		use_browser = 0;
768
	else if (report.use_tui)
769
		use_browser = 1;
770 771
	else if (report.use_gtk)
		use_browser = 2;
772

773
	if (report.inverted_callchain)
774 775
		callchain_param.order = ORDER_CALLER;

776
	if (!input_name || !strlen(input_name)) {
777
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
778
			input_name = "-";
779
		else
780
			input_name = "perf.data";
781
	}
782

783 784 785
	file.path  = input_name;
	file.force = report.force;

786
repeat:
787
	session = perf_session__new(&file, false, &report.tool);
788
	if (session == NULL)
789
		return -1;
790

791 792 793 794 795
	if (report.queue_size) {
		ordered_events__set_alloc_size(&session->ordered_events,
					       report.queue_size);
	}

796 797
	session->itrace_synth_opts = &itrace_synth_opts;

798 799 800 801
	report.session = session;

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

803 804 805 806 807 808
	/*
	 * 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) &&
809
	    !branch_call_mode) {
810
		sort__mode = SORT_MODE__BRANCH;
811 812
		symbol_conf.cumulate_callchain = false;
	}
813
	if (branch_call_mode) {
814
		callchain_param.key = CCKEY_ADDRESS;
815 816 817 818 819 820
		callchain_param.branch_callstack = 1;
		symbol_conf.use_callchain = true;
		callchain_register_param(&callchain_param);
		if (sort_order == NULL)
			sort_order = "srcline,symbol,dso";
	}
821

822
	if (report.mem_mode) {
823
		if (sort__mode == SORT_MODE__BRANCH) {
824
			pr_err("branch and mem mode incompatible\n");
825 826
			goto error;
		}
827
		sort__mode = SORT_MODE__MEMORY;
828
		symbol_conf.cumulate_callchain = false;
829
	}
830

831
	if (setup_sorting() < 0) {
832 833 834 835 836
		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);
837 838
		goto error;
	}
839

840 841
	/* Force tty output for header output and per-thread stat. */
	if (report.header || report.header_only || report.show_threads)
842 843
		use_browser = 0;

844 845
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
846
	else
847 848
		use_browser = 0;

849 850 851
	if (report.header || report.header_only) {
		perf_session__fprintf_info(session, stdout,
					   report.show_full_info);
852 853 854 855
		if (report.header_only) {
			ret = 0;
			goto error;
		}
856 857 858 859 860
	} else if (use_browser == 0) {
		fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
		      stdout);
	}

861
	/*
862
	 * Only in the TUI browser we are doing integrated annotation,
863 864 865
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
866
	if (ui__has_annotation()) {
867
		symbol_conf.priv_size = sizeof(struct annotation);
868 869
		machines__set_symbol_filter(&session->machines,
					    symbol__annotate_init);
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
		/*
 		 * 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;
		}
	}
886

887
	if (symbol__init(&session->header.env) < 0)
888
		goto error;
889

890 891 892 893 894 895 896 897 898 899
	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];
	}
900

901
	sort__setup_elide(stdout);
902

903
	ret = __cmd_report(&report);
904 905 906 907 908 909
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

910 911 912
error:
	perf_session__delete(session);
	return ret;
913
}