builtin-report.c 24.8 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
#include <dlfcn.h>
40 41
#include <linux/bitmap.h>

42
struct report {
43
	struct perf_tool	tool;
44
	struct perf_session	*session;
45
	bool			force, use_tui, use_gtk, use_stdio;
46 47 48 49 50
	bool			hide_unresolved;
	bool			dont_use_callchains;
	bool			show_full_info;
	bool			show_threads;
	bool			inverted_callchain;
51
	bool			mem_mode;
52 53
	bool			header;
	bool			header_only;
54
	int			max_stack;
55 56 57
	struct perf_read_values	show_threads_values;
	const char		*pretty_printing_style;
	const char		*cpu_list;
58
	const char		*symbol_filter_str;
59
	float			min_percent;
60
	u64			nr_entries;
61
	u64			queue_size;
62
	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
63
};
64

65
static int report__config(const char *var, const char *value, void *cb)
66
{
67 68
	struct report *rep = cb;

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

	return perf_default_config(var, value, cb);
}

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
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;

	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;
129 130
}

131
static int process_sample_event(struct perf_tool *tool,
132
				union perf_event *event,
133
				struct perf_sample *sample,
134
				struct perf_evsel *evsel,
135
				struct machine *machine)
136
{
137
	struct report *rep = container_of(tool, struct report, tool);
138
	struct addr_location al;
139 140
	struct hist_entry_iter iter = {
		.hide_unresolved = rep->hide_unresolved,
141
		.add_entry_cb = hist_iter__report_callback,
142
	};
143
	int ret;
144

145
	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
146 147
		pr_debug("problem processing %d event, skipping it.\n",
			 event->header.type);
148 149
		return -1;
	}
150

151
	if (rep->hide_unresolved && al.sym == NULL)
152
		return 0;
153

154
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
155 156
		return 0;

157 158 159 160
	if (sort__mode == SORT_MODE__BRANCH)
		iter.ops = &hist_iter_branch;
	else if (rep->mem_mode)
		iter.ops = &hist_iter_mem;
161 162
	else if (symbol_conf.cumulate_callchain)
		iter.ops = &hist_iter_cumulative;
163 164 165 166 167 168
	else
		iter.ops = &hist_iter_normal;

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

169 170
	ret = hist_entry_iter__add(&iter, &al, evsel, sample, rep->max_stack,
				   rep);
171 172
	if (ret < 0)
		pr_debug("problem adding hist entry, skipping event\n");
173

174
	return ret;
175
}
I
Ingo Molnar 已提交
176

177
static int process_read_event(struct perf_tool *tool,
178
			      union perf_event *event,
179
			      struct perf_sample *sample __maybe_unused,
180
			      struct perf_evsel *evsel,
181
			      struct machine *machine __maybe_unused)
182
{
183
	struct report *rep = container_of(tool, struct report, tool);
184

185
	if (rep->show_threads) {
186
		const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
187
		perf_read_values_add_value(&rep->show_threads_values,
188 189 190 191 192 193
					   event->read.pid, event->read.tid,
					   event->read.id,
					   name,
					   event->read.value);
	}

194
	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
195
		    evsel ? perf_evsel__name(evsel) : "FAIL",
196
		    event->read.value);
197 198 199 200

	return 0;
}

201
/* For pipe mode, sample_type is not currently set */
202
static int report__setup_sample_type(struct report *rep)
203
{
204 205 206
	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);
207

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

231 232 233 234 235 236 237 238
	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();
		}
	}

239
	if (sort__mode == SORT_MODE__BRANCH) {
240
		if (!is_pipe &&
241
		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
242 243
			ui__error("Selected -b but no branch data. "
				  "Did you call perf record without -b?\n");
244 245 246 247
			return -1;
		}
	}

248 249 250 251
	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;
252 253
		else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
			callchain_param.record_mode = CALLCHAIN_LBR;
254 255 256
		else
			callchain_param.record_mode = CALLCHAIN_FP;
	}
257 258
	return 0;
}
259

260
static void sig_handler(int sig __maybe_unused)
261 262 263 264
{
	session_done = 1;
}

