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 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
#define CALLCHAIN_DEFAULT_OPT  "graph,0.5,caller,function,percent"
629 630 631 632

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

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

	if (ret < 0)
		return ret;
795

796
	perf_config(report__config, &report);
797

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

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

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

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

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

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

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

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

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

847 848
	session->itrace_synth_opts = &itrace_synth_opts;

849 850 851 852
	report.session = session;

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

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

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

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

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

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

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

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

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

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

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

955
	sort__setup_elide(stdout);
956

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

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