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

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

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

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

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

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

39
#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
	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
61
};
62

63
static int report__config(const char *var, const char *value, void *cb)
64 65 66 67 68
{
	if (!strcmp(var, "report.group")) {
		symbol_conf.event_group = perf_config_bool(var, value);
		return 0;
	}
69
	if (!strcmp(var, "report.percent-limit")) {
70
		struct report *rep = cb;
71 72 73
		rep->min_percent = strtof(value, NULL);
		return 0;
	}
74 75 76 77

	return perf_default_config(var, value, cb);
}

78
static int report__add_mem_hist_entry(struct report *rep, struct addr_location *al,
79
				      struct perf_sample *sample, struct perf_evsel *evsel)
80 81 82 83 84
{
	struct symbol *parent = NULL;
	struct hist_entry *he;
	struct mem_info *mi, *mx;
	uint64_t cost;
85
	int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
86

87 88
	if (err)
		return err;
89

90
	mi = sample__resolve_mem(sample, al);
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
	if (!mi)
		return -ENOMEM;

	if (rep->hide_unresolved && !al->sym)
		return 0;

	cost = sample->weight;
	if (!cost)
		cost = 1;

	/*
	 * must pass period=weight in order to get the correct
	 * sorting from hists__collapse_resort() which is solely
	 * based on periods. We want sorting be done on nr_events * weight
	 * and this is indirectly achieved by passing period=weight here
	 * and the he_stat__add_period() function.
	 */
108 109
	he = __hists__add_entry(&evsel->hists, al, parent, NULL, mi,
				cost, cost, 0);
110 111 112
	if (!he)
		return -ENOMEM;

113 114 115 116
	if (ui__has_annotation()) {
		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
		if (err)
			goto out;
117

118 119 120 121 122
		mx = he->mem_info;
		err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
		if (err)
			goto out;
	}
123 124 125

	evsel->hists.stats.total_period += cost;
	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
126 127
	if (!he->filtered)
		evsel->hists.stats.nr_non_filtered_samples++;
128
	err = hist_entry__append_callchain(he, sample);
129 130 131 132
out:
	return err;
}

133
static int report__add_branch_hist_entry(struct report *rep, struct addr_location *al,
134
					 struct perf_sample *sample, struct perf_evsel *evsel)
135 136 137 138
{
	struct symbol *parent = NULL;
	unsigned i;
	struct hist_entry *he;
139
	struct branch_info *bi, *bx;
140
	int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
141

142 143
	if (err)
		return err;
144

145
	bi = sample__resolve_bstack(sample, al);
146 147 148 149 150 151
	if (!bi)
		return -ENOMEM;

	for (i = 0; i < sample->branch_stack->nr; i++) {
		if (rep->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym))
			continue;
152 153 154

		err = -ENOMEM;

155 156 157 158
		/* overwrite the 'al' to branch-to info */
		al->map = bi[i].to.map;
		al->sym = bi[i].to.sym;
		al->addr = bi[i].to.addr;
159 160 161 162
		/*
		 * The report shows the percentage of total branches captured
		 * and not events sampled. Thus we use a pseudo period of 1.
		 */
163 164
		he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
					1, 1, 0);
165
		if (he) {
166 167 168 169 170 171 172 173 174 175 176 177
			if (ui__has_annotation()) {
				bx = he->branch_info;
				err = addr_map_symbol__inc_samples(&bx->from,
								   evsel->idx);
				if (err)
					goto out;

				err = addr_map_symbol__inc_samples(&bx->to,
								   evsel->idx);
				if (err)
					goto out;
			}
178

179 180
			evsel->hists.stats.total_period += 1;
			hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
181 182
			if (!he->filtered)
				evsel->hists.stats.nr_non_filtered_samples++;
183
		} else
184
			goto out;
185
	}
186
	err = 0;
187
out:
188
	free(bi);
189 190 191
	return err;
}

192
static int report__add_hist_entry(struct report *rep, struct perf_evsel *evsel,
193
				  struct addr_location *al, struct perf_sample *sample)
