builtin-report.c 26.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
	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__resolve_callchain(struct report *rep, struct symbol **parent,
79
				     struct perf_evsel *evsel, struct addr_location *al,
80
				     struct perf_sample *sample)
81 82
{
	if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
83
		return machine__resolve_callchain(al->machine, evsel, al->thread, sample,
84 85 86 87 88 89 90 91 92 93 94 95
						  parent, al, rep->max_stack);
	}
	return 0;
}

static int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
{
	if (!symbol_conf.use_callchain)
		return 0;
	return callchain_append(he->callchain, &callchain_cursor, sample->period);
}

96 97
static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al,
				      struct perf_sample *sample, struct perf_evsel *evsel,
98
				      union perf_event *event)
99
{
100
	struct report *rep = container_of(tool, struct report, tool);
101 102 103 104 105
	struct symbol *parent = NULL;
	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
	struct hist_entry *he;
	struct mem_info *mi, *mx;
	uint64_t cost;
106
	int err = report__resolve_callchain(rep, &parent, evsel, al, sample);
107

108 109
	if (err)
		return err;
110

111
	mi = machine__resolve_mem(al->machine, al->thread, sample, cpumode);
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
	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.
	 */
129 130
	he = __hists__add_entry(&evsel->hists, al, parent, NULL, mi,
				cost, cost, 0);
131 132 133
	if (!he)
		return -ENOMEM;

134 135 136
	err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
	if (err)
		goto out;
137

138
	mx = he->mem_info;
139
	err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
140 141
	if (err)
		goto out;
142 143 144

	evsel->hists.stats.total_period += cost;
	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
145
	err = hist_entry__append_callchain(he, sample);
146 147 148 149
out:
	return err;
}

150
static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al,
151
					 struct perf_sample *sample, struct perf_evsel *evsel)
152
{
153
	struct report *rep = container_of(tool, struct report, tool);
154 155 156
	struct symbol *parent = NULL;
	unsigned i;
	struct hist_entry *he;
157
	struct branch_info *bi, *bx;
158
	int err = report__resolve_callchain(rep, &parent, evsel, al, sample);
159

160 161
	if (err)
		return err;
162

163
	bi = machine__resolve_bstack(al->machine, al->thread,
164 165 166 167 168 169 170
				     sample->branch_stack);
	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;
171 172 173

		err = -ENOMEM;

174 175 176 177
		/* 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;
178 179 180 181
		/*
		 * The report shows the percentage of total branches captured
		 * and not events sampled. Thus we use a pseudo period of 1.
		 */
182 183
		he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
					1, 1, 0);
184
		if (he) {
185
			bx = he->branch_info;
186
			err = addr_map_symbol__inc_samples(&bx->from, evsel->idx);
187 188 189
			if (err)
				goto out;

190
			err = addr_map_symbol__inc_samples(&bx->to, evsel->idx);
191 192 193
			if (err)
				goto out;

194 195 196
			evsel->hists.stats.total_period += 1;
			hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
		} else
197
			goto out;
198
	}
199
	err = 0;
200
out:
201
	free(bi);
202 203 204
	return err;
}

205
static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel,
206
				  struct addr_location *al, struct perf_sample *sample)
207
{
208
	struct report *rep = container_of(tool, struct report, tool);
209
	struct symbol *parent = NULL;
210
	struct hist_entry *he;
211
	int err = report__resolve_callchain(rep, &parent, evsel, al, sample);
212

213 214
	if (err)
		return err;
215

216 217 218
	he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
				sample->period, sample->weight,
				sample->transaction);
219
	if (he == NULL)
220 221
		return -ENOMEM;

222 223 224
	err = hist_entry__append_callchain(he, sample);
	if (err)
		goto out;
225

226
	err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
227 228
	evsel->hists.stats.total_period += sample->period;
	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
229
out:
230
	return err;
231 232
}

233

234
static int process_sample_event(struct perf_tool *tool,
235
				union perf_event *event,
236
				struct perf_sample *sample,
237
				struct perf_evsel *evsel,
238
				struct machine *machine)