265
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
266 267 268 269
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
270 271 272
	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);
273 274 275
	char buf[512];
	size_t size = sizeof(buf);

276 277 278 279 280
	if (symbol_conf.filter_relative) {
		nr_samples = hists->stats.nr_non_filtered_samples;
		nr_events = hists->stats.total_non_filtered_period;
	}

281
	if (perf_evsel__is_group_event(evsel)) {
282 283 284 285 286 287
		struct perf_evsel *pos;

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

		for_each_group_member(pos, evsel) {
288 289
			const struct hists *pos_hists = evsel__hists(pos);

290
			if (symbol_conf.filter_relative) {
291 292
				nr_samples += pos_hists->stats.nr_non_filtered_samples;
				nr_events += pos_hists->stats.total_non_filtered_period;
293
			} else {
294 295
				nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
				nr_events += pos_hists->stats.total_period;
296
			}
297 298
		}
	}
299

300 301
	nr_samples = convert_unit(nr_samples, &unit);
	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
302
	if (evname != NULL)
303 304
		ret += fprintf(fp, " of event '%s'", evname);

305 306
	if (rep->mem_mode) {
		ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
307
		ret += fprintf(fp, "\n# Sort order   : %s", sort_order ? : default_mem_sort_order);
308 309
	} else
		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
310 311 312
	return ret + fprintf(fp, "\n#\n");
}

313
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
314
					 struct report *rep,
315
					 const char *help)
316
{
317
	struct perf_evsel *pos;
318

319
	evlist__for_each(evlist, pos) {
320
		struct hists *hists = evsel__hists(pos);
321
		const char *evname = perf_evsel__name(pos);
322

323 324 325 326
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

327
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
328
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
329 330 331 332 333 334 335
		fprintf(stdout, "\n\n");
	}

	if (sort_order == default_sort_order &&
	    parent_pattern == default_parent_pattern) {
		fprintf(stdout, "#\n# (%s)\n#\n", help);

336 337 338
		if (rep->show_threads) {
			bool style = !strcmp(rep->pretty_printing_style, "raw");
			perf_read_values_display(stdout, &rep->show_threads_values,
339
						 style);
340
			perf_read_values_destroy(&rep->show_threads_values);
341 342 343 344 345 346
		}
	}

	return 0;
}

347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
static void report__warn_kptr_restrict(const struct report *rep)
{
	struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
	struct kmap *kernel_kmap = map__kmap(kernel_map);

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

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
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;
}

421
static void report__collapse_hists(struct report *rep)
422 423 424 425
{
	struct ui_progress prog;
	struct perf_evsel *pos;

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

428
	evlist__for_each(rep->session->evlist, pos) {
429
		struct hists *hists = evsel__hists(pos);
430 431 432 433 434 435 436 437 438

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

		hists__collapse_resort(hists, &prog);

		/* Non-group events are considered as leader */
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos)) {
439
			struct hists *leader_hists = evsel__hists(pos->leader);
440 441 442 443 444 445 446 447 448

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

	ui_progress__finish();
}

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

462
static int __cmd_report(struct report *rep)
463
{
464
	int ret;
465
	struct perf_session *session = rep->session;
466
	struct perf_evsel *pos;
467
	struct perf_data_file *file = session->file;
468

469 470
	signal(SIGINT, sig_handler);

471 472 473
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
474
		if (ret)
475
			return ret;
476 477
	}

478 479
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
480

481
	ret = report__setup_sample_type(rep);
482
	if (ret)
483
		return ret;
484

485
	ret = perf_session__process_events(session);
486
	if (ret)
487
		return ret;
488

489
	report__warn_kptr_restrict(rep);
490

491 492 493
	evlist__for_each(session->evlist, pos)
		rep->nr_entries += evsel__hists(pos)->nr_entries;

494 495 496
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
497

498 499
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
500

501 502
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
503
			perf_evlist__fprintf_nr_events(session->evlist, stdout);
504 505
			return 0;
		}
506 507
	}

508
	report__collapse_hists(rep);
509

510 511 512
	if (session_done())
		return 0;