194
{
195
	struct symbol *parent = NULL;
196
	struct hist_entry *he;
197
	int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
198

199 200
	if (err)
		return err;
201

202 203 204
	he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
				sample->period, sample->weight,
				sample->transaction);
205
	if (he == NULL)
206 207
		return -ENOMEM;

208 209 210
	err = hist_entry__append_callchain(he, sample);
	if (err)
		goto out;
211

212 213 214
	if (ui__has_annotation())
		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);

215
	evsel->hists.stats.total_period += sample->period;
216 217
	if (!he->filtered)
		evsel->hists.stats.nr_non_filtered_samples++;
218
	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
219
out:
220
	return err;
221 222
}

223

224
static int process_sample_event(struct perf_tool *tool,
225
				union perf_event *event,
226
				struct perf_sample *sample,
227
				struct perf_evsel *evsel,
228
				struct machine *machine)
229
{
230
	struct report *rep = container_of(tool, struct report, tool);
231
	struct addr_location al;
232
	int ret;
233

234
	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
235 236
		pr_debug("problem processing %d event, skipping it.\n",
			 event->header.type);
237 238
		return -1;
	}
239

240
	if (rep->hide_unresolved && al.sym == NULL)
241
		return 0;
242

243
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
244 245
		return 0;

246
	if (sort__mode == SORT_MODE__BRANCH) {
247
		ret = report__add_branch_hist_entry(rep, &al, sample, evsel);
248
		if (ret < 0)
249
			pr_debug("problem adding lbr entry, skipping event\n");
250
	} else if (rep->mem_mode == 1) {
251
		ret = report__add_mem_hist_entry(rep, &al, sample, evsel);
252
		if (ret < 0)
253
			pr_debug("problem adding mem entry, skipping event\n");
254 255 256
	} else {
		if (al.map != NULL)
			al.map->dso->hit = 1;
257

258
		ret = report__add_hist_entry(rep, evsel, &al, sample);
259
		if (ret < 0)
260
			pr_debug("problem incrementing symbol period, skipping event\n");
261
	}
262
	return ret;
263
}
I
Ingo Molnar 已提交
264

265
static int process_read_event(struct perf_tool *tool,
266
			      union perf_event *event,
267
			      struct perf_sample *sample __maybe_unused,
268
			      struct perf_evsel *evsel,
269
			      struct machine *machine __maybe_unused)
270
{
271
	struct report *rep = container_of(tool, struct report, tool);
272

273
	if (rep->show_threads) {
274
		const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
275
		perf_read_values_add_value(&rep->show_threads_values,
276 277 278 279 280 281
					   event->read.pid, event->read.tid,
					   event->read.id,
					   name,
					   event->read.value);
	}

282
	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
283
		    evsel ? perf_evsel__name(evsel) : "FAIL",
284
		    event->read.value);
285 286 287 288

	return 0;
}

289
/* For pipe mode, sample_type is not currently set */
290
static int report__setup_sample_type(struct report *rep)
291
{
292 293 294
	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);
295

296
	if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
297
		if (sort__has_parent) {
298
			ui__error("Selected --sort parent, but no "
299 300
				    "callchain data. Did you call "
				    "'perf record' without -g?\n");
301
			return -EINVAL;
302
		}
303
		if (symbol_conf.use_callchain) {
304
			ui__error("Selected -g but no callchain data. Did "
305
				    "you call 'perf record' without -g?\n");
306
			return -1;
307
		}
308 309
	} else if (!rep->dont_use_callchains &&
		   callchain_param.mode != CHAIN_NONE &&
310
		   !symbol_conf.use_callchain) {
311
			symbol_conf.use_callchain = true;
312
			if (callchain_register_param(&callchain_param) < 0) {
313
				ui__error("Can't register callchain params.\n");
314
				return -EINVAL;
315
			}
316 317
	}

318
	if (sort__mode == SORT_MODE__BRANCH) {
319
		if (!is_pipe &&
320
		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
321 322
			ui__error("Selected -b but no branch data. "
				  "Did you call perf record without -b?\n");
323 324 325 326
			return -1;
		}
	}

327 328
	return 0;
}
329

330
static void sig_handler(int sig __maybe_unused)
331 332 333 334
{
	session_done = 1;
}

