builtin-report.c 28.1 KB
Newer Older
1 2 3 4 5 6 7
/*
 * builtin-report.c
 *
 * Builtin report command: Analyze the perf.data input file,
 * look up and read DSOs and symbol information and display
 * a histogram of results, along various sorting keys.
 */
8
#include "builtin.h"
9

10
#include "util/util.h"
11
#include "util/cache.h"
12

13
#include "util/annotate.h"
14
#include "util/color.h"
15
#include <linux/list.h>
16
#include <linux/rbtree.h>
17
#include "util/symbol.h"
18
#include "util/callchain.h"
19
#include "util/strlist.h"
20
#include "util/values.h"
21

22
#include "perf.h"
23
#include "util/debug.h"
24 25
#include "util/evlist.h"
#include "util/evsel.h"
26
#include "util/header.h"
27
#include "util/session.h"
28
#include "util/tool.h"
29 30 31 32

#include "util/parse-options.h"
#include "util/parse-events.h"

33
#include "util/thread.h"
34
#include "util/sort.h"
35
#include "util/hist.h"
36
#include "util/data.h"
37
#include "arch/common.h"
38

39 40
#include "util/auxtrace.h"

41
#include <dlfcn.h>
42 43
#include <linux/bitmap.h>

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

68
static int report__config(const char *var, const char *value, void *cb)
69
{
70 71
	struct report *rep = cb;

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

	return perf_default_config(var, value, cb);
}

92 93 94 95 96 97 98 99 100 101 102 103 104 105
static int hist_iter__report_callback(struct hist_entry_iter *iter,
				      struct addr_location *al, bool single,
				      void *arg)
{
	int err = 0;
	struct report *rep = arg;
	struct hist_entry *he = iter->he;
	struct perf_evsel *evsel = iter->evsel;
	struct mem_info *mi;
	struct branch_info *bi;

	if (!ui__has_annotation())
		return 0;

106 107 108
	hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
			     rep->nonany_branch_mode);

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
	if (sort__mode == SORT_MODE__BRANCH) {
		bi = he->branch_info;
		err = addr_map_symbol__inc_samples(&bi->from, evsel->idx);
		if (err)
			goto out;

		err = addr_map_symbol__inc_samples(&bi->to, evsel->idx);

	} else if (rep->mem_mode) {
		mi = he->mem_info;
		err = addr_map_symbol__inc_samples(&mi->daddr, evsel->idx);
		if (err)
			goto out;

		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);

	} else if (symbol_conf.cumulate_callchain) {
		if (single)
			err = hist_entry__inc_addr_samples(he, evsel->idx,
							   al->addr);
	} else {
		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
	}

out:
	return err;
135 136
}

137
static int process_sample_event(struct perf_tool *tool,
138
				union perf_event *event,
139
				struct perf_sample *sample,
140
				struct perf_evsel *evsel,
141
				struct machine *machine)
142
{
143
	struct report *rep = container_of(tool, struct report, tool);
144
	struct addr_location al;
145
	struct hist_entry_iter iter = {
146 147
		.evsel 			= evsel,
		.sample 		= sample,
148
		.hide_unresolved 	= symbol_conf.hide_unresolved,
149
		.add_entry_cb 		= hist_iter__report_callback,
150
	};
151
	int ret = 0;
152

153
	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
154 155
		pr_debug("problem processing %d event, skipping it.\n",
			 event->header.type);
156 157
		return -1;
	}
158

159
	if (symbol_conf.hide_unresolved && al.sym == NULL)
160
		goto out_put;
161

162
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
163
		goto out_put;
164

165 166 167 168 169 170 171
	if (sort__mode == SORT_MODE__BRANCH) {
		/*
		 * A non-synthesized event might not have a branch stack if
		 * branch stacks have been synthesized (using itrace options).
		 */
		if (!sample->branch_stack)
			goto out_put;
172
		iter.ops = &hist_iter_branch;
173
	} else if (rep->mem_mode) {
174
		iter.ops = &hist_iter_mem;
175
	} else if (symbol_conf.cumulate_callchain) {
176
		iter.ops = &hist_iter_cumulative;
177
	} else {
178
		iter.ops = &hist_iter_normal;
179
	}
180 181 182 183

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

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

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

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

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

	return 0;
}

216
/* For pipe mode, sample_type is not currently set */
217
static int report__setup_sample_type(struct report *rep)
218
{
219 220 221
	struct perf_session *session = rep->session;
	u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
	bool is_pipe = perf_data_file__is_pipe(session->file);
222

223 224 225 226 227 228
	if (session->itrace_synth_opts->callchain ||
	    (!is_pipe &&
	     perf_header__has_feat(&session->header, HEADER_AUXTRACE) &&
	     !session->itrace_synth_opts->set))
		sample_type |= PERF_SAMPLE_CALLCHAIN;

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

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

255 256 257 258 259 260 261 262
	if (symbol_conf.cumulate_callchain) {
		/* Silently ignore if callchain is missing */
		if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
			symbol_conf.cumulate_callchain = false;
			perf_hpp__cancel_cumulate();
		}
	}

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