239
{
240
	struct report *rep = container_of(tool, struct report, tool);
241
	struct addr_location al;
242
	int ret;
243

244
	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
245 246
		pr_debug("problem processing %d event, skipping it.\n",
			 event->header.type);
247 248
		return -1;
	}
249

250
	if (al.filtered || (rep->hide_unresolved && al.sym == NULL))
251
		return 0;
252

253
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
254 255
		return 0;

256
	if (sort__mode == SORT_MODE__BRANCH) {
257
		ret = report__add_branch_hist_entry(tool, &al, sample, evsel);
258
		if (ret < 0)
259
			pr_debug("problem adding lbr entry, skipping event\n");
260
	} else if (rep->mem_mode == 1) {
261
		ret = report__add_mem_hist_entry(tool, &al, sample, evsel, event);
262
		if (ret < 0)
263
			pr_debug("problem adding mem entry, skipping event\n");
264 265 266
	} else {
		if (al.map != NULL)
			al.map->dso->hit = 1;
267

268
		ret = report__add_hist_entry(tool, evsel, &al, sample);
269
		if (ret < 0)
270
			pr_debug("problem incrementing symbol period, skipping event\n");
271
	}
272
	return ret;
273
}
I
Ingo Molnar 已提交
274

275
static int process_read_event(struct perf_tool *tool,
276
			      union perf_event *event,
277
			      struct perf_sample *sample __maybe_unused,
278
			      struct perf_evsel *evsel,
279
			      struct machine *machine __maybe_unused)
280
{
281
	struct report *rep = container_of(tool, struct report, tool);
282

283
	if (rep->show_threads) {
284
		const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
285
		perf_read_values_add_value(&rep->show_threads_values,
286 287 288 289 290 291
					   event->read.pid, event->read.tid,
					   event->read.id,
					   name,
					   event->read.value);
	}

292
	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
293
		    evsel ? perf_evsel__name(evsel) : "FAIL",
294
		    event->read.value);
295 296 297 298

	return 0;
}

299
/* For pipe mode, sample_type is not currently set */
300
static int report__setup_sample_type(struct report *rep)
301
{
302 303 304
	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);
305

306
	if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
307
		if (sort__has_parent) {
308
			ui__error("Selected --sort parent, but no "
309 310
				    "callchain data. Did you call "
				    "'perf record' without -g?\n");
311
			return -EINVAL;
312
		}
313
		if (symbol_conf.use_callchain) {
314
			ui__error("Selected -g but no callchain data. Did "
315
				    "you call 'perf record' without -g?\n");
316
			return -1;
317
		}
318 319
	} else if (!rep->dont_use_callchains &&
		   callchain_param.mode != CHAIN_NONE &&
320
		   !symbol_conf.use_callchain) {
321
			symbol_conf.use_callchain = true;
322
			if (callchain_register_param(&callchain_param) < 0) {
323
				ui__error("Can't register callchain params.\n");
324
				return -EINVAL;
325
			}
326 327
	}

328
	if (sort__mode == SORT_MODE__BRANCH) {
329
		if (!is_pipe &&
330
		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
331 332
			ui__error("Selected -b but no branch data. "
				  "Did you call perf record without -b?\n");
333 334 335 336
			return -1;
		}
	}

337 338
	return 0;
}
339

340
static void sig_handler(int sig __maybe_unused)
341 342 343 344
{
	session_done = 1;
}

345
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
346 347 348 349
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
350 351 352
	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);
353 354 355
	char buf[512];
	size_t size = sizeof(buf);

