builtin-report.c 27.6 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 170 171 172
	if (sort__mode == SORT_MODE__BRANCH) {
		/*
		 * A non-synthesized event might not have a branch stack if
		 * branch stacks have been synthesized (using itrace options).
		 */
		if (!sample->branch_stack)
			goto out_put;
173
		iter.ops = &hist_iter_branch;
174
	} else if (rep->mem_mode) {
175
		iter.ops = &hist_iter_mem;
176
	} else if (symbol_conf.cumulate_callchain) {
177
		iter.ops = &hist_iter_cumulative;
178
	} else {
179
		iter.ops = &hist_iter_normal;
180
	}
181 182 183 184

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

185
	ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep);
186 187
	if (ret < 0)
		pr_debug("problem adding hist entry, skipping event\n");
188 189
out_put:
	addr_location__put(&al);
190
	return ret;
191
}
I
Ingo Molnar 已提交
192

193
static int process_read_event(struct perf_tool *tool,
194
			      union perf_event *event,
195
			      struct perf_sample *sample __maybe_unused,
196
			      struct perf_evsel *evsel,
197
			      struct machine *machine __maybe_unused)
198
{
199
	struct report *rep = container_of(tool, struct report, tool);
200

201
	if (rep->show_threads) {
202
		const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
203
		perf_read_values_add_value(&rep->show_threads_values,
204 205 206 207 208 209
					   event->read.pid, event->read.tid,
					   event->read.id,
					   name,
					   event->read.value);
	}

210
	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
211
		    evsel ? perf_evsel__name(evsel) : "FAIL",
212
		    event->read.value);
213 214 215 216

	return 0;
}

217
/* For pipe mode, sample_type is not currently set */
218
static int report__setup_sample_type(struct report *rep)
219
{
220 221 222
	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);
223

224 225 226 227 228 229
	if (session->itrace_synth_opts->callchain ||
	    (!is_pipe &&
	     perf_header__has_feat(&session->header, HEADER_AUXTRACE) &&
	     !session->itrace_synth_opts->set))
		sample_type |= PERF_SAMPLE_CALLCHAIN;

230 231 232
	if (session->itrace_synth_opts->last_branch)
		sample_type |= PERF_SAMPLE_BRANCH_STACK;

233
	if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
234
		if (sort__has_parent) {
235
			ui__error("Selected --sort parent, but no "
236 237
				    "callchain data. Did you call "
				    "'perf record' without -g?\n");
238
			return -EINVAL;
239
		}
240
		if (symbol_conf.use_callchain) {
241 242 243
			ui__error("Selected -g or --branch-history but no "
				  "callchain data. Did\n"
				  "you call 'perf record' without -g?\n");
244
			return -1;
245
		}
246 247
	} else if (!rep->dont_use_callchains &&
		   callchain_param.mode != CHAIN_NONE &&
248
		   !symbol_conf.use_callchain) {
249
			symbol_conf.use_callchain = true;
250
			if (callchain_register_param(&callchain_param) < 0) {
251
				ui__error("Can't register callchain params.\n");
252
				return -EINVAL;
253
			}
254 255
	}

256 257 258 259 260 261 262 263
	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();
		}
	}

264
	if (sort__mode == SORT_MODE__BRANCH) {
265
		if (!is_pipe &&
266
		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
267 268
			ui__error("Selected -b but no branch data. "
				  "Did you call perf record without -b?\n");
269 270 271 272
			return -1;
		}
	}

273 274 275 276
	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;
277 278
		else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
			callchain_param.record_mode = CALLCHAIN_LBR;
279 280 281
		else
			callchain_param.record_mode = CALLCHAIN_FP;
	}
282 283 284 285 286 287

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

288 289
	return 0;
}
290

291
static void sig_handler(int sig __maybe_unused)
292 293 294 295
{
	session_done = 1;
}

296
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
297 298 299 300
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
301 302 303
	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);
304 305
	char buf[512];
	size_t size = sizeof(buf);
306
	int socked_id = hists->socket_filter;
307

308 309 310 311 312
	if (symbol_conf.filter_relative) {
		nr_samples = hists->stats.nr_non_filtered_samples;
		nr_events = hists->stats.total_non_filtered_period;
	}

