builtin-report.c 26.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
	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
	int			socket_filter;
66
	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
67
};
68

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

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

	return perf_default_config(var, value, cb);
}

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

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

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 135
	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;
136 137
}

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

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

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

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

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

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

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

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

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

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

	return 0;
}

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

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

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

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

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

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

272 273
	return 0;
}
274

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

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

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

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

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

		for_each_group_member(pos, evsel) {
304 305
			const struct hists *pos_hists = evsel__hists(pos);

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

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

321 322 323 324 325
	if (symbol_conf.show_ref_callgraph &&
	    strstr(evname, "call-graph=no")) {
		ret += fprintf(fp, ", show reference callgraph");
	}

326 327
	if (rep->mem_mode) {
		ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
328
		ret += fprintf(fp, "\n# Sort order   : %s", sort_order ? : default_mem_sort_order);
329 330
	} else
		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
331 332 333 334

	if (socket > -1)
		ret += fprintf(fp, "\n# Processor Socket: %d", socket);

335 336 337
	return ret + fprintf(fp, "\n#\n");
}

338
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
339
					 struct report *rep,
340
					 const char *help)
341
{
342
	struct perf_evsel *pos;
343

344
	fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples);
345
	evlist__for_each(evlist, pos) {
346
		struct hists *hists = evsel__hists(pos);
347
		const char *evname = perf_evsel__name(pos);
348

349 350 351 352
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

353
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
354
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
355 356 357
		fprintf(stdout, "\n\n");
	}

358
	if (sort_order == NULL &&
359
	    parent_pattern == default_parent_pattern)
360 361
		fprintf(stdout, "#\n# (%s)\n#\n", help);

362 363 364 365 366
	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);
367 368 369 370 371
	}

	return 0;
}

372 373 374
static void report__warn_kptr_restrict(const struct report *rep)
{
	struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
375
	struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400

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

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 435 436 437 438 439 440 441 442 443 444 445
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;
}

446
static void report__collapse_hists(struct report *rep)
447 448 449 450
{
	struct ui_progress prog;
	struct perf_evsel *pos;

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

453
	evlist__for_each(rep->session->evlist, pos) {
454
		struct hists *hists = evsel__hists(pos);
455 456 457 458

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

459 460
		hists->socket_filter = rep->socket_filter;

461 462 463 464 465
		hists__collapse_resort(hists, &prog);

		/* Non-group events are considered as leader */
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos)) {
466
			struct hists *leader_hists = evsel__hists(pos->leader);
467 468 469 470 471 472 473 474 475

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

	ui_progress__finish();
}

476 477 478 479 480 481 482 483 484 485 486 487 488
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();
}

489
static int __cmd_report(struct report *rep)
490
{
491
	int ret;
492
	struct perf_session *session = rep->session;
493
	struct perf_evsel *pos;
494
	struct perf_data_file *file = session->file;
495

496 497
	signal(SIGINT, sig_handler);

498 499 500
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
501
		if (ret)
502
			return ret;
503 504
	}

505 506
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
507

508
	ret = report__setup_sample_type(rep);
509
	if (ret)
510
		return ret;
511

512
	ret = perf_session__process_events(session);
513
	if (ret)
514
		return ret;
515

516
	report__warn_kptr_restrict(rep);
517

518 519 520
	evlist__for_each(session->evlist, pos)
		rep->nr_entries += evsel__hists(pos)->nr_entries;

521 522 523
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
524

525 526
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
527

528 529
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
530
			perf_evlist__fprintf_nr_events(session->evlist, stdout);
531 532
			return 0;
		}
533 534
	}

535
	report__collapse_hists(rep);
536

537 538 539
	if (session_done())
		return 0;

540 541 542 543 544 545 546 547
	/*
	 * 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;

548
	if (rep->nr_entries == 0) {
549
		ui__error("The %s file has no samples!\n", file->path);
550
		return 0;
551 552
	}

553
	report__output_resort(rep);
554

555
	return report__browse_hists(rep);
556 557
}

558
static int
559
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
560
{
561
	struct report *rep = (struct report *)opt->value;
562

563 564 565 566
	/*
	 * --no-call-graph
	 */
	if (unset) {
567
		rep->dont_use_callchains = true;
568 569 570
		return 0;
	}