356
	if (perf_evsel__is_group_event(evsel)) {
357 358 359 360 361 362 363 364 365 366
		struct perf_evsel *pos;

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

		for_each_group_member(pos, evsel) {
			nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
			nr_events += pos->hists.stats.total_period;
		}
	}
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 388
	list_for_each_entry(pos, &evlist->entries, node) {
		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
static int __cmd_report(struct report *rep)
445
{
446
	int ret = -EINVAL;
447
	u64 nr_samples;
448
	struct perf_session *session = rep->session;
449
	struct perf_evsel *pos;
450
	const char *help = "For a higher level overview, try: perf report --sort comm,dso";
451
	struct ui_progress prog;
452
	struct perf_data_file *file = session->file;
453

454 455
	signal(SIGINT, sig_handler);

456 457 458
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
459
		if (ret)
460
			return ret;
461 462
	}

463 464
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
465

466
	ret = report__setup_sample_type(rep);
467
	if (ret)
468
		return ret;
469

470
	ret = perf_session__process_events(session, &rep->tool);
471
	if (ret)
472
		return ret;
473

474
	report__warn_kptr_restrict(rep);
475

476 477 478
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
479

480 481
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
482

483 484 485 486
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
			return 0;
		}
487 488
	}

489 490 491 492 493 494
	nr_samples = 0;
	list_for_each_entry(pos, &session->evlist->entries, node)
		nr_samples += pos->hists.nr_entries;

	ui_progress__init(&prog, nr_samples, "Merging related events...");

495 496 497
	nr_samples = 0;
	list_for_each_entry(pos, &session->evlist->entries, node) {
		struct hists *hists = &pos->hists;
498

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

502
		hists__collapse_resort(hists, &prog);
503
		nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
504 505 506 507 508 509 510 511 512

		/* 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);
		}
513
	}
514
	ui_progress__finish();
515

516 517 518
	if (session_done())
		return 0;

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

524 525 526
	list_for_each_entry(pos, &session->evlist->entries, node)
		hists__output_resort(&pos->hists);

527
	if (use_browser > 0) {
528
		if (use_browser == 1) {
529
			ret = perf_evlist__tui_browse_hists(session->evlist,
530 531
							help, NULL,
							rep->min_percent,
532 533 534 535 536 537 538 539
							&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;

540
		} else if (use_browser == 2) {
541 542 543 544 545 546 547 548 549 550 551 552 553
			int (*hist_browser)(struct perf_evlist *,
					    const char *,
					    struct hist_browser_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 ret;
			}
			hist_browser(session->evlist, help, NULL,
				     rep->min_percent);
554
		}
555
	} else
556
		perf_evlist__tty_browse_hists(session->evlist, rep, help);
557

558
	return ret;
559 560
}

561
static int
562
parse_callchain_opt(const struct option *opt, const char *arg, int unset)
563
{
564
	struct report *rep = (struct report *)opt->value;
565
	char *tok, *tok2;
566 567
	char *endptr;

568 569 570 571
	/*
	 * --no-call-graph
	 */
	if (unset) {
572
		rep->dont_use_callchains = true;
573 574 575
		return 0;
	}

576
	symbol_conf.use_callchain = true;
577 578 579 580

	if (!arg)
		return 0;

581 582 583 584 585 586
	tok = strtok((char *)arg, ",");
	if (!tok)
		return -1;

	/* get the output mode */
	if (!strncmp(tok, "graph", strlen(arg)))
587
		callchain_param.mode = CHAIN_GRAPH_ABS;
588

589
	else if (!strncmp(tok, "flat", strlen(arg)))
590 591 592 593 594
		callchain_param.mode = CHAIN_FLAT;

	else if (!strncmp(tok, "fractal", strlen(arg)))
		callchain_param.mode = CHAIN_GRAPH_REL;

595 596
	else if (!strncmp(tok, "none", strlen(arg))) {
		callchain_param.mode = CHAIN_NONE;
597
		symbol_conf.use_callchain = false;
598 599 600 601

		return 0;
	}

602 603 604
	else
		return -1;

605 606 607
	/* get the min percentage */
	tok = strtok(NULL, ",");
	if (!tok)
608
		goto setup;
609

610
	callchain_param.min_percent = strtod(tok, &endptr);
611 612 613
	if (tok == endptr)
		return -1;

614 615 616 617 618 619
	/* get the print limit */
	tok2 = strtok(NULL, ",");
	if (!tok2)
		goto setup;

	if (tok2[0] != 'c') {
620
		callchain_param.print_limit = strtoul(tok2, &endptr, 0);
621 622 623 624 625 626
		tok2 = strtok(NULL, ",");
		if (!tok2)
			goto setup;
	}

	/* get the call chain order */
627
	if (!strncmp(tok2, "caller", strlen("caller")))
628
		callchain_param.order = ORDER_CALLER;
629
	else if (!strncmp(tok2, "callee", strlen("callee")))
630 631 632
		callchain_param.order = ORDER_CALLEE;
	else
		return -1;
633 634 635 636 637 638 639 640 641 642 643

	/* Get the sort key */
	tok2 = strtok(NULL, ",");
	if (!tok2)
		goto setup;
	if (!strncmp(tok2, "function", strlen("function")))
		callchain_param.key = CCKEY_FUNCTION;
	else if (!strncmp(tok2, "address", strlen("address")))
		callchain_param.key = CCKEY_ADDRESS;
	else
		return -1;
644
setup:
645
	if (callchain_register_param(&callchain_param) < 0) {
646
		pr_err("Can't register callchain params\n");
647 648
		return -1;
	}
649 650 651
	return 0;
}

