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

	if (ret < 0)
		return ret;
786

787
	perf_config(report__config, &report);
788

789 790
	argc = parse_options(argc, argv, options, report_usage, 0);

791 792 793 794 795 796 797 798 799 800 801
	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;
	}

802
	if (report.use_stdio)
803
		use_browser = 0;
804
	else if (report.use_tui)
805
		use_browser = 1;
806 807
	else if (report.use_gtk)
		use_browser = 2;
808

809
	if (report.inverted_callchain)
810 811
		callchain_param.order = ORDER_CALLER;

812 813 814 815
	if (itrace_synth_opts.callchain &&
	    (int)itrace_synth_opts.callchain_sz > report.max_stack)
		report.max_stack = itrace_synth_opts.callchain_sz;

816
	if (!input_name || !strlen(input_name)) {
817
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
818
			input_name = "-";
819
		else
820
			input_name = "perf.data";
821
	}
822

823 824 825
	file.path  = input_name;
	file.force = report.force;

826
repeat:
827
	session = perf_session__new(&file, false, &report.tool);
828
	if (session == NULL)
829
		return -1;
830

831 832 833 834 835
	if (report.queue_size) {
		ordered_events__set_alloc_size(&session->ordered_events,
					       report.queue_size);
	}

836 837
	session->itrace_synth_opts = &itrace_synth_opts;

838 839 840 841
	report.session = session;

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

843 844 845
	if (itrace_synth_opts.last_branch)
		has_br_stack = true;

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

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

874
	if (setup_sorting() < 0) {
875 876 877 878 879
		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);
880 881
		goto error;
	}
882

883 884
	/* Force tty output for header output and per-thread stat. */
	if (report.header || report.header_only || report.show_threads)
885 886
		use_browser = 0;

887 888
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
889
	else
890 891
		use_browser = 0;

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

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

930
	if (symbol__init(&session->header.env) < 0)
931
		goto error;
932

933 934 935 936 937 938 939 940 941 942
	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];
	}
943

944
	sort__setup_elide(stdout);
945

946
	ret = __cmd_report(&report);
947 948 949 950 951 952
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

953 954 955
error:
	perf_session__delete(session);
	return ret;
956
}