builtin-report.c 27.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			use_tui, use_gtk, use_stdio;
48 49 50 51
	bool			dont_use_callchains;
	bool			show_full_info;
	bool			show_threads;
	bool			inverted_callchain;
52
	bool			mem_mode;
53 54
	bool			header;
	bool			header_only;
55
	bool			nonany_branch_mode;
56
	int			max_stack;
57 58 59
	struct perf_read_values	show_threads_values;
	const char		*pretty_printing_style;
	const char		*cpu_list;
60
	const char		*symbol_filter_str;
61
	float			min_percent;
62
	u64			nr_entries;
63
	u64			queue_size;
64
	int			socket_filter;
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
		.evsel 			= evsel,
		.sample 		= sample,
148
		.hide_unresolved 	= symbol_conf.hide_unresolved,
149
		.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 (symbol_conf.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 169 170 171
	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;
172
		iter.ops = &hist_iter_branch;
173
	} else if (rep->mem_mode) {
174
		iter.ops = &hist_iter_mem;
175
	} else if (symbol_conf.cumulate_callchain) {
176
		iter.ops = &hist_iter_cumulative;
177
	} else {
178
		iter.ops = &hist_iter_normal;
179
	}
180 181 182 183

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

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

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

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

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

	return 0;
}

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

223 224 225 226 227 228
	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;

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

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

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

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

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

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

287 288
	return 0;
}
289

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return 0;
}

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

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

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

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

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

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

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

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

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

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

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

	ui_progress__finish();
}

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

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

511 512
	signal(SIGINT, sig_handler);

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

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

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

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

531
	report__warn_kptr_restrict(rep);
532

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

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

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

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

550
	report__collapse_hists(rep);
551

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

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

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

568
	report__output_resort(rep);
569

570
	return report__browse_hists(rep);
571 572
}

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

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

586
	return parse_callchain_report_opt(arg);
587 588
}

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

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

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

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

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

627
#define CALLCHAIN_DEFAULT_OPT  "graph,0.5,caller,function,percent"
628 629 630 631

const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
				     CALLCHAIN_REPORT_HELP
				     "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
632

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

	if (ret < 0)
		return ret;
794

795
	perf_config(report__config, &report);
796

797 798
	argc = parse_options(argc, argv, options, report_usage, 0);

799 800 801 802 803 804 805 806 807 808 809
	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;
	}

810
	if (report.use_stdio)
811
		use_browser = 0;
812
	else if (report.use_tui)
813
		use_browser = 1;
814 815
	else if (report.use_gtk)
		use_browser = 2;
816

817
	if (report.inverted_callchain)
818
		callchain_param.order = ORDER_CALLER;
819 820
	if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
		callchain_param.order = ORDER_CALLER;
821

822 823 824 825
	if (itrace_synth_opts.callchain &&
	    (int)itrace_synth_opts.callchain_sz > report.max_stack)
		report.max_stack = itrace_synth_opts.callchain_sz;

826
	if (!input_name || !strlen(input_name)) {
827
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
828
			input_name = "-";
829
		else
830
			input_name = "perf.data";
831
	}
832

833
	file.path  = input_name;
834
	file.force = symbol_conf.force;
835

836
repeat:
837
	session = perf_session__new(&file, false, &report.tool);
838
	if (session == NULL)
839
		return -1;
840

841 842 843 844 845
	if (report.queue_size) {
		ordered_events__set_alloc_size(&session->ordered_events,
					       report.queue_size);
	}

846 847
	session->itrace_synth_opts = &itrace_synth_opts;

848 849 850 851
	report.session = session;

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

853 854 855
	if (itrace_synth_opts.last_branch)
		has_br_stack = true;

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

875
	if (report.mem_mode) {
876
		if (sort__mode == SORT_MODE__BRANCH) {
877
			pr_err("branch and mem mode incompatible\n");
878 879
			goto error;
		}
880
		sort__mode = SORT_MODE__MEMORY;
881
		symbol_conf.cumulate_callchain = false;
882
	}
883

884
	if (setup_sorting() < 0) {
885 886 887 888 889
		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);
890 891
		goto error;
	}
892

893 894
	/* Force tty output for header output and per-thread stat. */
	if (report.header || report.header_only || report.show_threads)
895 896
		use_browser = 0;

897 898
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
899
	else
900 901
		use_browser = 0;

902 903 904
	if (report.header || report.header_only) {
		perf_session__fprintf_info(session, stdout,
					   report.show_full_info);
905 906 907 908
		if (report.header_only) {
			ret = 0;
			goto error;
		}
909 910 911 912 913
	} else if (use_browser == 0) {
		fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
		      stdout);
	}

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

940
	if (symbol__init(&session->header.env) < 0)
941
		goto error;
942

943 944 945 946 947 948 949 950 951 952
	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];
	}
953

954
	sort__setup_elide(stdout);
955

956
	ret = __cmd_report(&report);
957 958 959 960 961 962
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

963 964 965
error:
	perf_session__delete(session);
	return ret;
966
}