builtin-report.c 23.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
static void report__inc_stats(struct report *rep, struct hist_entry *he)
90 91
{
	/*
92 93 94
	 * The @he is either of a newly created one or an existing one
	 * merging current sample.  We only want to count a new one so
	 * checking ->nr_events being 1.
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 129 130 131 132 133 134 135 136 137 138 139 140 141
	if (he->stat.nr_events == 1)
		rep->nr_entries++;
}

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;

	report__inc_stats(rep, he);

	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;
142 143
}

144
static int process_sample_event(struct perf_tool *tool,
145
				union perf_event *event,
146
				struct perf_sample *sample,
147
				struct perf_evsel *evsel,
148
				struct machine *machine)
149
{
150
	struct report *rep = container_of(tool, struct report, tool);
151
	struct addr_location al;
152 153
	struct hist_entry_iter iter = {
		.hide_unresolved = rep->hide_unresolved,
154
		.add_entry_cb = hist_iter__report_callback,
155
	};
156
	int ret;
157

158
	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
159 160
		pr_debug("problem processing %d event, skipping it.\n",
			 event->header.type);
161 162
		return -1;
	}
163

164
	if (rep->hide_unresolved && al.sym == NULL)
165
		return 0;
166

167
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
168 169
		return 0;

170 171 172 173
	if (sort__mode == SORT_MODE__BRANCH)
		iter.ops = &hist_iter_branch;
	else if (rep->mem_mode)
		iter.ops = &hist_iter_mem;
174 175
	else if (symbol_conf.cumulate_callchain)
		iter.ops = &hist_iter_cumulative;
176 177 178 179 180 181
	else
		iter.ops = &hist_iter_normal;

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

182 183
	ret = hist_entry_iter__add(&iter, &al, evsel, sample, rep->max_stack,
				   rep);
184 185
	if (ret < 0)
		pr_debug("problem adding hist entry, skipping event\n");
186

187
	return ret;
188
}
I
Ingo Molnar 已提交
189

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

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

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

	return 0;
}

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

221
	if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
222
		if (sort__has_parent) {
223
			ui__error("Selected --sort parent, but no "
224 225
				    "callchain data. Did you call "
				    "'perf record' without -g?\n");
226
			return -EINVAL;
227
		}
228
		if (symbol_conf.use_callchain) {
229
			ui__error("Selected -g but no callchain data. Did "
230
				    "you call 'perf record' without -g?\n");
231
			return -1;
232
		}
233 234
	} else if (!rep->dont_use_callchains &&
		   callchain_param.mode != CHAIN_NONE &&
235
		   !symbol_conf.use_callchain) {
236
			symbol_conf.use_callchain = true;
237
			if (callchain_register_param(&callchain_param) < 0) {
238
				ui__error("Can't register callchain params.\n");
239
				return -EINVAL;
240
			}
241 242
	}

243 244 245 246 247 248 249 250
	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();
		}
	}

251
	if (sort__mode == SORT_MODE__BRANCH) {
252
		if (!is_pipe &&
253
		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
254 255
			ui__error("Selected -b but no branch data. "
				  "Did you call perf record without -b?\n");
256 257 258 259
			return -1;
		}
	}

260 261 262 263 264 265 266
	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;
		else
			callchain_param.record_mode = CALLCHAIN_FP;
	}
267 268
	return 0;
}
269

270
static void sig_handler(int sig __maybe_unused)
271 272 273 274
{
	session_done = 1;
}

275
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
276 277 278 279
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
280 281 282
	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);
283 284 285
	char buf[512];
	size_t size = sizeof(buf);

286 287 288 289 290
	if (symbol_conf.filter_relative) {
		nr_samples = hists->stats.nr_non_filtered_samples;
		nr_events = hists->stats.total_non_filtered_period;
	}

291
	if (perf_evsel__is_group_event(evsel)) {
292 293 294 295 296 297
		struct perf_evsel *pos;

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

		for_each_group_member(pos, evsel) {
298 299
			const struct hists *pos_hists = evsel__hists(pos);

300
			if (symbol_conf.filter_relative) {
301 302
				nr_samples += pos_hists->stats.nr_non_filtered_samples;
				nr_events += pos_hists->stats.total_non_filtered_period;
303
			} else {
304 305
				nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
				nr_events += pos_hists->stats.total_period;
306
			}
307 308
		}
	}
309

310 311
	nr_samples = convert_unit(nr_samples, &unit);
	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
312
	if (evname != NULL)
313 314
		ret += fprintf(fp, " of event '%s'", evname);

315 316 317 318 319
	if (rep->mem_mode) {
		ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
		ret += fprintf(fp, "\n# Sort order   : %s", sort_order);
	} else
		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
320 321 322
	return ret + fprintf(fp, "\n#\n");
}

323
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
324
					 struct report *rep,
325
					 const char *help)
326
{
327
	struct perf_evsel *pos;
328

329
	evlist__for_each(evlist, pos) {
330
		struct hists *hists = evsel__hists(pos);
331
		const char *evname = perf_evsel__name(pos);
332

333 334 335 336
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

337
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
338
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
339 340 341 342 343 344 345
		fprintf(stdout, "\n\n");
	}

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

346 347 348
		if (rep->show_threads) {
			bool style = !strcmp(rep->pretty_printing_style, "raw");
			perf_read_values_display(stdout, &rep->show_threads_values,
349
						 style);
350
			perf_read_values_destroy(&rep->show_threads_values);
351 352 353 354 355 356
		}
	}

	return 0;
}

357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
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);
	}
}

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 421 422 423 424 425 426 427 428 429 430
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;
}

431
static void report__collapse_hists(struct report *rep)
432 433 434 435
{
	struct ui_progress prog;
	struct perf_evsel *pos;

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

438
	evlist__for_each(rep->session->evlist, pos) {
439
		struct hists *hists = evsel__hists(pos);
440 441 442 443 444 445 446 447 448

		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)) {
449
			struct hists *leader_hists = evsel__hists(pos->leader);
450 451 452 453 454 455 456 457 458

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

	ui_progress__finish();
}

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

466 467
	signal(SIGINT, sig_handler);

468 469 470
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
471
		if (ret)
472
			return ret;
473 474
	}

475 476
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
477

478
	ret = report__setup_sample_type(rep);
479
	if (ret)
480
		return ret;
481

482
	ret = perf_session__process_events(session, &rep->tool);
483
	if (ret)
484
		return ret;
485

486
	report__warn_kptr_restrict(rep);
487

488 489 490
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
491

492 493
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
494

495 496
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
497
			perf_evlist__fprintf_nr_events(session->evlist, stdout);
498 499
			return 0;
		}
500 501
	}

502
	report__collapse_hists(rep);
503

504 505 506
	if (session_done())
		return 0;

507
	if (rep->nr_entries == 0) {
508
		ui__error("The %s file has no samples!\n", file->path);
509
		return 0;
510 511
	}

512
	evlist__for_each(session->evlist, pos)
513
		hists__output_resort(evsel__hists(pos));
514

515
	return report__browse_hists(rep);
516 517
}

518
static int
519
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
520
{
521
	struct report *rep = (struct report *)opt->value;
522

523 524 525 526
	/*
	 * --no-call-graph
	 */
	if (unset) {
527
		rep->dont_use_callchains = true;
528 529 530
		return 0;
	}

531
	return parse_callchain_report_opt(arg);
532 533
}

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
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;
}