571
	return parse_callchain_report_opt(arg);
572 573
}

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
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;
}

592
static int
593 594
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
595
{
596 597 598
	int *branch_mode = opt->value;

	*branch_mode = !unset;
599 600 601
	return 0;
}

602 603 604 605
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
606
	struct report *rep = opt->value;
607 608 609 610 611

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

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

	if (ret < 0)
		return ret;
770

771
	perf_config(report__config, &report);
772

773 774
	argc = parse_options(argc, argv, options, report_usage, 0);

775 776 777 778 779 780 781 782 783 784 785
	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;
	}

786
	if (report.use_stdio)
787
		use_browser = 0;
788
	else if (report.use_tui)
789
		use_browser = 1;
790 791
	else if (report.use_gtk)
		use_browser = 2;
792

793
	if (report.inverted_callchain)
794 795
		callchain_param.order = ORDER_CALLER;

796
	if (!input_name || !strlen(input_name)) {
797
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
798
			input_name = "-";
799
		else
800
			input_name = "perf.data";
801
	}
802

803 804 805
	file.path  = input_name;
	file.force = report.force;

806
repeat:
807
	session = perf_session__new(&file, false, &report.tool);
808
	if (session == NULL)
809
		return -1;
810

811 812 813 814 815
	if (report.queue_size) {
		ordered_events__set_alloc_size(&session->ordered_events,
					       report.queue_size);
	}

816 817
	session->itrace_synth_opts = &itrace_synth_opts;

818 819 820 821
	report.session = session;

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

823 824 825 826 827 828
	/*
	 * 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) &&
829
	    !branch_call_mode) {
830
		sort__mode = SORT_MODE__BRANCH;
831 832
		symbol_conf.cumulate_callchain = false;
	}
833
	if (branch_call_mode) {
834
		callchain_param.key = CCKEY_ADDRESS;
835 836 837 838 839 840
		callchain_param.branch_callstack = 1;
		symbol_conf.use_callchain = true;
		callchain_register_param(&callchain_param);
		if (sort_order == NULL)
			sort_order = "srcline,symbol,dso";
	}
841

842
	if (report.mem_mode) {
843
		if (sort__mode == SORT_MODE__BRANCH) {
844
			pr_err("branch and mem mode incompatible\n");
845 846
			goto error;
		}
847
		sort__mode = SORT_MODE__MEMORY;
848
		symbol_conf.cumulate_callchain = false;
849
	}
850

851
	if (setup_sorting() < 0) {
852 853 854 855 856
		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);
857 858
		goto error;
	}
859

860 861
	/* Force tty output for header output and per-thread stat. */
	if (report.header || report.header_only || report.show_threads)
862 863
		use_browser = 0;

864 865
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
866
	else
867 868
		use_browser = 0;

869 870 871
	if (report.header || report.header_only) {
		perf_session__fprintf_info(session, stdout,
					   report.show_full_info);
872 873 874 875
		if (report.header_only) {
			ret = 0;
			goto error;
		}
876 877 878 879 880
	} else if (use_browser == 0) {
		fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
		      stdout);
	}

881
	/*
882
	 * Only in the TUI browser we are doing integrated annotation,
883 884 885
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
886
	if (ui__has_annotation()) {
887
		symbol_conf.priv_size = sizeof(struct annotation);
888 889
		machines__set_symbol_filter(&session->machines,
					    symbol__annotate_init);
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
		/*
 		 * 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;
		}
	}
906

907
	if (symbol__init(&session->header.env) < 0)
908
		goto error;
909

910 911 912 913 914 915 916 917 918 919
	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];
	}
920

921
	sort__setup_elide(stdout);
922

923
	ret = __cmd_report(&report);
924 925 926 927 928 929
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

930 931 932
error:
	perf_session__delete(session);
	return ret;
933
}