272 273 274 275
	if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
		if ((sample_type & PERF_SAMPLE_REGS_USER) &&
		    (sample_type & PERF_SAMPLE_STACK_USER))
			callchain_param.record_mode = CALLCHAIN_DWARF;
276 277
		else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
			callchain_param.record_mode = CALLCHAIN_LBR;
278 279 280
		else
			callchain_param.record_mode = CALLCHAIN_FP;
	}
281 282 283 284 285 286

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

287 288
	return 0;
}
289

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

295
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
296 297 298 299
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
300 301 302
	unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
	u64 nr_events = hists->stats.total_period;
	struct perf_evsel *evsel = hists_to_evsel(hists);
303 304
	char buf[512];
	size_t size = sizeof(buf);
305
	int socked_id = hists->socket_filter;
306

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

377 378 379 380 381
	if (rep->show_threads) {
		bool style = !strcmp(rep->pretty_printing_style, "raw");
		perf_read_values_display(stdout, &rep->show_threads_values,
					 style);
		perf_read_values_destroy(&rep->show_threads_values);
382 383 384 385 386
	}

	return 0;
}

387 388
static void report__warn_kptr_restrict(const struct report *rep)
{
389
	struct map *kernel_map = machine__kernel_map(&rep->session->machines.host);
390
	struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415

	if (kernel_map == NULL ||
	    (kernel_map->dso->hit &&
	     (kernel_kmap->ref_reloc_sym == NULL ||
	      kernel_kmap->ref_reloc_sym->addr == 0))) {
		const char *desc =
		    "As no suitable kallsyms nor vmlinux was found, kernel samples\n"
		    "can't be resolved.";

		if (kernel_map) {
			const struct dso *kdso = kernel_map->dso;
			if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) {
				desc = "If some relocation was applied (e.g. "
				       "kexec) symbols may be misresolved.";
			}
		}

		ui__warning(
"Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n"
"Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n"
"Samples in kernel modules can't be resolved as well.\n\n",
		desc);
	}
}

416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
static int report__gtk_browse_hists(struct report *rep, const char *help)
{
	int (*hist_browser)(struct perf_evlist *evlist, const char *help,
			    struct hist_browser_timer *timer, float min_pcnt);

	hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists");

	if (hist_browser == NULL) {
		ui__error("GTK browser not found!\n");
		return -1;
	}

	return hist_browser(rep->session->evlist, help, NULL, rep->min_percent);
}

static int report__browse_hists(struct report *rep)
{
	int ret;
	struct perf_session *session = rep->session;
	struct perf_evlist *evlist = session->evlist;
	const char *help = "For a higher level overview, try: perf report --sort comm,dso";

	switch (use_browser) {
	case 1:
		ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
						    rep->min_percent,
						    &session->header.env);
		/*
		 * Usually "ret" is the last pressed key, and we only
		 * care if the key notifies us to switch data file.
		 */
		if (ret != K_SWITCH_INPUT_DATA)
			ret = 0;
		break;
	case 2:
		ret = report__gtk_browse_hists(rep, help);
		break;
	default:
		ret = perf_evlist__tty_browse_hists(evlist, rep, help);
		break;
	}

	return ret;
}

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

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

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

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

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

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

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

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

	ui_progress__finish();
}

491 492 493 494 495 496 497 498 499 500 501 502 503
static void report__output_resort(struct report *rep)
{
	struct ui_progress prog;
	struct perf_evsel *pos;

	ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");

	evlist__for_each(rep->session->evlist, pos)
		hists__output_resort(evsel__hists(pos), &prog);

	ui_progress__finish();
}

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

511 512
	signal(SIGINT, sig_handler);

513 514 515
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
516 517
		if (ret) {
			ui__error("failed to set cpu bitmap\n");
518
			return ret;
519
		}
520 521
	}

522 523
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
524

525
	ret = report__setup_sample_type(rep);
526 527
	if (ret) {
		/* report__setup_sample_type() already showed error message */
528
		return ret;
529
	}
530

531
	ret = perf_session__process_events(session);
532 533
	if (ret) {
		ui__error("failed to process sample\n");
534
		return ret;
535
	}
536

537
	report__warn_kptr_restrict(rep);
538

539 540 541
	evlist__for_each(session->evlist, pos)
		rep->nr_entries += evsel__hists(pos)->nr_entries;

542 543 544
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
545

546 547
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
548

549 550
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
551
			perf_evlist__fprintf_nr_events(session->evlist, stdout);
552 553
			return 0;
		}
554 555
	}

556
	report__collapse_hists(rep);
557

558 559 560
	if (session_done())
		return 0;