313
	if (perf_evsel__is_group_event(evsel)) {
314 315 316 317 318 319
		struct perf_evsel *pos;

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

		for_each_group_member(pos, evsel) {
320 321
			const struct hists *pos_hists = evsel__hists(pos);

322
			if (symbol_conf.filter_relative) {
323 324
				nr_samples += pos_hists->stats.nr_non_filtered_samples;
				nr_events += pos_hists->stats.total_non_filtered_period;
325
			} else {
326 327
				nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
				nr_events += pos_hists->stats.total_period;
328
			}
329 330
		}
	}
331

332 333
	nr_samples = convert_unit(nr_samples, &unit);
	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
334
	if (evname != NULL)
335 336
		ret += fprintf(fp, " of event '%s'", evname);

337 338 339 340 341
	if (symbol_conf.show_ref_callgraph &&
	    strstr(evname, "call-graph=no")) {
		ret += fprintf(fp, ", show reference callgraph");
	}

342 343
	if (rep->mem_mode) {
		ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
344
		ret += fprintf(fp, "\n# Sort order   : %s", sort_order ? : default_mem_sort_order);
345 346
	} else
		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
347

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

351 352 353
	return ret + fprintf(fp, "\n#\n");
}

354
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
355
					 struct report *rep,
356
					 const char *help)
357
{
358
	struct perf_evsel *pos;
359

360
	fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples);
361
	evlist__for_each(evlist, pos) {
362
		struct hists *hists = evsel__hists(pos);
363
		const char *evname = perf_evsel__name(pos);
364

365 366 367 368
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

369
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
370
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
371 372 373
		fprintf(stdout, "\n\n");
	}

374
	if (sort_order == NULL &&
375
	    parent_pattern == default_parent_pattern)
376 377
		fprintf(stdout, "#\n# (%s)\n#\n", help);

378 379 380 381 382
	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);
383 384 385 386 387
	}

	return 0;
}

388 389
static void report__warn_kptr_restrict(const struct report *rep)
{
390
	struct map *kernel_map = machine__kernel_map(&rep->session->machines.host);
391
	struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
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

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

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 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
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;
}

462
static void report__collapse_hists(struct report *rep)
463 464 465 466
{
	struct ui_progress prog;
	struct perf_evsel *pos;

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

469
	evlist__for_each(rep->session->evlist, pos) {
470
		struct hists *hists = evsel__hists(pos);
471 472 473 474

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

475 476
		hists->socket_filter = rep->socket_filter;

477 478 479 480 481
		hists__collapse_resort(hists, &prog);

		/* Non-group events are considered as leader */
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos)) {
482
			struct hists *leader_hists = evsel__hists(pos->leader);
483 484 485 486 487 488 489 490 491

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

	ui_progress__finish();
}

492 493 494 495 496 497 498 499 500 501 502 503 504
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();
}

505
static int __cmd_report(struct report *rep)
506
{
507
	int ret;
508
	struct perf_session *session = rep->session;
509
	struct perf_evsel *pos;
510
	struct perf_data_file *file = session->file;
511

512 513
	signal(SIGINT, sig_handler);

514 515 516
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
517
		if (ret)
518
			return ret;
519 520
	}

521 522
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
523

524
	ret = report__setup_sample_type(rep);
525
	if (ret)
526
		return ret;
527

528
	ret = perf_session__process_events(session);
529
	if (ret)
530
		return ret;
531

532
	report__warn_kptr_restrict(rep);
533

534 535 536
	evlist__for_each(session->evlist, pos)
		rep->nr_entries += evsel__hists(pos)->nr_entries;

537 538 539
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
540

541 542
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
543

544 545
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
546
			perf_evlist__fprintf_nr_events(session->evlist, stdout);
547 548
			return 0;
		}
549 550
	}

551
	report__collapse_hists(rep);
552

553 554 555
	if (session_done())
		return 0;

556 557 558 559 560 561 562 563
	/*
	 * 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;

564
	if (rep->nr_entries == 0) {
565
		ui__error("The %s file has no samples!\n", file->path);
566
		return 0;
567 568
	}

569
	report__output_resort(rep);
570

571
	return report__browse_hists(rep);
572 573
}

574
static int
575
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
576
{
577
	struct report *rep = (struct report *)opt->value;
578

579 580 581 582
	/*
	 * --no-call-graph
	 */
	if (unset) {
583
		rep->dont_use_callchains = true;
584 585 586
		return 0;
	}