513 514 515 516 517 518 519 520
	/*
	 * 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;

521
	if (rep->nr_entries == 0) {
522
		ui__error("The %s file has no samples!\n", file->path);
523
		return 0;
524 525
	}

526
	report__output_resort(rep);
527

528
	return report__browse_hists(rep);
529 530
}

531
static int
532
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
533
{
534
	struct report *rep = (struct report *)opt->value;
535

536 537 538 539
	/*
	 * --no-call-graph
	 */
	if (unset) {
540
		rep->dont_use_callchains = true;
541 542 543
		return 0;
	}

544
	return parse_callchain_report_opt(arg);
545 546
}

547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
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;
}

565
static int
566 567
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
568
{
569 570 571
	int *branch_mode = opt->value;

	*branch_mode = !unset;
572 573 574
	return 0;
}

575 576 577 578
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
579
	struct report *rep = opt->value;
580 581 582 583 584

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

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

	if (ret < 0)
		return ret;
725

726
	perf_config(report__config, &report);
727

728 729
	argc = parse_options(argc, argv, options, report_usage, 0);

730
	if (report.use_stdio)
731
		use_browser = 0;
732
	else if (report.use_tui)
733
		use_browser = 1;
734 735
	else if (report.use_gtk)
		use_browser = 2;
736

737
	if (report.inverted_callchain)
738 739
		callchain_param.order = ORDER_CALLER;

740
	if (!input_name || !strlen(input_name)) {
741
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
742
			input_name = "-";
743
		else
744
			input_name = "perf.data";
745
	}
746

747 748 749
	file.path  = input_name;
	file.force = report.force;

750
repeat:
751
	session = perf_session__new(&file, false, &report.tool);
752
	if (session == NULL)
753
		return -1;
754

755 756 757 758 759
	if (report.queue_size) {
		ordered_events__set_alloc_size(&session->ordered_events,
					       report.queue_size);
	}

760 761 762 763
	report.session = session;

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

765 766 767 768 769 770
	/*
	 * 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) &&
771
	    !branch_call_mode) {
772
		sort__mode = SORT_MODE__BRANCH;
773 774
		symbol_conf.cumulate_callchain = false;
	}
775
	if (branch_call_mode) {
776
		callchain_param.key = CCKEY_ADDRESS;
777 778 779 780 781 782
		callchain_param.branch_callstack = 1;
		symbol_conf.use_callchain = true;
		callchain_register_param(&callchain_param);
		if (sort_order == NULL)
			sort_order = "srcline,symbol,dso";
	}
783

784
	if (report.mem_mode) {
785
		if (sort__mode == SORT_MODE__BRANCH) {
786
			pr_err("branch and mem mode incompatible\n");
787 788
			goto error;
		}
789
		sort__mode = SORT_MODE__MEMORY;
790
		symbol_conf.cumulate_callchain = false;
791
	}
792

793
	if (setup_sorting() < 0) {
794 795 796 797 798
		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);
799 800
		goto error;
	}
801

802 803 804 805
	/* Force tty output for header output. */
	if (report.header || report.header_only)
		use_browser = 0;

806 807
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
808
	else
809 810
		use_browser = 0;

811 812 813 814 815 816 817 818 819 820
	if (report.header || report.header_only) {
		perf_session__fprintf_info(session, stdout,
					   report.show_full_info);
		if (report.header_only)
			return 0;
	} else if (use_browser == 0) {
		fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
		      stdout);
	}

821
	/*
822
	 * Only in the TUI browser we are doing integrated annotation,
823 824 825
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
826
	if (ui__has_annotation()) {
827
		symbol_conf.priv_size = sizeof(struct annotation);
828 829
		machines__set_symbol_filter(&session->machines,
					    symbol__annotate_init);
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
		/*
 		 * 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;
		}
	}
846

847
	if (symbol__init(&session->header.env) < 0)
848
		goto error;
849

850 851 852 853 854 855 856 857 858 859
	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];
	}
860

861
	sort__setup_elide(stdout);
862

863
	ret = __cmd_report(&report);
864 865 866 867 868 869
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

870 871 872
error:
	perf_session__delete(session);
	return ret;
873
}