552
static int
553 554
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
555
{
556 557 558
	int *branch_mode = opt->value;

	*branch_mode = !unset;
559 560 561
	return 0;
}

562 563 564 565
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
566
	struct report *rep = opt->value;
567 568 569 570 571

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

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

	if (ret < 0)
		return ret;
708

709
	perf_config(report__config, &report);
710

711 712
	argc = parse_options(argc, argv, options, report_usage, 0);

713
	if (report.use_stdio)
714
		use_browser = 0;
715
	else if (report.use_tui)
716
		use_browser = 1;
717 718
	else if (report.use_gtk)
		use_browser = 2;
719

720
	if (report.inverted_callchain)
721 722
		callchain_param.order = ORDER_CALLER;

723
	if (!input_name || !strlen(input_name)) {
724
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
725
			input_name = "-";
726
		else
727
			input_name = "perf.data";
728
	}
729

730 731 732
	file.path  = input_name;
	file.force = report.force;

733
repeat:
734
	session = perf_session__new(&file, false, &report.tool);
735
	if (session == NULL)
736
		return -1;
737

738 739 740 741 742
	if (report.queue_size) {
		ordered_events__set_alloc_size(&session->ordered_events,
					       report.queue_size);
	}

743 744 745 746
	report.session = session;

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

748
	if ((branch_mode == -1 && has_br_stack) || branch_mode == 1) {
749
		sort__mode = SORT_MODE__BRANCH;
750 751
		symbol_conf.cumulate_callchain = false;
	}
752

753
	if (report.mem_mode) {
754
		if (sort__mode == SORT_MODE__BRANCH) {
755
			pr_err("branch and mem mode incompatible\n");
756 757
			goto error;
		}
758
		sort__mode = SORT_MODE__MEMORY;
759
		symbol_conf.cumulate_callchain = false;
760
	}
761

762
	if (setup_sorting() < 0) {
763 764 765 766 767
		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);
768 769
		goto error;
	}
770

771 772 773 774
	/* Force tty output for header output. */
	if (report.header || report.header_only)
		use_browser = 0;

775 776
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
777
	else
778 779
		use_browser = 0;

780 781 782 783 784 785 786 787 788 789
	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);
	}

790
	/*
791
	 * Only in the TUI browser we are doing integrated annotation,
792 793 794
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
795
	if (ui__has_annotation()) {
796
		symbol_conf.priv_size = sizeof(struct annotation);
797 798
		machines__set_symbol_filter(&session->machines,
					    symbol__annotate_init);
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
		/*
 		 * 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;
		}
	}
815

816
	if (symbol__init(&session->header.env) < 0)
817
		goto error;
818

819 820 821 822 823 824 825 826 827 828
	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];
	}
829

830
	sort__setup_elide(stdout);
831

832
	ret = __cmd_report(&report);
833 834 835 836 837 838
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

839 840 841
error:
	perf_session__delete(session);
	return ret;
842
}