335
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
336 337 338 339
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
340 341 342
	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);
343 344 345
	char buf[512];
	size_t size = sizeof(buf);

346 347 348 349 350
	if (symbol_conf.filter_relative) {
		nr_samples = hists->stats.nr_non_filtered_samples;
		nr_events = hists->stats.total_non_filtered_period;
	}

351
	if (perf_evsel__is_group_event(evsel)) {
352 353 354 355 356 357
		struct perf_evsel *pos;

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

		for_each_group_member(pos, evsel) {
358 359 360 361 362 363 364
			if (symbol_conf.filter_relative) {
				nr_samples += pos->hists.stats.nr_non_filtered_samples;
				nr_events += pos->hists.stats.total_non_filtered_period;
			} else {
				nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
				nr_events += pos->hists.stats.total_period;
			}
365 366
		}
	}
367

368 369
	nr_samples = convert_unit(nr_samples, &unit);
	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
370
	if (evname != NULL)
371 372
		ret += fprintf(fp, " of event '%s'", evname);

373 374 375 376 377
	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);
378 379 380
	return ret + fprintf(fp, "\n#\n");
}

381
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
382
					 struct report *rep,
383
					 const char *help)
384
{
385
	struct perf_evsel *pos;
386

387
	evlist__for_each(evlist, pos) {
388
		struct hists *hists = &pos->hists;
389
		const char *evname = perf_evsel__name(pos);
390

391 392 393 394
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

395
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
396
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
397 398 399 400 401 402 403
		fprintf(stdout, "\n\n");
	}

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

404 405 406
		if (rep->show_threads) {
			bool style = !strcmp(rep->pretty_printing_style, "raw");
			perf_read_values_display(stdout, &rep->show_threads_values,
407
						 style);
408
			perf_read_values_destroy(&rep->show_threads_values);
409 410 411 412 413 414
		}
	}

	return 0;
}

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

444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
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;
}

489 490 491 492 493 494 495 496 497
static u64 report__collapse_hists(struct report *rep)
{
	struct ui_progress prog;
	struct perf_evsel *pos;
	u64 nr_samples = 0;
	/*
 	 * Count number of histogram entries to use when showing progress,
 	 * reusing nr_samples variable.
 	 */
498
	evlist__for_each(rep->session->evlist, pos)
499 500 501 502 503 504 505 506 507
		nr_samples += pos->hists.nr_entries;

	ui_progress__init(&prog, nr_samples, "Merging related events...");
	/*
	 * Count total number of samples, will be used to check if this
 	 * session had any.
 	 */
	nr_samples = 0;

508
	evlist__for_each(rep->session->evlist, pos) {
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
		struct hists *hists = &pos->hists;

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

		hists__collapse_resort(hists, &prog);
		nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];

		/* Non-group events are considered as leader */
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos)) {
			struct hists *leader_hists = &pos->leader->hists;

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

	ui_progress__finish();

	return nr_samples;
}

532
static int __cmd_report(struct report *rep)
533
{
534
	int ret;
535
	u64 nr_samples;
536
	struct perf_session *session = rep->session;
537
	struct perf_evsel *pos;
538
	struct perf_data_file *file = session->file;
539

540 541
	signal(SIGINT, sig_handler);

542 543 544
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
545
		if (ret)
546
			return ret;
547 548
	}

549 550
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
551

552
	ret = report__setup_sample_type(rep);
553
	if (ret)
554
		return ret;
555

556
	ret = perf_session__process_events(session, &rep->tool);
557
	if (ret)
558
		return ret;
559

560
	report__warn_kptr_restrict(rep);
561

562 563 564
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
565

566 567
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
568

569 570 571 572
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
			return 0;
		}
573 574
	}

575
	nr_samples = report__collapse_hists(rep);
576

577 578 579
	if (session_done())
		return 0;

580
	if (nr_samples == 0) {
581
		ui__error("The %s file has no samples!\n", file->path);
582
		return 0;
583 584
	}

585
	evlist__for_each(session->evlist, pos)
586 587
		hists__output_resort(&pos->hists);

