builtin-report.c 26.4 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
	err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
	if (err)
		goto out;
116

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

	evsel->hists.stats.total_period += cost;
	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
124
	err = hist_entry__append_callchain(he, sample);
125 126 127 128
out:
	return err;
}

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

138 139
	if (err)
		return err;
140

141
	bi = sample__resolve_bstack(sample, al);
142 143 144 145 146 147
	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;
148 149 150

		err = -ENOMEM;

151 152 153 154
		/* 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;
155 156 157 158
		/*
		 * The report shows the percentage of total branches captured
		 * and not events sampled. Thus we use a pseudo period of 1.
		 */
159 160
		he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
					1, 1, 0);
161
		if (he) {
162
			bx = he->branch_info;
163
			err = addr_map_symbol__inc_samples(&bx->from, evsel->idx);
164 165 166
			if (err)
				goto out;

167
			err = addr_map_symbol__inc_samples(&bx->to, evsel->idx);
168 169 170
			if (err)
				goto out;

171 172 173
			evsel->hists.stats.total_period += 1;
			hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
		} else
174
			goto out;
175
	}
176
	err = 0;
177
out:
178
	free(bi);
179 180 181
	return err;
}

182
static int report__add_hist_entry(struct report *rep, struct perf_evsel *evsel,
183
				  struct addr_location *al, struct perf_sample *sample)
184
{
185
	struct symbol *parent = NULL;
186
	struct hist_entry *he;
187
	int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
188

189 190
	if (err)
		return err;
191

192 193 194
	he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
				sample->period, sample->weight,
				sample->transaction);
195
	if (he == NULL)
196 197
		return -ENOMEM;

198 199 200
	err = hist_entry__append_callchain(he, sample);
	if (err)
		goto out;
201

202
	err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
203 204
	evsel->hists.stats.total_period += sample->period;
	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
205
out:
206
	return err;
207 208
}

209

210
static int process_sample_event(struct perf_tool *tool,
211
				union perf_event *event,
212
				struct perf_sample *sample,
213
				struct perf_evsel *evsel,
214
				struct machine *machine)
215
{
216
	struct report *rep = container_of(tool, struct report, tool);
217
	struct addr_location al;
218
	int ret;
219

220
	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
221 222
		pr_debug("problem processing %d event, skipping it.\n",
			 event->header.type);
223 224
		return -1;
	}
225

226
	if (al.filtered || (rep->hide_unresolved && al.sym == NULL))
227
		return 0;
228

229
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
230 231
		return 0;

232
	if (sort__mode == SORT_MODE__BRANCH) {
233
		ret = report__add_branch_hist_entry(rep, &al, sample, evsel);
234
		if (ret < 0)
235
			pr_debug("problem adding lbr entry, skipping event\n");
236
	} else if (rep->mem_mode == 1) {
237
		ret = report__add_mem_hist_entry(rep, &al, sample, evsel);
238
		if (ret < 0)
239
			pr_debug("problem adding mem entry, skipping event\n");
240 241 242
	} else {
		if (al.map != NULL)
			al.map->dso->hit = 1;
243

244
		ret = report__add_hist_entry(rep, evsel, &al, sample);
245
		if (ret < 0)
246
			pr_debug("problem incrementing symbol period, skipping event\n");
247
	}
248
	return ret;
249
}
I
Ingo Molnar 已提交
250

251
static int process_read_event(struct perf_tool *tool,
252
			      union perf_event *event,
253
			      struct perf_sample *sample __maybe_unused,
254
			      struct perf_evsel *evsel,
255
			      struct machine *machine __maybe_unused)
256
{
257
	struct report *rep = container_of(tool, struct report, tool);
258

259
	if (rep->show_threads) {
260
		const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
261
		perf_read_values_add_value(&rep->show_threads_values,
262 263 264 265 266 267
					   event->read.pid, event->read.tid,
					   event->read.id,
					   name,
					   event->read.value);
	}

268
	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
269
		    evsel ? perf_evsel__name(evsel) : "FAIL",
270
		    event->read.value);
271 272 273 274

	return 0;
}

275
/* For pipe mode, sample_type is not currently set */
276
static int report__setup_sample_type(struct report *rep)
277
{
278 279 280
	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);
281

282
	if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