561 562 563 564 565 566 567 568
	/*
	 * 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;

569
	if (rep->nr_entries == 0) {
570
		ui__error("The %s file has no samples!\n", file->path);
571
		return 0;
572 573
	}

574
	report__output_resort(rep);
575

576
	return report__browse_hists(rep);
577 578
}

579
static int
580
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
581
{
582
	struct report *rep = (struct report *)opt->value;
583

584 585 586 587
	/*
	 * --no-call-graph
	 */
	if (unset) {
588
		rep->dont_use_callchains = true;
589 590 591
		return 0;
	}

592
	return parse_callchain_report_opt(arg);
593 594
}

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
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;
}

613
static int
614 615
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
616
{
617 618 619
	int *branch_mode = opt->value;

	*branch_mode = !unset;
620 621 622
	return 0;
}

623 624 625 626
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
627
	struct report *rep = opt->value;
628 629 630 631 632

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

633
#define CALLCHAIN_DEFAULT_OPT  "graph,0.5,caller,function,percent"
634 635 636 637

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

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

	if (ret < 0)
		return ret;
800

801
	perf_config(report__config, &report);
802

803
	argc = parse_options(argc, argv, options, report_usage, 0);
804 805 806 807 808 809 810 811 812 813
	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];
	}
814

815 816 817 818 819 820 821 822 823 824 825
	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;
	}

826
	if (report.use_stdio)
827
		use_browser = 0;
828
	else if (report.use_tui)
829
		use_browser = 1;
830 831
	else if (report.use_gtk)
		use_browser = 2;
832

833
	if (report.inverted_callchain)
834
		callchain_param.order = ORDER_CALLER;
835 836
	if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
		callchain_param.order = ORDER_CALLER;
837

838 839 840 841
	if (itrace_synth_opts.callchain &&
	    (int)itrace_synth_opts.callchain_sz > report.max_stack)
		report.max_stack = itrace_synth_opts.callchain_sz;

842
	if (!input_name || !strlen(input_name)) {
843
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
844
			input_name = "-";
845
		else
846
			input_name = "perf.data";
847
	}
848

849
	file.path  = input_name;
850
	file.force = symbol_conf.force;
851

852
repeat:
853
	session = perf_session__new(&file, false, &report.tool);
854
	if (session == NULL)
855
		return -1;
856

857 858 859 860 861
	if (report.queue_size) {
		ordered_events__set_alloc_size(&session->ordered_events,
					       report.queue_size);
	}

862 863
	session->itrace_synth_opts = &itrace_synth_opts;

864 865 866 867
	report.session = session;

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

869 870 871
	if (itrace_synth_opts.last_branch)
		has_br_stack = true;

872 873 874 875 876 877
	/*
	 * 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) &&
878
	    !branch_call_mode) {
879
		sort__mode = SORT_MODE__BRANCH;
880 881
		symbol_conf.cumulate_callchain = false;
	}
882
	if (branch_call_mode) {
883
		callchain_param.key = CCKEY_ADDRESS;
884 885 886 887 888 889
		callchain_param.branch_callstack = 1;
		symbol_conf.use_callchain = true;
		callchain_register_param(&callchain_param);
		if (sort_order == NULL)
			sort_order = "srcline,symbol,dso";
	}
890

891
	if (report.mem_mode) {
892
		if (sort__mode == SORT_MODE__BRANCH) {
893
			pr_err("branch and mem mode incompatible\n");
894 895
			goto error;
		}
896
		sort__mode = SORT_MODE__MEMORY;
897
		symbol_conf.cumulate_callchain = false;
898
	}
899

900
	if (setup_sorting() < 0) {
901 902 903 904 905
		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);
906 907
		goto error;
	}
908

909 910
	/* Force tty output for header output and per-thread stat. */
	if (report.header || report.header_only || report.show_threads)
911 912
		use_browser = 0;

913 914
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
915
	else
916 917
		use_browser = 0;

918 919 920
	if (report.header || report.header_only) {
		perf_session__fprintf_info(session, stdout,
					   report.show_full_info);
921 922 923 924
		if (report.header_only) {
			ret = 0;
			goto error;
		}
925 926 927 928 929
	} else if (use_browser == 0) {
		fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
		      stdout);
	}

930
	/*
931
	 * Only in the TUI browser we are doing integrated annotation,
932 933 934
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
935
	if (ui__has_annotation()) {
936
		symbol_conf.priv_size = sizeof(struct annotation);
937 938
		machines__set_symbol_filter(&session->machines,
					    symbol__annotate_init);
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
		/*
 		 * 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;
		}
	}
955

956
	if (symbol__init(&session->header.env) < 0)
957
		goto error;
958

959
	sort__setup_elide(stdout);
960

961
	ret = __cmd_report(&report);
962 963 964 965 966 967
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

968 969 970
error:
	perf_session__delete(session);
	return ret;
971
}