588
	return report__browse_hists(rep);
589 590
}

591
static int
592
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
593
{
594
	struct report *rep = (struct report *)opt->value;
595

596 597 598 599
	/*
	 * --no-call-graph
	 */
	if (unset) {
600
		rep->dont_use_callchains = true;
601 602 603
		return 0;
	}

604
	return parse_callchain_report_opt(arg);
605 606
}

607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
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;
}

625
static int
626 627
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
628
{
629 630 631
	int *branch_mode = opt->value;

	*branch_mode = !unset;
632 633 634
	return 0;
}

635 636 637 638
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
639
	struct report *rep = opt->value;
640 641 642 643 644

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

645
int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
646
{
647
	struct perf_session *session;
648
	struct stat st;
649
	bool has_br_stack = false;
650
	int branch_mode = -1;
651
	int ret = -1;
652 653
	char callchain_default_opt[] = "fractal,0.5,callee";
	const char * const report_usage[] = {
N
Namhyung Kim 已提交
654
		"perf report [<options>]",
655 656
		NULL
	};
657
	struct report report = {
658
		.tool = {
659 660
			.sample		 = process_sample_event,
			.mmap		 = perf_event__process_mmap,
661
			.mmap2		 = perf_event__process_mmap2,
662
			.comm		 = perf_event__process_comm,
663 664
			.exit		 = perf_event__process_exit,
			.fork		 = perf_event__process_fork,
665 666 667 668 669 670 671 672
			.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,
			.ordered_samples = true,
			.ordering_requires_timestamps = true,
		},
673
		.max_stack		 = PERF_MAX_STACK_DEPTH,
674 675 676
		.pretty_printing_style	 = "normal",
	};
	const struct option options[] = {
677
	OPT_STRING('i', "input", &input_name, "file",
678
		    "input file name"),
679
	OPT_INCR('v', "verbose", &verbose,
680
		    "be more verbose (show symbol address, etc)"),
681 682
	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
		    "dump raw trace in ASCII"),
683 684
	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
		   "file", "vmlinux pathname"),
685 686
	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
		   "file", "kallsyms pathname"),
687
	OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"),
688
	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
689
		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
690
	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
691
		    "Show a column with the number of samples"),
692
	OPT_BOOLEAN('T', "threads", &report.show_threads,
693
		    "Show per-thread event counters"),
694
	OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
695
		   "pretty printing style key: normal raw"),
696
	OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
697
	OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
698 699
	OPT_BOOLEAN(0, "stdio", &report.use_stdio,
		    "Use the stdio interface"),
700 701 702
	OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
	OPT_BOOLEAN(0, "header-only", &report.header_only,
		    "Show only data header."),
703
	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
704
		   "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
705
		   " dso_to, dso_from, symbol_to, symbol_from, mispredict,"
706
		   " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, "
707
		   "snoop, locked, abort, in_tx, transaction"),
708 709
	OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
		    "Show sample percentage for different cpu modes"),
710 711
	OPT_STRING('p', "parent", &parent_pattern, "regex",
		   "regex filter to identify parent, see: '--sort parent'"),
712
	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
713
		    "Only display entries with parent-match"),
714
	OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
715
		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
716
		     "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt),
717 718 719 720
	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)),
721 722
	OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
		    "alias for inverted call graph"),
723 724 725
	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
		   "ignore callees of these functions in call graphs",
		   report_parse_ignore_callees_opt),
726
	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
727
		   "only consider symbols in these dsos"),
728
	OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
729
		   "only consider symbols in these comms"),
730
	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
731
		   "only consider these symbols"),
732 733
	OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
		   "only show symbols that (partially) match with this filter"),
734
	OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
735 736
		   "width[,width...]",
		   "don't try to adjust column width, use these fixed values"),
737
	OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
738 739
		   "separator for columns, no spaces will be added between "
		   "columns '.' is reserved."),
740
	OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
741
		    "Only display entries resolved to a symbol"),
742 743
	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
		    "Look for files with symbols relative to this directory"),
744
	OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
745 746
		   "list of cpus to profile"),
	OPT_BOOLEAN('I', "show-info", &report.show_full_info,
747
		    "Display extended information about perf.data file"),