283
		if (sort__has_parent) {
284
			ui__error("Selected --sort parent, but no "
285 286
				    "callchain data. Did you call "
				    "'perf record' without -g?\n");
287
			return -EINVAL;
288
		}
289
		if (symbol_conf.use_callchain) {
290
			ui__error("Selected -g but no callchain data. Did "
291
				    "you call 'perf record' without -g?\n");
292
			return -1;
293
		}
294 295
	} else if (!rep->dont_use_callchains &&
		   callchain_param.mode != CHAIN_NONE &&
296
		   !symbol_conf.use_callchain) {
297
			symbol_conf.use_callchain = true;
298
			if (callchain_register_param(&callchain_param) < 0) {
299
				ui__error("Can't register callchain params.\n");
300
				return -EINVAL;
301
			}
302 303
	}

304
	if (sort__mode == SORT_MODE__BRANCH) {
305
		if (!is_pipe &&
306
		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
307 308
			ui__error("Selected -b but no branch data. "
				  "Did you call perf record without -b?\n");
309 310 311 312
			return -1;
		}
	}

313 314
	return 0;
}
315

316
static void sig_handler(int sig __maybe_unused)
317 318 319 320
{
	session_done = 1;
}

321
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
322 323 324 325
					      const char *evname, FILE *fp)
{
	size_t ret;
	char unit;
326 327 328
	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);
329 330 331
	char buf[512];
	size_t size = sizeof(buf);

332
	if (perf_evsel__is_group_event(evsel)) {
333 334 335 336 337 338 339 340 341 342
		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;
		}
	}
343

344 345
	nr_samples = convert_unit(nr_samples, &unit);
	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
346
	if (evname != NULL)
347 348
		ret += fprintf(fp, " of event '%s'", evname);

349 350 351 352 353
	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);
354 355 356
	return ret + fprintf(fp, "\n#\n");
}

357
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
358
					 struct report *rep,
359
					 const char *help)
360
{
361
	struct perf_evsel *pos;
362

363
	evlist__for_each(evlist, pos) {
364
		struct hists *hists = &pos->hists;
365
		const char *evname = perf_evsel__name(pos);
366

367 368 369 370
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

371
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
372
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
373 374 375 376 377 378 379
		fprintf(stdout, "\n\n");
	}

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

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

	return 0;
}

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
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);
	}
}

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 461 462 463 464
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;
}

465 466 467 468 469 470 471 472 473
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.
 	 */
474
	evlist__for_each(rep->session->evlist, pos)
475 476 477 478 479 480 481 482 483
		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;

484
	evlist__for_each(rep->session->evlist, pos) {
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
		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;
}

508
static int __cmd_report(struct report *rep)
509
{
510
	int ret;
511
	u64 nr_samples;
512
	struct perf_session *session = rep->session;
513
	struct perf_evsel *pos;
514
	struct perf_data_file *file = session->file;
515

516 517
	signal(SIGINT, sig_handler);

518 519 520
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
521
		if (ret)
522
			return ret;
523 524
	}

525 526
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
527

528
	ret = report__setup_sample_type(rep);
529
	if (ret)
530
		return ret;
531

532
	ret = perf_session__process_events(session, &rep->tool);
533
	if (ret)
534
		return ret;
535

536
	report__warn_kptr_restrict(rep);
537

538 539 540
	if (use_browser == 0) {
		if (verbose > 3)
			perf_session__fprintf(session, stdout);
541

542 543
		if (verbose > 2)
			perf_session__fprintf_dsos(session, stdout);
544

545 546 547 548
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
			return 0;
		}
549 550
	}

551
	nr_samples = report__collapse_hists(rep);
552

553 554 555
	if (session_done())
		return 0;

556
	if (nr_samples == 0) {
557
		ui__error("The %s file has no samples!\n", file->path);
558
		return 0;
559 560
	}

561
	evlist__for_each(session->evlist, pos)
562 563
		hists__output_resort(&pos->hists);

564
	return report__browse_hists(rep);
565 566
}