587
	return parse_callchain_report_opt(arg);
588 589
}

590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
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;
}

608
static int
609 610
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
611
{
612 613 614
	int *branch_mode = opt->value;

	*branch_mode = !unset;
615 616 617
	return 0;
}

618 619 620 621
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
622
	struct report *rep = opt->value;
623 624 625 626 627

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

628 629 630
const char report_callchain_help[] = "Display callchains using " CALLCHAIN_REPORT_HELP ". "
				     "Default: graph,0.5,caller";

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

	if (ret < 0)
		return ret;
790

791
	perf_config(report__config, &report);
792

793 794
	argc = parse_options(argc, argv, options, report_usage, 0);

795 796 797 798 799 800 801 802 803 804 805
	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;
	}

806
	if (report.use_stdio)
807
		use_browser = 0;
808
	else if (report.use_tui)
809
		use_browser = 1;
810 811
	else if (report.use_gtk)
		use_browser = 2;
812

813
	if (report.inverted_callchain)
814 815
		callchain_param.order = ORDER_CALLER;

816 817 818 819
	if (itrace_synth_opts.callchain &&
	    (int)itrace_synth_opts.callchain_sz > report.max_stack)
		report.max_stack = itrace_synth_opts.callchain_sz;

820
	if (!input_name || !strlen(input_name)) {
821
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
822
			input_name = "-";
823
		else
824
			input_name = "perf.data";
825
	}
826

827 828 829
	file.path  = input_name;
	file.force = report.force;

830
repeat:
831
	session = perf_session__new(&file, false, &report.tool);
832
	if (session == NULL)
833
		return -1;
834

835 836 837 838 839
	if (report.queue_size) {
		ordered_events__set_alloc_size(&session->ordered_events,
					       report.queue_size);
	}

840 841
	session->itrace_synth_opts = &itrace_synth_opts;

842 843 844 845
	report.session = session;

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

847 848 849
	if (itrace_synth_opts.last_branch)
		has_br_stack = true;

850 851 852 853 854 855
	/*
	 * 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) &&
856
	    !branch_call_mode) {
857
		sort__mode = SORT_MODE__BRANCH;
858 859
		symbol_conf.cumulate_callchain = false;
	}
860
	if (branch_call_mode) {
861
		callchain_param.key = CCKEY_ADDRESS;
862 863 864 865 866 867
		callchain_param.branch_callstack = 1;
		symbol_conf.use_callchain = true;
		callchain_register_param(&callchain_param);
		if (sort_order == NULL)
			sort_order = "srcline,symbol,dso";
	}
868

869
	if (report.mem_mode) {
870
		if (sort__mode == SORT_MODE__BRANCH) {
871
			pr_err("branch and mem mode incompatible\n");
872 873
			goto error;
		}
874
		sort__mode = SORT_MODE__MEMORY;
875
		symbol_conf.cumulate_callchain = false;
876
	}
877

878
	if (setup_sorting() < 0) {
879 880 881 882 883
		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);
884 885
		goto error;
	}
886

887 888
	/* Force tty output for header output and per-thread stat. */
	if (report.header || report.header_only || report.show_threads)
889 890
		use_browser = 0;

891 892
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
893
	else
894 895
		use_browser = 0;

896 897 898
	if (report.header || report.header_only) {
		perf_session__fprintf_info(session, stdout,
					   report.show_full_info);
899 900 901 902
		if (report.header_only) {
			ret = 0;
			goto error;
		}
903 904 905 906 907
	} else if (use_browser == 0) {
		fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
		      stdout);
	}

908
	/*
909
	 * Only in the TUI browser we are doing integrated annotation,
910 911 912
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
913
	if (ui__has_annotation()) {
914
		symbol_conf.priv_size = sizeof(struct annotation);
915 916
		machines__set_symbol_filter(&session->machines,
					    symbol__annotate_init);
917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
		/*
 		 * 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;
		}
	}
933

934
	if (symbol__init(&session->header.env) < 0)
935
		goto error;
936

937 938 939 940 941 942 943 944 945 946
	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];
	}
947

948
	sort__setup_elide(stdout);
949

950
	ret = __cmd_report(&report);
951 952 953 954 955 956
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

957 958 959
error:
	perf_session__delete(session);
	return ret;
960
}