748 749 750 751
	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)"),
752 753
	OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
754 755
	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
		    "Show a column with the sum of periods"),
N
Namhyung Kim 已提交
756 757
	OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
		    "Show event group information together"),
758
	OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
759
		    "use branch records for histogram filling", parse_branch_mode),
760 761
	OPT_STRING(0, "objdump", &objdump_path, "path",
		   "objdump binary to use for disassembly and annotations"),
762 763
	OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
		    "Disable symbol demangling"),
764
	OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
765 766
	OPT_CALLBACK(0, "percent-limit", &report, "percent",
		     "Don't show entries under that percent", parse_percent_limit),
767
	OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
N
Namhyung Kim 已提交
768
		     "how to display percentage of filtered entries", parse_filter_percentage),
769
	OPT_END()
770
	};
771 772 773
	struct perf_data_file file = {
		.mode  = PERF_DATA_MODE_READ,
	};
774

775
	perf_config(report__config, &report);
776

777 778
	argc = parse_options(argc, argv, options, report_usage, 0);

779
	if (report.use_stdio)
780
		use_browser = 0;
781
	else if (report.use_tui)
782
		use_browser = 1;
783 784
	else if (report.use_gtk)
		use_browser = 2;
785

786
	if (report.inverted_callchain)
787 788
		callchain_param.order = ORDER_CALLER;

789
	if (!input_name || !strlen(input_name)) {
790
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
791
			input_name = "-";
792
		else
793
			input_name = "perf.data";
794
	}
795

796 797 798
	file.path  = input_name;
	file.force = report.force;

799
repeat:
800
	session = perf_session__new(&file, false, &report.tool);
801 802 803 804 805 806 807
	if (session == NULL)
		return -ENOMEM;

	report.session = session;

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

809 810
	if (branch_mode == -1 && has_br_stack)
		sort__mode = SORT_MODE__BRANCH;
811

812 813
	/* sort__mode could be NORMAL if --no-branch-stack */
	if (sort__mode == SORT_MODE__BRANCH) {
814
		/*
815 816
		 * if no sort_order is provided, then specify
		 * branch-mode specific order
817 818 819 820 821
		 */
		if (sort_order == default_sort_order)
			sort_order = "comm,dso_from,symbol_from,"
				     "dso_to,symbol_to";

822
	}
823
	if (report.mem_mode) {
824
		if (sort__mode == SORT_MODE__BRANCH) {
825
			pr_err("branch and mem mode incompatible\n");
826 827
			goto error;
		}
828 829
		sort__mode = SORT_MODE__MEMORY;

830 831 832 833 834 835 836
		/*
		 * if no sort_order is provided, then specify
		 * branch-mode specific order
		 */
		if (sort_order == default_sort_order)
			sort_order = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
	}
837

838 839 840 841
	if (setup_sorting() < 0) {
		parse_options_usage(report_usage, options, "s", 1);
		goto error;
	}
842

843 844 845 846 847
	if (parent_pattern != default_parent_pattern) {
		if (sort_dimension__add("parent") < 0)
			goto error;
	}

848 849 850 851
	/* Force tty output for header output. */
	if (report.header || report.header_only)
		use_browser = 0;

852 853 854 855 856 857 858
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
	else {
		use_browser = 0;
		perf_hpp__init();
	}

859 860 861 862 863 864 865 866 867 868
	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);
	}

869
	/*
870
	 * Only in the TUI browser we are doing integrated annotation,
871 872 873
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
874
	if (ui__has_annotation()) {
875
		symbol_conf.priv_size = sizeof(struct annotation);
876 877
		machines__set_symbol_filter(&session->machines,
					    symbol__annotate_init);
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
		/*
 		 * 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;
		}
	}
894

895
	if (symbol__init() < 0)
896
		goto error;
897

898 899 900 901 902 903 904 905 906 907
	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];
	}
908

909
	sort__setup_elide(stdout);
910

911
	ret = __cmd_report(&report);
912 913 914 915 916 917
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

918 919 920
error:
	perf_session__delete(session);
	return ret;
921
}