builtin-report.c 26.7 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 perf_tool *tool, struct addr_location *al,
79
				      struct perf_sample *sample, struct perf_evsel *evsel)
80
{
81
	struct report *rep = container_of(tool, struct report, tool);
82 83 84 85
	struct symbol *parent = NULL;
	struct hist_entry *he;
	struct mem_info *mi, *mx;
	uint64_t cost;
86
	int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
87

88 89
	if (err)
		return err;
90

91
	mi = sample__resolve_mem(sample, al);
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
	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.
	 */
109 110
	he = __hists__add_entry(&evsel->hists, al, parent, NULL, mi,
				cost, cost, 0);
111 112 113
	if (!he)
		return -ENOMEM;

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

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

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

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

140 141
	if (err)
		return err;
142

143
	bi = machine__resolve_bstack(al->machine, al->thread,
144 145 146 147 148 149 150
				     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;
151 152 153

		err = -ENOMEM;

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

170
			err = addr_map_symbol__inc_samples(&bx->to, evsel->idx);
171 172 173
			if (err)
				goto out;

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

185
static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel,
186
				  struct addr_location *al, struct perf_sample *sample)
187
{
188
	struct report *rep = container_of(tool, struct report, tool);
189
	struct symbol *parent = NULL;
190
	struct hist_entry *he;
191
	int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
192

193 194
	if (err)
		return err;
195

196 197 198
	he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
				sample->period, sample->weight,
				sample->transaction);
199
	if (he == NULL)
200 201
		return -ENOMEM;

202 203 204
	err = hist_entry__append_callchain(he, sample);
	if (err)
		goto out;
205

206
	err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
207 208
	evsel->hists.stats.total_period += sample->period;
	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
209
out:
210
	return err;
211 212
}

213

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

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

230
	if (al.filtered || (rep->hide_unresolved && al.sym == NULL))
231
		return 0;
232

233
	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
234 235
		return 0;

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

248
		ret = report__add_hist_entry(tool, evsel, &al, sample);
249
		if (ret < 0)
250
			pr_debug("problem incrementing symbol period, skipping event\n");
251
	}
252
	return ret;
253
}
I
Ingo Molnar 已提交
254

255
static int process_read_event(struct perf_tool *tool,
256
			      union perf_event *event,
257
			      struct perf_sample *sample __maybe_unused,
258
			      struct perf_evsel *evsel,
259
			      struct machine *machine __maybe_unused)
260
{
261
	struct report *rep = container_of(tool, struct report, tool);
262

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

272
	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
273
		    evsel ? perf_evsel__name(evsel) : "FAIL",
274
		    event->read.value);
275 276 277 278

	return 0;
}

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

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

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

317 318
	return 0;
}
319

320
static void sig_handler(int sig __maybe_unused)
321 322 323 324
{
	session_done = 1;
}

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

336
	if (perf_evsel__is_group_event(evsel)) {
337 338 339 340 341 342 343 344 345 346
		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;
		}
	}
347

348 349
	nr_samples = convert_unit(nr_samples, &unit);
	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
350
	if (evname != NULL)
351 352
		ret += fprintf(fp, " of event '%s'", evname);

353 354 355 356 357
	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);
358 359 360
	return ret + fprintf(fp, "\n#\n");
}

361
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
362
					 struct report *rep,
363
					 const char *help)
364
{
365
	struct perf_evsel *pos;
366

367
	evlist__for_each(evlist, pos) {
368
		struct hists *hists = &pos->hists;
369
		const char *evname = perf_evsel__name(pos);
370

371 372 373 374
		if (symbol_conf.event_group &&
		    !perf_evsel__is_group_leader(pos))
			continue;

375
		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
376
		hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
377 378 379 380 381 382 383
		fprintf(stdout, "\n\n");
	}

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

384 385 386
		if (rep->show_threads) {
			bool style = !strcmp(rep->pretty_printing_style, "raw");
			perf_read_values_display(stdout, &rep->show_threads_values,
387
						 style);
388
			perf_read_values_destroy(&rep->show_threads_values);
389 390 391 392 393 394
		}
	}

	return 0;
}

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

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 465 466 467 468
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;
}

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

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

512
static int __cmd_report(struct report *rep)
513
{
514
	int ret;
515
	u64 nr_samples;
516
	struct perf_session *session = rep->session;
517
	struct perf_evsel *pos;
518
	struct perf_data_file *file = session->file;
519

520 521
	signal(SIGINT, sig_handler);

522 523 524
	if (rep->cpu_list) {
		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
					       rep->cpu_bitmap);
525
		if (ret)
526
			return ret;
527 528
	}

529 530
	if (rep->show_threads)
		perf_read_values_init(&rep->show_threads_values);
531

532
	ret = report__setup_sample_type(rep);
533
	if (ret)
534
		return ret;
535

536
	ret = perf_session__process_events(session, &rep->tool);