652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
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;
}

670
static int
671 672
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
673
{
674 675 676
	int *branch_mode = opt->value;

	*branch_mode = !unset;
677 678 679
	return 0;
}

680 681 682 683
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
684
	struct report *rep = opt->value;
685 686 687 688 689

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

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

818
	perf_config(report__config, &report);
819

820 821
	argc = parse_options(argc, argv, options, report_usage, 0);

822
	if (report.use_stdio)
823
		use_browser = 0;
824
	else if (report.use_tui)
825
		use_browser = 1;
826 827
	else if (report.use_gtk)
		use_browser = 2;
828

829
	if (report.inverted_callchain)
830 831
		callchain_param.order = ORDER_CALLER;

832
	if (!input_name || !strlen(input_name)) {
833
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
834
			input_name = "-";
835
		else
836
			input_name = "perf.data";
837
	}
838

839 840 841
	file.path  = input_name;
	file.force = report.force;

842
repeat:
843
	session = perf_session__new(&file, false, &report.tool);
844 845 846 847 848 849 850
	if (session == NULL)
		return -ENOMEM;

	report.session = session;

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

852 853
	if (branch_mode == -1 && has_br_stack)
		sort__mode = SORT_MODE__BRANCH;
854

855 856
	/* sort__mode could be NORMAL if --no-branch-stack */
	if (sort__mode == SORT_MODE__BRANCH) {
857
		/*
858 859
		 * if no sort_order is provided, then specify
		 * branch-mode specific order
860 861 862 863 864
		 */
		if (sort_order == default_sort_order)
			sort_order = "comm,dso_from,symbol_from,"
				     "dso_to,symbol_to";

865
	}
866
	if (report.mem_mode) {
867
		if (sort__mode == SORT_MODE__BRANCH) {
868
			pr_err("branch and mem mode incompatible\n");
869 870
			goto error;
		}
871 872
		sort__mode = SORT_MODE__MEMORY;

873 874 875 876 877 878 879
		/*
		 * 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";
	}
880

881 882 883 884
	if (setup_sorting() < 0) {
		parse_options_usage(report_usage, options, "s", 1);
		goto error;
	}
885

886 887 888 889 890
	if (parent_pattern != default_parent_pattern) {
		if (sort_dimension__add("parent") < 0)
			goto error;
	}

891 892 893 894
	/* Force tty output for header output. */
	if (report.header || report.header_only)
		use_browser = 0;

895 896 897 898 899 900 901
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
	else {
		use_browser = 0;
		perf_hpp__init();
	}

902 903 904 905 906 907 908 909 910 911
	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);
	}

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

938
	if (symbol__init() < 0)
939
		goto error;
940

941 942 943 944 945 946 947 948 949 950
	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];
	}
951

952
	sort__setup_elide(stdout);
953

954
	ret = __cmd_report(&report);
955 956 957 958 959 960
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

961 962 963
error:
	perf_session__delete(session);
	return ret;
964
}