567
static int
568
parse_callchain_opt(const struct option *opt, const char *arg, int unset)
569
{
570
	struct report *rep = (struct report *)opt->value;
571
	char *tok, *tok2;
572 573
	char *endptr;

574 575 576 577
	/*
	 * --no-call-graph
	 */
	if (unset) {
578
		rep->dont_use_callchains = true;
579 580 581
		return 0;
	}

582
	symbol_conf.use_callchain = true;
583 584 585 586

	if (!arg)
		return 0;

587 588 589 590 591 592
	tok = strtok((char *)arg, ",");
	if (!tok)
		return -1;

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

595
	else if (!strncmp(tok, "flat", strlen(arg)))
596 597 598 599 600
		callchain_param.mode = CHAIN_FLAT;

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

601 602
	else if (!strncmp(tok, "none", strlen(arg))) {
		callchain_param.mode = CHAIN_NONE;
603
		symbol_conf.use_callchain = false;
604 605 606 607

		return 0;
	}

608 609 610
	else
		return -1;

611 612 613
	/* get the min percentage */
	tok = strtok(NULL, ",");
	if (!tok)
614
		goto setup;
615

616
	callchain_param.min_percent = strtod(tok, &endptr);
617 618 619
	if (tok == endptr)
		return -1;

620 621 622 623 624 625
	/* get the print limit */
	tok2 = strtok(NULL, ",");
	if (!tok2)
		goto setup;

	if (tok2[0] != 'c') {
626
		callchain_param.print_limit = strtoul(tok2, &endptr, 0);
627 628 629 630 631 632
		tok2 = strtok(NULL, ",");
		if (!tok2)
			goto setup;
	}

	/* get the call chain order */
633
	if (!strncmp(tok2, "caller", strlen("caller")))
634
		callchain_param.order = ORDER_CALLER;
635
	else if (!strncmp(tok2, "callee", strlen("callee")))
636 637 638
		callchain_param.order = ORDER_CALLEE;
	else
		return -1;
639 640 641 642 643 644 645 646 647 648 649

	/* 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;
650
setup:
651
	if (callchain_register_param(&callchain_param) < 0) {
652
		pr_err("Can't register callchain params\n");
653 654
		return -1;
	}
655 656 657
	return 0;
}

658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
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;
}

676
static int
677 678
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
679
{
680 681 682
	int *branch_mode = opt->value;

	*branch_mode = !unset;
683 684 685
	return 0;
}

686 687 688 689
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
690
	struct report *rep = opt->value;
691 692 693 694 695

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

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

824
	perf_config(report__config, &report);
825

826 827
	argc = parse_options(argc, argv, options, report_usage, 0);

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

835
	if (report.inverted_callchain)
836 837
		callchain_param.order = ORDER_CALLER;

838
	if (!input_name || !strlen(input_name)) {
839
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
840
			input_name = "-";
841
		else
842
			input_name = "perf.data";
843
	}
844

845 846 847
	file.path  = input_name;
	file.force = report.force;

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

	report.session = session;

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

858 859
	if (branch_mode == -1 && has_br_stack)
		sort__mode = SORT_MODE__BRANCH;
860

861 862
	/* sort__mode could be NORMAL if --no-branch-stack */
	if (sort__mode == SORT_MODE__BRANCH) {
863
		/*
864 865
		 * if no sort_order is provided, then specify
		 * branch-mode specific order
866 867 868 869 870
		 */
		if (sort_order == default_sort_order)
			sort_order = "comm,dso_from,symbol_from,"
				     "dso_to,symbol_to";

871
	}
872
	if (report.mem_mode) {
873
		if (sort__mode == SORT_MODE__BRANCH) {
874
			pr_err("branch and mem mode incompatible\n");
875 876
			goto error;
		}
877 878
		sort__mode = SORT_MODE__MEMORY;

879 880 881 882 883 884 885
		/*
		 * 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";
	}
886

887 888 889 890
	if (setup_sorting() < 0) {
		parse_options_usage(report_usage, options, "s", 1);
		goto error;
	}
891

892 893 894 895 896
	if (parent_pattern != default_parent_pattern) {
		if (sort_dimension__add("parent") < 0)
			goto error;
	}

897 898 899 900
	/* Force tty output for header output. */
	if (report.header || report.header_only)
		use_browser = 0;

901 902 903 904 905 906 907
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
	else {
		use_browser = 0;
		perf_hpp__init();
	}

908 909 910 911 912 913 914 915 916 917
	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);
	}

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

944
	if (symbol__init() < 0)
945
		goto error;
946

947 948 949 950 951 952 953 954 955 956
	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];
	}
957

958
	sort__setup_elide(stdout);
959

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

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