537
	if (ret)
538
		return ret;
539

540
	report__warn_kptr_restrict(rep);
541

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 551 552
		if (dump_trace) {
			perf_session__fprintf_nr_events(session, stdout);
			return 0;
		}
553 554
	}

555
	nr_samples = report__collapse_hists(rep);
556

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

560
	if (nr_samples == 0) {
561
		ui__error("The %s file has no samples!\n", file->path);
562
		return 0;
563 564
	}

565
	evlist__for_each(session->evlist, pos)
566 567
		hists__output_resort(&pos->hists);

568
	return report__browse_hists(rep);
569 570
}

571
static int
572
parse_callchain_opt(const struct option *opt, const char *arg, int unset)
573
{
574
	struct report *rep = (struct report *)opt->value;
575
	char *tok, *tok2;
576 577
	char *endptr;

578 579 580 581
	/*
	 * --no-call-graph
	 */
	if (unset) {
582
		rep->dont_use_callchains = true;
583 584 585
		return 0;
	}

586
	symbol_conf.use_callchain = true;
587 588 589 590

	if (!arg)
		return 0;

591 592 593 594 595 596
	tok = strtok((char *)arg, ",");
	if (!tok)
		return -1;

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

599
	else if (!strncmp(tok, "flat", strlen(arg)))
600 601 602 603 604
		callchain_param.mode = CHAIN_FLAT;

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

605 606
	else if (!strncmp(tok, "none", strlen(arg))) {
		callchain_param.mode = CHAIN_NONE;
607
		symbol_conf.use_callchain = false;
608 609 610 611

		return 0;
	}

612 613 614
	else
		return -1;

615 616 617
	/* get the min percentage */
	tok = strtok(NULL, ",");
	if (!tok)
618
		goto setup;
619

620
	callchain_param.min_percent = strtod(tok, &endptr);
621 622 623
	if (tok == endptr)
		return -1;

624 625 626 627 628 629
	/* get the print limit */
	tok2 = strtok(NULL, ",");
	if (!tok2)
		goto setup;

	if (tok2[0] != 'c') {
630
		callchain_param.print_limit = strtoul(tok2, &endptr, 0);
631 632 633 634 635 636
		tok2 = strtok(NULL, ",");
		if (!tok2)
			goto setup;
	}

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

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

662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
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;
}

680
static int
681 682
parse_branch_mode(const struct option *opt __maybe_unused,
		  const char *str __maybe_unused, int unset)
683
{
684 685 686
	int *branch_mode = opt->value;

	*branch_mode = !unset;
687 688 689
	return 0;
}

690 691 692 693
static int
parse_percent_limit(const struct option *opt, const char *str,
		    int unset __maybe_unused)
{
694
	struct report *rep = opt->value;
695 696 697 698 699

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

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

828
	perf_config(report__config, &report);
829

830 831
	argc = parse_options(argc, argv, options, report_usage, 0);

832
	if (report.use_stdio)
833
		use_browser = 0;
834
	else if (report.use_tui)
835
		use_browser = 1;
836 837
	else if (report.use_gtk)
		use_browser = 2;
838

839
	if (report.inverted_callchain)
840 841
		callchain_param.order = ORDER_CALLER;

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 850 851
	file.path  = input_name;
	file.force = report.force;

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

	report.session = session;

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

862 863
	if (branch_mode == -1 && has_br_stack)
		sort__mode = SORT_MODE__BRANCH;
864

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

875
	}
876
	if (report.mem_mode) {
877
		if (sort__mode == SORT_MODE__BRANCH) {
878
			pr_err("branch and mem mode incompatible\n");
879 880
			goto error;
		}
881 882
		sort__mode = SORT_MODE__MEMORY;

883 884 885 886 887 888 889
		/*
		 * 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";
	}
890

891 892 893 894
	if (setup_sorting() < 0) {
		parse_options_usage(report_usage, options, "s", 1);
		goto error;
	}
895

896 897 898 899 900
	if (parent_pattern != default_parent_pattern) {
		if (sort_dimension__add("parent") < 0)
			goto error;
	}

901 902 903 904
	/* Force tty output for header output. */
	if (report.header || report.header_only)
		use_browser = 0;

905 906 907 908 909 910 911
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
	else {
		use_browser = 0;
		perf_hpp__init();
	}

912 913 914 915 916 917 918 919 920 921
	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);
	}

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

948
	if (symbol__init() < 0)
949
		goto error;
950

951 952 953 954 955 956 957 958 959 960
	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];
	}
961

962
	sort__setup_elide(stdout);
963

964
	ret = __cmd_report(&report);
965 966 967 968 969 970
	if (ret == K_SWITCH_INPUT_DATA) {
		perf_session__delete(session);
		goto repeat;
	} else
		ret = 0;

971 972 973
error:
	perf_session__delete(session);
	return ret;
974
}