cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

builtin-report.c (47921B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * builtin-report.c
      4 *
      5 * Builtin report command: Analyze the perf.data input file,
      6 * look up and read DSOs and symbol information and display
      7 * a histogram of results, along various sorting keys.
      8 */
      9#include "builtin.h"
     10
     11#include "util/config.h"
     12
     13#include "util/annotate.h"
     14#include "util/color.h"
     15#include "util/dso.h"
     16#include <linux/list.h>
     17#include <linux/rbtree.h>
     18#include <linux/err.h>
     19#include <linux/zalloc.h>
     20#include "util/map.h"
     21#include "util/symbol.h"
     22#include "util/map_symbol.h"
     23#include "util/mem-events.h"
     24#include "util/branch.h"
     25#include "util/callchain.h"
     26#include "util/values.h"
     27
     28#include "perf.h"
     29#include "util/debug.h"
     30#include "util/evlist.h"
     31#include "util/evsel.h"
     32#include "util/evswitch.h"
     33#include "util/header.h"
     34#include "util/session.h"
     35#include "util/srcline.h"
     36#include "util/tool.h"
     37
     38#include <subcmd/parse-options.h>
     39#include <subcmd/exec-cmd.h>
     40#include "util/parse-events.h"
     41
     42#include "util/thread.h"
     43#include "util/sort.h"
     44#include "util/hist.h"
     45#include "util/data.h"
     46#include "arch/common.h"
     47#include "util/time-utils.h"
     48#include "util/auxtrace.h"
     49#include "util/units.h"
     50#include "util/util.h" // perf_tip()
     51#include "ui/ui.h"
     52#include "ui/progress.h"
     53#include "util/block-info.h"
     54
     55#include <dlfcn.h>
     56#include <errno.h>
     57#include <inttypes.h>
     58#include <regex.h>
     59#include <linux/ctype.h>
     60#include <signal.h>
     61#include <linux/bitmap.h>
     62#include <linux/string.h>
     63#include <linux/stringify.h>
     64#include <linux/time64.h>
     65#include <sys/types.h>
     66#include <sys/stat.h>
     67#include <unistd.h>
     68#include <linux/mman.h>
     69
     70struct report {
     71	struct perf_tool	tool;
     72	struct perf_session	*session;
     73	struct evswitch		evswitch;
     74#ifdef HAVE_SLANG_SUPPORT
     75	bool			use_tui;
     76#endif
     77	bool			use_gtk;
     78	bool			use_stdio;
     79	bool			show_full_info;
     80	bool			show_threads;
     81	bool			inverted_callchain;
     82	bool			mem_mode;
     83	bool			stats_mode;
     84	bool			tasks_mode;
     85	bool			mmaps_mode;
     86	bool			header;
     87	bool			header_only;
     88	bool			nonany_branch_mode;
     89	bool			group_set;
     90	bool			stitch_lbr;
     91	bool			disable_order;
     92	bool			skip_empty;
     93	int			max_stack;
     94	struct perf_read_values	show_threads_values;
     95	struct annotation_options annotation_opts;
     96	const char		*pretty_printing_style;
     97	const char		*cpu_list;
     98	const char		*symbol_filter_str;
     99	const char		*time_str;
    100	struct perf_time_interval *ptime_range;
    101	int			range_size;
    102	int			range_num;
    103	float			min_percent;
    104	u64			nr_entries;
    105	u64			queue_size;
    106	u64			total_cycles;
    107	int			socket_filter;
    108	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
    109	struct branch_type_stat	brtype_stat;
    110	bool			symbol_ipc;
    111	bool			total_cycles_mode;
    112	struct block_report	*block_reports;
    113	int			nr_block_reports;
    114};
    115
    116static int report__config(const char *var, const char *value, void *cb)
    117{
    118	struct report *rep = cb;
    119
    120	if (!strcmp(var, "report.group")) {
    121		symbol_conf.event_group = perf_config_bool(var, value);
    122		return 0;
    123	}
    124	if (!strcmp(var, "report.percent-limit")) {
    125		double pcnt = strtof(value, NULL);
    126
    127		rep->min_percent = pcnt;
    128		callchain_param.min_percent = pcnt;
    129		return 0;
    130	}
    131	if (!strcmp(var, "report.children")) {
    132		symbol_conf.cumulate_callchain = perf_config_bool(var, value);
    133		return 0;
    134	}
    135	if (!strcmp(var, "report.queue-size"))
    136		return perf_config_u64(&rep->queue_size, var, value);
    137
    138	if (!strcmp(var, "report.sort_order")) {
    139		default_sort_order = strdup(value);
    140		return 0;
    141	}
    142
    143	if (!strcmp(var, "report.skip-empty")) {
    144		rep->skip_empty = perf_config_bool(var, value);
    145		return 0;
    146	}
    147
    148	return 0;
    149}
    150
    151static int hist_iter__report_callback(struct hist_entry_iter *iter,
    152				      struct addr_location *al, bool single,
    153				      void *arg)
    154{
    155	int err = 0;
    156	struct report *rep = arg;
    157	struct hist_entry *he = iter->he;
    158	struct evsel *evsel = iter->evsel;
    159	struct perf_sample *sample = iter->sample;
    160	struct mem_info *mi;
    161	struct branch_info *bi;
    162
    163	if (!ui__has_annotation() && !rep->symbol_ipc)
    164		return 0;
    165
    166	if (sort__mode == SORT_MODE__BRANCH) {
    167		bi = he->branch_info;
    168		err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
    169		if (err)
    170			goto out;
    171
    172		err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
    173
    174	} else if (rep->mem_mode) {
    175		mi = he->mem_info;
    176		err = addr_map_symbol__inc_samples(&mi->daddr, sample, evsel);
    177		if (err)
    178			goto out;
    179
    180		err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
    181
    182	} else if (symbol_conf.cumulate_callchain) {
    183		if (single)
    184			err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
    185	} else {
    186		err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
    187	}
    188
    189out:
    190	return err;
    191}
    192
    193static int hist_iter__branch_callback(struct hist_entry_iter *iter,
    194				      struct addr_location *al __maybe_unused,
    195				      bool single __maybe_unused,
    196				      void *arg)
    197{
    198	struct hist_entry *he = iter->he;
    199	struct report *rep = arg;
    200	struct branch_info *bi = he->branch_info;
    201	struct perf_sample *sample = iter->sample;
    202	struct evsel *evsel = iter->evsel;
    203	int err;
    204
    205	branch_type_count(&rep->brtype_stat, &bi->flags,
    206			  bi->from.addr, bi->to.addr);
    207
    208	if (!ui__has_annotation() && !rep->symbol_ipc)
    209		return 0;
    210
    211	err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
    212	if (err)
    213		goto out;
    214
    215	err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
    216
    217out:
    218	return err;
    219}
    220
    221static void setup_forced_leader(struct report *report,
    222				struct evlist *evlist)
    223{
    224	if (report->group_set)
    225		evlist__force_leader(evlist);
    226}
    227
    228static int process_feature_event(struct perf_session *session,
    229				 union perf_event *event)
    230{
    231	struct report *rep = container_of(session->tool, struct report, tool);
    232
    233	if (event->feat.feat_id < HEADER_LAST_FEATURE)
    234		return perf_event__process_feature(session, event);
    235
    236	if (event->feat.feat_id != HEADER_LAST_FEATURE) {
    237		pr_err("failed: wrong feature ID: %" PRI_lu64 "\n",
    238		       event->feat.feat_id);
    239		return -1;
    240	} else if (rep->header_only) {
    241		session_done = 1;
    242	}
    243
    244	/*
    245	 * (feat_id = HEADER_LAST_FEATURE) is the end marker which
    246	 * means all features are received, now we can force the
    247	 * group if needed.
    248	 */
    249	setup_forced_leader(rep, session->evlist);
    250	return 0;
    251}
    252
    253static int process_sample_event(struct perf_tool *tool,
    254				union perf_event *event,
    255				struct perf_sample *sample,
    256				struct evsel *evsel,
    257				struct machine *machine)
    258{
    259	struct report *rep = container_of(tool, struct report, tool);
    260	struct addr_location al;
    261	struct hist_entry_iter iter = {
    262		.evsel 			= evsel,
    263		.sample 		= sample,
    264		.hide_unresolved 	= symbol_conf.hide_unresolved,
    265		.add_entry_cb 		= hist_iter__report_callback,
    266	};
    267	int ret = 0;
    268
    269	if (perf_time__ranges_skip_sample(rep->ptime_range, rep->range_num,
    270					  sample->time)) {
    271		return 0;
    272	}
    273
    274	if (evswitch__discard(&rep->evswitch, evsel))
    275		return 0;
    276
    277	if (machine__resolve(machine, &al, sample) < 0) {
    278		pr_debug("problem processing %d event, skipping it.\n",
    279			 event->header.type);
    280		return -1;
    281	}
    282
    283	if (rep->stitch_lbr)
    284		al.thread->lbr_stitch_enable = true;
    285
    286	if (symbol_conf.hide_unresolved && al.sym == NULL)
    287		goto out_put;
    288
    289	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
    290		goto out_put;
    291
    292	if (sort__mode == SORT_MODE__BRANCH) {
    293		/*
    294		 * A non-synthesized event might not have a branch stack if
    295		 * branch stacks have been synthesized (using itrace options).
    296		 */
    297		if (!sample->branch_stack)
    298			goto out_put;
    299
    300		iter.add_entry_cb = hist_iter__branch_callback;
    301		iter.ops = &hist_iter_branch;
    302	} else if (rep->mem_mode) {
    303		iter.ops = &hist_iter_mem;
    304	} else if (symbol_conf.cumulate_callchain) {
    305		iter.ops = &hist_iter_cumulative;
    306	} else {
    307		iter.ops = &hist_iter_normal;
    308	}
    309
    310	if (al.map != NULL)
    311		al.map->dso->hit = 1;
    312
    313	if (ui__has_annotation() || rep->symbol_ipc || rep->total_cycles_mode) {
    314		hist__account_cycles(sample->branch_stack, &al, sample,
    315				     rep->nonany_branch_mode,
    316				     &rep->total_cycles);
    317	}
    318
    319	ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep);
    320	if (ret < 0)
    321		pr_debug("problem adding hist entry, skipping event\n");
    322out_put:
    323	addr_location__put(&al);
    324	return ret;
    325}
    326
    327static int process_read_event(struct perf_tool *tool,
    328			      union perf_event *event,
    329			      struct perf_sample *sample __maybe_unused,
    330			      struct evsel *evsel,
    331			      struct machine *machine __maybe_unused)
    332{
    333	struct report *rep = container_of(tool, struct report, tool);
    334
    335	if (rep->show_threads) {
    336		const char *name = evsel__name(evsel);
    337		int err = perf_read_values_add_value(&rep->show_threads_values,
    338					   event->read.pid, event->read.tid,
    339					   evsel->core.idx,
    340					   name,
    341					   event->read.value);
    342
    343		if (err)
    344			return err;
    345	}
    346
    347	return 0;
    348}
    349
    350/* For pipe mode, sample_type is not currently set */
    351static int report__setup_sample_type(struct report *rep)
    352{
    353	struct perf_session *session = rep->session;
    354	u64 sample_type = evlist__combined_sample_type(session->evlist);
    355	bool is_pipe = perf_data__is_pipe(session->data);
    356	struct evsel *evsel;
    357
    358	if (session->itrace_synth_opts->callchain ||
    359	    session->itrace_synth_opts->add_callchain ||
    360	    (!is_pipe &&
    361	     perf_header__has_feat(&session->header, HEADER_AUXTRACE) &&
    362	     !session->itrace_synth_opts->set))
    363		sample_type |= PERF_SAMPLE_CALLCHAIN;
    364
    365	if (session->itrace_synth_opts->last_branch ||
    366	    session->itrace_synth_opts->add_last_branch)
    367		sample_type |= PERF_SAMPLE_BRANCH_STACK;
    368
    369	if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
    370		if (perf_hpp_list.parent) {
    371			ui__error("Selected --sort parent, but no "
    372				    "callchain data. Did you call "
    373				    "'perf record' without -g?\n");
    374			return -EINVAL;
    375		}
    376		if (symbol_conf.use_callchain &&
    377			!symbol_conf.show_branchflag_count) {
    378			ui__error("Selected -g or --branch-history.\n"
    379				  "But no callchain or branch data.\n"
    380				  "Did you call 'perf record' without -g or -b?\n");
    381			return -1;
    382		}
    383	} else if (!callchain_param.enabled &&
    384		   callchain_param.mode != CHAIN_NONE &&
    385		   !symbol_conf.use_callchain) {
    386			symbol_conf.use_callchain = true;
    387			if (callchain_register_param(&callchain_param) < 0) {
    388				ui__error("Can't register callchain params.\n");
    389				return -EINVAL;
    390			}
    391	}
    392
    393	if (symbol_conf.cumulate_callchain) {
    394		/* Silently ignore if callchain is missing */
    395		if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
    396			symbol_conf.cumulate_callchain = false;
    397			perf_hpp__cancel_cumulate();
    398		}
    399	}
    400
    401	if (sort__mode == SORT_MODE__BRANCH) {
    402		if (!is_pipe &&
    403		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
    404			ui__error("Selected -b but no branch data. "
    405				  "Did you call perf record without -b?\n");
    406			return -1;
    407		}
    408	}
    409
    410	if (sort__mode == SORT_MODE__MEMORY) {
    411		/*
    412		 * FIXUP: prior to kernel 5.18, Arm SPE missed to set
    413		 * PERF_SAMPLE_DATA_SRC bit in sample type.  For backward
    414		 * compatibility, set the bit if it's an old perf data file.
    415		 */
    416		evlist__for_each_entry(session->evlist, evsel) {
    417			if (strstr(evsel->name, "arm_spe") &&
    418				!(sample_type & PERF_SAMPLE_DATA_SRC)) {
    419				evsel->core.attr.sample_type |= PERF_SAMPLE_DATA_SRC;
    420				sample_type |= PERF_SAMPLE_DATA_SRC;
    421			}
    422		}
    423
    424		if (!is_pipe && !(sample_type & PERF_SAMPLE_DATA_SRC)) {
    425			ui__error("Selected --mem-mode but no mem data. "
    426				  "Did you call perf record without -d?\n");
    427			return -1;
    428		}
    429	}
    430
    431	callchain_param_setup(sample_type, perf_env__arch(&rep->session->header.env));
    432
    433	if (rep->stitch_lbr && (callchain_param.record_mode != CALLCHAIN_LBR)) {
    434		ui__warning("Can't find LBR callchain. Switch off --stitch-lbr.\n"
    435			    "Please apply --call-graph lbr when recording.\n");
    436		rep->stitch_lbr = false;
    437	}
    438
    439	/* ??? handle more cases than just ANY? */
    440	if (!(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY))
    441		rep->nonany_branch_mode = true;
    442
    443#if !defined(HAVE_LIBUNWIND_SUPPORT) && !defined(HAVE_DWARF_SUPPORT)
    444	if (dwarf_callchain_users) {
    445		ui__warning("Please install libunwind or libdw "
    446			    "development packages during the perf build.\n");
    447	}
    448#endif
    449
    450	return 0;
    451}
    452
    453static void sig_handler(int sig __maybe_unused)
    454{
    455	session_done = 1;
    456}
    457
    458static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
    459					      const char *evname, FILE *fp)
    460{
    461	size_t ret;
    462	char unit;
    463	unsigned long nr_samples = hists->stats.nr_samples;
    464	u64 nr_events = hists->stats.total_period;
    465	struct evsel *evsel = hists_to_evsel(hists);
    466	char buf[512];
    467	size_t size = sizeof(buf);
    468	int socked_id = hists->socket_filter;
    469
    470	if (quiet)
    471		return 0;
    472
    473	if (symbol_conf.filter_relative) {
    474		nr_samples = hists->stats.nr_non_filtered_samples;
    475		nr_events = hists->stats.total_non_filtered_period;
    476	}
    477
    478	if (evsel__is_group_event(evsel)) {
    479		struct evsel *pos;
    480
    481		evsel__group_desc(evsel, buf, size);
    482		evname = buf;
    483
    484		for_each_group_member(pos, evsel) {
    485			const struct hists *pos_hists = evsel__hists(pos);
    486
    487			if (symbol_conf.filter_relative) {
    488				nr_samples += pos_hists->stats.nr_non_filtered_samples;
    489				nr_events += pos_hists->stats.total_non_filtered_period;
    490			} else {
    491				nr_samples += pos_hists->stats.nr_samples;
    492				nr_events += pos_hists->stats.total_period;
    493			}
    494		}
    495	}
    496
    497	nr_samples = convert_unit(nr_samples, &unit);
    498	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
    499	if (evname != NULL) {
    500		ret += fprintf(fp, " of event%s '%s'",
    501			       evsel->core.nr_members > 1 ? "s" : "", evname);
    502	}
    503
    504	if (rep->time_str)
    505		ret += fprintf(fp, " (time slices: %s)", rep->time_str);
    506
    507	if (symbol_conf.show_ref_callgraph && evname && strstr(evname, "call-graph=no")) {
    508		ret += fprintf(fp, ", show reference callgraph");
    509	}
    510
    511	if (rep->mem_mode) {
    512		ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
    513		ret += fprintf(fp, "\n# Sort order   : %s", sort_order ? : default_mem_sort_order);
    514	} else
    515		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
    516
    517	if (socked_id > -1)
    518		ret += fprintf(fp, "\n# Processor Socket: %d", socked_id);
    519
    520	return ret + fprintf(fp, "\n#\n");
    521}
    522
    523static int evlist__tui_block_hists_browse(struct evlist *evlist, struct report *rep)
    524{
    525	struct evsel *pos;
    526	int i = 0, ret;
    527
    528	evlist__for_each_entry(evlist, pos) {
    529		ret = report__browse_block_hists(&rep->block_reports[i++].hist,
    530						 rep->min_percent, pos,
    531						 &rep->session->header.env,
    532						 &rep->annotation_opts);
    533		if (ret != 0)
    534			return ret;
    535	}
    536
    537	return 0;
    538}
    539
    540static int evlist__tty_browse_hists(struct evlist *evlist, struct report *rep, const char *help)
    541{
    542	struct evsel *pos;
    543	int i = 0;
    544
    545	if (!quiet) {
    546		fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n",
    547			evlist->stats.total_lost_samples);
    548	}
    549
    550	evlist__for_each_entry(evlist, pos) {
    551		struct hists *hists = evsel__hists(pos);
    552		const char *evname = evsel__name(pos);
    553
    554		if (symbol_conf.event_group && !evsel__is_group_leader(pos))
    555			continue;
    556
    557		if (rep->skip_empty && !hists->stats.nr_samples)
    558			continue;
    559
    560		hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
    561
    562		if (rep->total_cycles_mode) {
    563			report__browse_block_hists(&rep->block_reports[i++].hist,
    564						   rep->min_percent, pos,
    565						   NULL, NULL);
    566			continue;
    567		}
    568
    569		hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout,
    570			       !(symbol_conf.use_callchain ||
    571			         symbol_conf.show_branchflag_count));
    572		fprintf(stdout, "\n\n");
    573	}
    574
    575	if (!quiet)
    576		fprintf(stdout, "#\n# (%s)\n#\n", help);
    577
    578	if (rep->show_threads) {
    579		bool style = !strcmp(rep->pretty_printing_style, "raw");
    580		perf_read_values_display(stdout, &rep->show_threads_values,
    581					 style);
    582		perf_read_values_destroy(&rep->show_threads_values);
    583	}
    584
    585	if (sort__mode == SORT_MODE__BRANCH)
    586		branch_type_stat_display(stdout, &rep->brtype_stat);
    587
    588	return 0;
    589}
    590
    591static void report__warn_kptr_restrict(const struct report *rep)
    592{
    593	struct map *kernel_map = machine__kernel_map(&rep->session->machines.host);
    594	struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
    595
    596	if (evlist__exclude_kernel(rep->session->evlist))
    597		return;
    598
    599	if (kernel_map == NULL ||
    600	    (kernel_map->dso->hit &&
    601	     (kernel_kmap->ref_reloc_sym == NULL ||
    602	      kernel_kmap->ref_reloc_sym->addr == 0))) {
    603		const char *desc =
    604		    "As no suitable kallsyms nor vmlinux was found, kernel samples\n"
    605		    "can't be resolved.";
    606
    607		if (kernel_map && map__has_symbols(kernel_map)) {
    608			desc = "If some relocation was applied (e.g. "
    609			       "kexec) symbols may be misresolved.";
    610		}
    611
    612		ui__warning(
    613"Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n"
    614"Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n"
    615"Samples in kernel modules can't be resolved as well.\n\n",
    616		desc);
    617	}
    618}
    619
    620static int report__gtk_browse_hists(struct report *rep, const char *help)
    621{
    622	int (*hist_browser)(struct evlist *evlist, const char *help,
    623			    struct hist_browser_timer *timer, float min_pcnt);
    624
    625	hist_browser = dlsym(perf_gtk_handle, "evlist__gtk_browse_hists");
    626
    627	if (hist_browser == NULL) {
    628		ui__error("GTK browser not found!\n");
    629		return -1;
    630	}
    631
    632	return hist_browser(rep->session->evlist, help, NULL, rep->min_percent);
    633}
    634
    635static int report__browse_hists(struct report *rep)
    636{
    637	int ret;
    638	struct perf_session *session = rep->session;
    639	struct evlist *evlist = session->evlist;
    640	char *help = NULL, *path = NULL;
    641
    642	path = system_path(TIPDIR);
    643	if (perf_tip(&help, path) || help == NULL) {
    644		/* fallback for people who don't install perf ;-) */
    645		free(path);
    646		path = system_path(DOCDIR);
    647		if (perf_tip(&help, path) || help == NULL)
    648			help = strdup("Cannot load tips.txt file, please install perf!");
    649	}
    650	free(path);
    651
    652	switch (use_browser) {
    653	case 1:
    654		if (rep->total_cycles_mode) {
    655			ret = evlist__tui_block_hists_browse(evlist, rep);
    656			break;
    657		}
    658
    659		ret = evlist__tui_browse_hists(evlist, help, NULL, rep->min_percent,
    660					       &session->header.env, true, &rep->annotation_opts);
    661		/*
    662		 * Usually "ret" is the last pressed key, and we only
    663		 * care if the key notifies us to switch data file.
    664		 */
    665		if (ret != K_SWITCH_INPUT_DATA && ret != K_RELOAD)
    666			ret = 0;
    667		break;
    668	case 2:
    669		ret = report__gtk_browse_hists(rep, help);
    670		break;
    671	default:
    672		ret = evlist__tty_browse_hists(evlist, rep, help);
    673		break;
    674	}
    675	free(help);
    676	return ret;
    677}
    678
    679static int report__collapse_hists(struct report *rep)
    680{
    681	struct ui_progress prog;
    682	struct evsel *pos;
    683	int ret = 0;
    684
    685	ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
    686
    687	evlist__for_each_entry(rep->session->evlist, pos) {
    688		struct hists *hists = evsel__hists(pos);
    689
    690		if (pos->core.idx == 0)
    691			hists->symbol_filter_str = rep->symbol_filter_str;
    692
    693		hists->socket_filter = rep->socket_filter;
    694
    695		ret = hists__collapse_resort(hists, &prog);
    696		if (ret < 0)
    697			break;
    698
    699		/* Non-group events are considered as leader */
    700		if (symbol_conf.event_group && !evsel__is_group_leader(pos)) {
    701			struct hists *leader_hists = evsel__hists(evsel__leader(pos));
    702
    703			hists__match(leader_hists, hists);
    704			hists__link(leader_hists, hists);
    705		}
    706	}
    707
    708	ui_progress__finish();
    709	return ret;
    710}
    711
    712static int hists__resort_cb(struct hist_entry *he, void *arg)
    713{
    714	struct report *rep = arg;
    715	struct symbol *sym = he->ms.sym;
    716
    717	if (rep->symbol_ipc && sym && !sym->annotate2) {
    718		struct evsel *evsel = hists_to_evsel(he->hists);
    719
    720		symbol__annotate2(&he->ms, evsel,
    721				  &annotation__default_options, NULL);
    722	}
    723
    724	return 0;
    725}
    726
    727static void report__output_resort(struct report *rep)
    728{
    729	struct ui_progress prog;
    730	struct evsel *pos;
    731
    732	ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
    733
    734	evlist__for_each_entry(rep->session->evlist, pos) {
    735		evsel__output_resort_cb(pos, &prog, hists__resort_cb, rep);
    736	}
    737
    738	ui_progress__finish();
    739}
    740
    741static int count_sample_event(struct perf_tool *tool __maybe_unused,
    742			      union perf_event *event __maybe_unused,
    743			      struct perf_sample *sample __maybe_unused,
    744			      struct evsel *evsel,
    745			      struct machine *machine __maybe_unused)
    746{
    747	struct hists *hists = evsel__hists(evsel);
    748
    749	hists__inc_nr_events(hists);
    750	return 0;
    751}
    752
    753static int process_attr(struct perf_tool *tool __maybe_unused,
    754			union perf_event *event,
    755			struct evlist **pevlist);
    756
    757static void stats_setup(struct report *rep)
    758{
    759	memset(&rep->tool, 0, sizeof(rep->tool));
    760	rep->tool.attr = process_attr;
    761	rep->tool.sample = count_sample_event;
    762	rep->tool.no_warn = true;
    763}
    764
    765static int stats_print(struct report *rep)
    766{
    767	struct perf_session *session = rep->session;
    768
    769	perf_session__fprintf_nr_events(session, stdout, rep->skip_empty);
    770	evlist__fprintf_nr_events(session->evlist, stdout, rep->skip_empty);
    771	return 0;
    772}
    773
    774static void tasks_setup(struct report *rep)
    775{
    776	memset(&rep->tool, 0, sizeof(rep->tool));
    777	rep->tool.ordered_events = true;
    778	if (rep->mmaps_mode) {
    779		rep->tool.mmap = perf_event__process_mmap;
    780		rep->tool.mmap2 = perf_event__process_mmap2;
    781	}
    782	rep->tool.attr = process_attr;
    783	rep->tool.comm = perf_event__process_comm;
    784	rep->tool.exit = perf_event__process_exit;
    785	rep->tool.fork = perf_event__process_fork;
    786	rep->tool.no_warn = true;
    787}
    788
    789struct task {
    790	struct thread		*thread;
    791	struct list_head	 list;
    792	struct list_head	 children;
    793};
    794
    795static struct task *tasks_list(struct task *task, struct machine *machine)
    796{
    797	struct thread *parent_thread, *thread = task->thread;
    798	struct task   *parent_task;
    799
    800	/* Already listed. */
    801	if (!list_empty(&task->list))
    802		return NULL;
    803
    804	/* Last one in the chain. */
    805	if (thread->ppid == -1)
    806		return task;
    807
    808	parent_thread = machine__find_thread(machine, -1, thread->ppid);
    809	if (!parent_thread)
    810		return ERR_PTR(-ENOENT);
    811
    812	parent_task = thread__priv(parent_thread);
    813	list_add_tail(&task->list, &parent_task->children);
    814	return tasks_list(parent_task, machine);
    815}
    816
    817static size_t maps__fprintf_task(struct maps *maps, int indent, FILE *fp)
    818{
    819	size_t printed = 0;
    820	struct map *map;
    821
    822	maps__for_each_entry(maps, map) {
    823		printed += fprintf(fp, "%*s  %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRIx64 " %" PRIu64 " %s\n",
    824				   indent, "", map->start, map->end,
    825				   map->prot & PROT_READ ? 'r' : '-',
    826				   map->prot & PROT_WRITE ? 'w' : '-',
    827				   map->prot & PROT_EXEC ? 'x' : '-',
    828				   map->flags & MAP_SHARED ? 's' : 'p',
    829				   map->pgoff,
    830				   map->dso->id.ino, map->dso->name);
    831	}
    832
    833	return printed;
    834}
    835
    836static void task__print_level(struct task *task, FILE *fp, int level)
    837{
    838	struct thread *thread = task->thread;
    839	struct task *child;
    840	int comm_indent = fprintf(fp, "  %8d %8d %8d |%*s",
    841				  thread->pid_, thread->tid, thread->ppid,
    842				  level, "");
    843
    844	fprintf(fp, "%s\n", thread__comm_str(thread));
    845
    846	maps__fprintf_task(thread->maps, comm_indent, fp);
    847
    848	if (!list_empty(&task->children)) {
    849		list_for_each_entry(child, &task->children, list)
    850			task__print_level(child, fp, level + 1);
    851	}
    852}
    853
    854static int tasks_print(struct report *rep, FILE *fp)
    855{
    856	struct perf_session *session = rep->session;
    857	struct machine      *machine = &session->machines.host;
    858	struct task *tasks, *task;
    859	unsigned int nr = 0, itask = 0, i;
    860	struct rb_node *nd;
    861	LIST_HEAD(list);
    862
    863	/*
    864	 * No locking needed while accessing machine->threads,
    865	 * because --tasks is single threaded command.
    866	 */
    867
    868	/* Count all the threads. */
    869	for (i = 0; i < THREADS__TABLE_SIZE; i++)
    870		nr += machine->threads[i].nr;
    871
    872	tasks = malloc(sizeof(*tasks) * nr);
    873	if (!tasks)
    874		return -ENOMEM;
    875
    876	for (i = 0; i < THREADS__TABLE_SIZE; i++) {
    877		struct threads *threads = &machine->threads[i];
    878
    879		for (nd = rb_first_cached(&threads->entries); nd;
    880		     nd = rb_next(nd)) {
    881			task = tasks + itask++;
    882
    883			task->thread = rb_entry(nd, struct thread, rb_node);
    884			INIT_LIST_HEAD(&task->children);
    885			INIT_LIST_HEAD(&task->list);
    886			thread__set_priv(task->thread, task);
    887		}
    888	}
    889
    890	/*
    891	 * Iterate every task down to the unprocessed parent
    892	 * and link all in task children list. Task with no
    893	 * parent is added into 'list'.
    894	 */
    895	for (itask = 0; itask < nr; itask++) {
    896		task = tasks + itask;
    897
    898		if (!list_empty(&task->list))
    899			continue;
    900
    901		task = tasks_list(task, machine);
    902		if (IS_ERR(task)) {
    903			pr_err("Error: failed to process tasks\n");
    904			free(tasks);
    905			return PTR_ERR(task);
    906		}
    907
    908		if (task)
    909			list_add_tail(&task->list, &list);
    910	}
    911
    912	fprintf(fp, "# %8s %8s %8s  %s\n", "pid", "tid", "ppid", "comm");
    913
    914	list_for_each_entry(task, &list, list)
    915		task__print_level(task, fp, 0);
    916
    917	free(tasks);
    918	return 0;
    919}
    920
    921static int __cmd_report(struct report *rep)
    922{
    923	int ret;
    924	struct perf_session *session = rep->session;
    925	struct evsel *pos;
    926	struct perf_data *data = session->data;
    927
    928	signal(SIGINT, sig_handler);
    929
    930	if (rep->cpu_list) {
    931		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
    932					       rep->cpu_bitmap);
    933		if (ret) {
    934			ui__error("failed to set cpu bitmap\n");
    935			return ret;
    936		}
    937		session->itrace_synth_opts->cpu_bitmap = rep->cpu_bitmap;
    938	}
    939
    940	if (rep->show_threads) {
    941		ret = perf_read_values_init(&rep->show_threads_values);
    942		if (ret)
    943			return ret;
    944	}
    945
    946	ret = report__setup_sample_type(rep);
    947	if (ret) {
    948		/* report__setup_sample_type() already showed error message */
    949		return ret;
    950	}
    951
    952	if (rep->stats_mode)
    953		stats_setup(rep);
    954
    955	if (rep->tasks_mode)
    956		tasks_setup(rep);
    957
    958	ret = perf_session__process_events(session);
    959	if (ret) {
    960		ui__error("failed to process sample\n");
    961		return ret;
    962	}
    963
    964	evlist__check_mem_load_aux(session->evlist);
    965
    966	if (rep->stats_mode)
    967		return stats_print(rep);
    968
    969	if (rep->tasks_mode)
    970		return tasks_print(rep, stdout);
    971
    972	report__warn_kptr_restrict(rep);
    973
    974	evlist__for_each_entry(session->evlist, pos)
    975		rep->nr_entries += evsel__hists(pos)->nr_entries;
    976
    977	if (use_browser == 0) {
    978		if (verbose > 3)
    979			perf_session__fprintf(session, stdout);
    980
    981		if (verbose > 2)
    982			perf_session__fprintf_dsos(session, stdout);
    983
    984		if (dump_trace) {
    985			perf_session__fprintf_nr_events(session, stdout,
    986							rep->skip_empty);
    987			evlist__fprintf_nr_events(session->evlist, stdout,
    988						  rep->skip_empty);
    989			return 0;
    990		}
    991	}
    992
    993	ret = report__collapse_hists(rep);
    994	if (ret) {
    995		ui__error("failed to process hist entry\n");
    996		return ret;
    997	}
    998
    999	if (session_done())
   1000		return 0;
   1001
   1002	/*
   1003	 * recalculate number of entries after collapsing since it
   1004	 * might be changed during the collapse phase.
   1005	 */
   1006	rep->nr_entries = 0;
   1007	evlist__for_each_entry(session->evlist, pos)
   1008		rep->nr_entries += evsel__hists(pos)->nr_entries;
   1009
   1010	if (rep->nr_entries == 0) {
   1011		ui__error("The %s data has no samples!\n", data->path);
   1012		return 0;
   1013	}
   1014
   1015	report__output_resort(rep);
   1016
   1017	if (rep->total_cycles_mode) {
   1018		int block_hpps[6] = {
   1019			PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT,
   1020			PERF_HPP_REPORT__BLOCK_LBR_CYCLES,
   1021			PERF_HPP_REPORT__BLOCK_CYCLES_PCT,
   1022			PERF_HPP_REPORT__BLOCK_AVG_CYCLES,
   1023			PERF_HPP_REPORT__BLOCK_RANGE,
   1024			PERF_HPP_REPORT__BLOCK_DSO,
   1025		};
   1026
   1027		rep->block_reports = block_info__create_report(session->evlist,
   1028							       rep->total_cycles,
   1029							       block_hpps, 6,
   1030							       &rep->nr_block_reports);
   1031		if (!rep->block_reports)
   1032			return -1;
   1033	}
   1034
   1035	return report__browse_hists(rep);
   1036}
   1037
   1038static int
   1039report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
   1040{
   1041	struct callchain_param *callchain = opt->value;
   1042
   1043	callchain->enabled = !unset;
   1044	/*
   1045	 * --no-call-graph
   1046	 */
   1047	if (unset) {
   1048		symbol_conf.use_callchain = false;
   1049		callchain->mode = CHAIN_NONE;
   1050		return 0;
   1051	}
   1052
   1053	return parse_callchain_report_opt(arg);
   1054}
   1055
   1056static int
   1057parse_time_quantum(const struct option *opt, const char *arg,
   1058		   int unset __maybe_unused)
   1059{
   1060	unsigned long *time_q = opt->value;
   1061	char *end;
   1062
   1063	*time_q = strtoul(arg, &end, 0);
   1064	if (end == arg)
   1065		goto parse_err;
   1066	if (*time_q == 0) {
   1067		pr_err("time quantum cannot be 0");
   1068		return -1;
   1069	}
   1070	end = skip_spaces(end);
   1071	if (*end == 0)
   1072		return 0;
   1073	if (!strcmp(end, "s")) {
   1074		*time_q *= NSEC_PER_SEC;
   1075		return 0;
   1076	}
   1077	if (!strcmp(end, "ms")) {
   1078		*time_q *= NSEC_PER_MSEC;
   1079		return 0;
   1080	}
   1081	if (!strcmp(end, "us")) {
   1082		*time_q *= NSEC_PER_USEC;
   1083		return 0;
   1084	}
   1085	if (!strcmp(end, "ns"))
   1086		return 0;
   1087parse_err:
   1088	pr_err("Cannot parse time quantum `%s'\n", arg);
   1089	return -1;
   1090}
   1091
   1092int
   1093report_parse_ignore_callees_opt(const struct option *opt __maybe_unused,
   1094				const char *arg, int unset __maybe_unused)
   1095{
   1096	if (arg) {
   1097		int err = regcomp(&ignore_callees_regex, arg, REG_EXTENDED);
   1098		if (err) {
   1099			char buf[BUFSIZ];
   1100			regerror(err, &ignore_callees_regex, buf, sizeof(buf));
   1101			pr_err("Invalid --ignore-callees regex: %s\n%s", arg, buf);
   1102			return -1;
   1103		}
   1104		have_ignore_callees = 1;
   1105	}
   1106
   1107	return 0;
   1108}
   1109
   1110static int
   1111parse_branch_mode(const struct option *opt,
   1112		  const char *str __maybe_unused, int unset)
   1113{
   1114	int *branch_mode = opt->value;
   1115
   1116	*branch_mode = !unset;
   1117	return 0;
   1118}
   1119
   1120static int
   1121parse_percent_limit(const struct option *opt, const char *str,
   1122		    int unset __maybe_unused)
   1123{
   1124	struct report *rep = opt->value;
   1125	double pcnt = strtof(str, NULL);
   1126
   1127	rep->min_percent = pcnt;
   1128	callchain_param.min_percent = pcnt;
   1129	return 0;
   1130}
   1131
   1132static int process_attr(struct perf_tool *tool __maybe_unused,
   1133			union perf_event *event,
   1134			struct evlist **pevlist)
   1135{
   1136	u64 sample_type;
   1137	int err;
   1138
   1139	err = perf_event__process_attr(tool, event, pevlist);
   1140	if (err)
   1141		return err;
   1142
   1143	/*
   1144	 * Check if we need to enable callchains based
   1145	 * on events sample_type.
   1146	 */
   1147	sample_type = evlist__combined_sample_type(*pevlist);
   1148	callchain_param_setup(sample_type, perf_env__arch((*pevlist)->env));
   1149	return 0;
   1150}
   1151
   1152int cmd_report(int argc, const char **argv)
   1153{
   1154	struct perf_session *session;
   1155	struct itrace_synth_opts itrace_synth_opts = { .set = 0, };
   1156	struct stat st;
   1157	bool has_br_stack = false;
   1158	int branch_mode = -1;
   1159	int last_key = 0;
   1160	bool branch_call_mode = false;
   1161#define CALLCHAIN_DEFAULT_OPT  "graph,0.5,caller,function,percent"
   1162	static const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
   1163						    CALLCHAIN_REPORT_HELP
   1164						    "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
   1165	char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
   1166	const char * const report_usage[] = {
   1167		"perf report [<options>]",
   1168		NULL
   1169	};
   1170	struct report report = {
   1171		.tool = {
   1172			.sample		 = process_sample_event,
   1173			.mmap		 = perf_event__process_mmap,
   1174			.mmap2		 = perf_event__process_mmap2,
   1175			.comm		 = perf_event__process_comm,
   1176			.namespaces	 = perf_event__process_namespaces,
   1177			.cgroup		 = perf_event__process_cgroup,
   1178			.exit		 = perf_event__process_exit,
   1179			.fork		 = perf_event__process_fork,
   1180			.lost		 = perf_event__process_lost,
   1181			.read		 = process_read_event,
   1182			.attr		 = process_attr,
   1183			.tracing_data	 = perf_event__process_tracing_data,
   1184			.build_id	 = perf_event__process_build_id,
   1185			.id_index	 = perf_event__process_id_index,
   1186			.auxtrace_info	 = perf_event__process_auxtrace_info,
   1187			.auxtrace	 = perf_event__process_auxtrace,
   1188			.event_update	 = perf_event__process_event_update,
   1189			.feature	 = process_feature_event,
   1190			.ordered_events	 = true,
   1191			.ordering_requires_timestamps = true,
   1192		},
   1193		.max_stack		 = PERF_MAX_STACK_DEPTH,
   1194		.pretty_printing_style	 = "normal",
   1195		.socket_filter		 = -1,
   1196		.annotation_opts	 = annotation__default_options,
   1197		.skip_empty		 = true,
   1198	};
   1199	char *sort_order_help = sort_help("sort by key(s):");
   1200	char *field_order_help = sort_help("output field(s): overhead period sample ");
   1201	const struct option options[] = {
   1202	OPT_STRING('i', "input", &input_name, "file",
   1203		    "input file name"),
   1204	OPT_INCR('v', "verbose", &verbose,
   1205		    "be more verbose (show symbol address, etc)"),
   1206	OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any message"),
   1207	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
   1208		    "dump raw trace in ASCII"),
   1209	OPT_BOOLEAN(0, "stats", &report.stats_mode, "Display event stats"),
   1210	OPT_BOOLEAN(0, "tasks", &report.tasks_mode, "Display recorded tasks"),
   1211	OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"),
   1212	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
   1213		   "file", "vmlinux pathname"),
   1214	OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
   1215                    "don't load vmlinux even if found"),
   1216	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
   1217		   "file", "kallsyms pathname"),
   1218	OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
   1219	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
   1220		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
   1221	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
   1222		    "Show a column with the number of samples"),
   1223	OPT_BOOLEAN('T', "threads", &report.show_threads,
   1224		    "Show per-thread event counters"),
   1225	OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
   1226		   "pretty printing style key: normal raw"),
   1227#ifdef HAVE_SLANG_SUPPORT
   1228	OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
   1229#endif
   1230	OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
   1231	OPT_BOOLEAN(0, "stdio", &report.use_stdio,
   1232		    "Use the stdio interface"),
   1233	OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
   1234	OPT_BOOLEAN(0, "header-only", &report.header_only,
   1235		    "Show only data header."),
   1236	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
   1237		   sort_order_help),
   1238	OPT_STRING('F', "fields", &field_order, "key[,keys...]",
   1239		   field_order_help),
   1240	OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization,
   1241		    "Show sample percentage for different cpu modes"),
   1242	OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
   1243		    "Show sample percentage for different cpu modes", PARSE_OPT_HIDDEN),
   1244	OPT_STRING('p', "parent", &parent_pattern, "regex",
   1245		   "regex filter to identify parent, see: '--sort parent'"),
   1246	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
   1247		    "Only display entries with parent-match"),
   1248	OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
   1249			     "print_type,threshold[,print_limit],order,sort_key[,branch],value",
   1250			     report_callchain_help, &report_parse_callchain_opt,
   1251			     callchain_default_opt),
   1252	OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
   1253		    "Accumulate callchains of children and show total overhead as well. "
   1254		    "Enabled by default, use --no-children to disable."),
   1255	OPT_INTEGER(0, "max-stack", &report.max_stack,
   1256		    "Set the maximum stack depth when parsing the callchain, "
   1257		    "anything beyond the specified depth will be ignored. "
   1258		    "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
   1259	OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
   1260		    "alias for inverted call graph"),
   1261	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
   1262		   "ignore callees of these functions in call graphs",
   1263		   report_parse_ignore_callees_opt),
   1264	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
   1265		   "only consider symbols in these dsos"),
   1266	OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
   1267		   "only consider symbols in these comms"),
   1268	OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
   1269		   "only consider symbols in these pids"),
   1270	OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
   1271		   "only consider symbols in these tids"),
   1272	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
   1273		   "only consider these symbols"),
   1274	OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
   1275		   "only show symbols that (partially) match with this filter"),
   1276	OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
   1277		   "width[,width...]",
   1278		   "don't try to adjust column width, use these fixed values"),
   1279	OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
   1280		   "separator for columns, no spaces will be added between "
   1281		   "columns '.' is reserved."),
   1282	OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved,
   1283		    "Only display entries resolved to a symbol"),
   1284	OPT_CALLBACK(0, "symfs", NULL, "directory",
   1285		     "Look for files with symbols relative to this directory",
   1286		     symbol__config_symfs),
   1287	OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
   1288		   "list of cpus to profile"),
   1289	OPT_BOOLEAN('I', "show-info", &report.show_full_info,
   1290		    "Display extended information about perf.data file"),
   1291	OPT_BOOLEAN(0, "source", &report.annotation_opts.annotate_src,
   1292		    "Interleave source code with assembly code (default)"),
   1293	OPT_BOOLEAN(0, "asm-raw", &report.annotation_opts.show_asm_raw,
   1294		    "Display raw encoding of assembly instructions (default)"),
   1295	OPT_STRING('M', "disassembler-style", &report.annotation_opts.disassembler_style, "disassembler style",
   1296		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
   1297	OPT_STRING(0, "prefix", &report.annotation_opts.prefix, "prefix",
   1298		    "Add prefix to source file path names in programs (with --prefix-strip)"),
   1299	OPT_STRING(0, "prefix-strip", &report.annotation_opts.prefix_strip, "N",
   1300		    "Strip first N entries of source file path name in programs (with --prefix)"),
   1301	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
   1302		    "Show a column with the sum of periods"),
   1303	OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &report.group_set,
   1304		    "Show event group information together"),
   1305	OPT_INTEGER(0, "group-sort-idx", &symbol_conf.group_sort_idx,
   1306		    "Sort the output by the event at the index n in group. "
   1307		    "If n is invalid, sort by the first event. "
   1308		    "WARNING: should be used on grouped events."),
   1309	OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
   1310		    "use branch records for per branch histogram filling",
   1311		    parse_branch_mode),
   1312	OPT_BOOLEAN(0, "branch-history", &branch_call_mode,
   1313		    "add last branch records to call history"),
   1314	OPT_STRING(0, "objdump", &report.annotation_opts.objdump_path, "path",
   1315		   "objdump binary to use for disassembly and annotations"),
   1316	OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
   1317		    "Disable symbol demangling"),
   1318	OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
   1319		    "Enable kernel symbol demangling"),
   1320	OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
   1321	OPT_INTEGER(0, "samples", &symbol_conf.res_sample,
   1322		    "Number of samples to save per histogram entry for individual browsing"),
   1323	OPT_CALLBACK(0, "percent-limit", &report, "percent",
   1324		     "Don't show entries under that percent", parse_percent_limit),
   1325	OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
   1326		     "how to display percentage of filtered entries", parse_filter_percentage),
   1327	OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
   1328			    "Instruction Tracing options\n" ITRACE_HELP,
   1329			    itrace_parse_synth_opts),
   1330	OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
   1331			"Show full source file name path for source lines"),
   1332	OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph,
   1333		    "Show callgraph from reference event"),
   1334	OPT_BOOLEAN(0, "stitch-lbr", &report.stitch_lbr,
   1335		    "Enable LBR callgraph stitching approach"),
   1336	OPT_INTEGER(0, "socket-filter", &report.socket_filter,
   1337		    "only show processor socket that match with this filter"),
   1338	OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
   1339		    "Show raw trace event output (do not use print fmt or plugins)"),
   1340	OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
   1341		    "Show entries in a hierarchy"),
   1342	OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
   1343			     "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
   1344			     stdio__config_color, "always"),
   1345	OPT_STRING(0, "time", &report.time_str, "str",
   1346		   "Time span of interest (start,stop)"),
   1347	OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
   1348		    "Show inline function"),
   1349	OPT_CALLBACK(0, "percent-type", &report.annotation_opts, "local-period",
   1350		     "Set percent type local/global-period/hits",
   1351		     annotate_parse_percent_type),
   1352	OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs, "Show times in nanosecs"),
   1353	OPT_CALLBACK(0, "time-quantum", &symbol_conf.time_quantum, "time (ms|us|ns|s)",
   1354		     "Set time quantum for time sort key (default 100ms)",
   1355		     parse_time_quantum),
   1356	OPTS_EVSWITCH(&report.evswitch),
   1357	OPT_BOOLEAN(0, "total-cycles", &report.total_cycles_mode,
   1358		    "Sort all blocks by 'Sampled Cycles%'"),
   1359	OPT_BOOLEAN(0, "disable-order", &report.disable_order,
   1360		    "Disable raw trace ordering"),
   1361	OPT_BOOLEAN(0, "skip-empty", &report.skip_empty,
   1362		    "Do not display empty (or dummy) events in the output"),
   1363	OPT_END()
   1364	};
   1365	struct perf_data data = {
   1366		.mode  = PERF_DATA_MODE_READ,
   1367	};
   1368	int ret = hists__init();
   1369	char sort_tmp[128];
   1370
   1371	if (ret < 0)
   1372		goto exit;
   1373
   1374	ret = perf_config(report__config, &report);
   1375	if (ret)
   1376		goto exit;
   1377
   1378	argc = parse_options(argc, argv, options, report_usage, 0);
   1379	if (argc) {
   1380		/*
   1381		 * Special case: if there's an argument left then assume that
   1382		 * it's a symbol filter:
   1383		 */
   1384		if (argc > 1)
   1385			usage_with_options(report_usage, options);
   1386
   1387		report.symbol_filter_str = argv[0];
   1388	}
   1389
   1390	if (annotate_check_args(&report.annotation_opts) < 0) {
   1391		ret = -EINVAL;
   1392		goto exit;
   1393	}
   1394
   1395	if (report.mmaps_mode)
   1396		report.tasks_mode = true;
   1397
   1398	if (dump_trace && report.disable_order)
   1399		report.tool.ordered_events = false;
   1400
   1401	if (quiet)
   1402		perf_quiet_option();
   1403
   1404	ret = symbol__validate_sym_arguments();
   1405	if (ret)
   1406		goto exit;
   1407
   1408	if (report.inverted_callchain)
   1409		callchain_param.order = ORDER_CALLER;
   1410	if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
   1411		callchain_param.order = ORDER_CALLER;
   1412
   1413	if ((itrace_synth_opts.callchain || itrace_synth_opts.add_callchain) &&
   1414	    (int)itrace_synth_opts.callchain_sz > report.max_stack)
   1415		report.max_stack = itrace_synth_opts.callchain_sz;
   1416
   1417	if (!input_name || !strlen(input_name)) {
   1418		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
   1419			input_name = "-";
   1420		else
   1421			input_name = "perf.data";
   1422	}
   1423
   1424	data.path  = input_name;
   1425	data.force = symbol_conf.force;
   1426
   1427repeat:
   1428	session = perf_session__new(&data, &report.tool);
   1429	if (IS_ERR(session)) {
   1430		ret = PTR_ERR(session);
   1431		goto exit;
   1432	}
   1433
   1434	ret = evswitch__init(&report.evswitch, session->evlist, stderr);
   1435	if (ret)
   1436		goto exit;
   1437
   1438	if (zstd_init(&(session->zstd_data), 0) < 0)
   1439		pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
   1440
   1441	if (report.queue_size) {
   1442		ordered_events__set_alloc_size(&session->ordered_events,
   1443					       report.queue_size);
   1444	}
   1445
   1446	session->itrace_synth_opts = &itrace_synth_opts;
   1447
   1448	report.session = session;
   1449
   1450	has_br_stack = perf_header__has_feat(&session->header,
   1451					     HEADER_BRANCH_STACK);
   1452	if (evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER)
   1453		has_br_stack = false;
   1454
   1455	setup_forced_leader(&report, session->evlist);
   1456
   1457	if (symbol_conf.group_sort_idx && !session->evlist->core.nr_groups) {
   1458		parse_options_usage(NULL, options, "group-sort-idx", 0);
   1459		ret = -EINVAL;
   1460		goto error;
   1461	}
   1462
   1463	if (itrace_synth_opts.last_branch || itrace_synth_opts.add_last_branch)
   1464		has_br_stack = true;
   1465
   1466	if (has_br_stack && branch_call_mode)
   1467		symbol_conf.show_branchflag_count = true;
   1468
   1469	memset(&report.brtype_stat, 0, sizeof(struct branch_type_stat));
   1470
   1471	/*
   1472	 * Branch mode is a tristate:
   1473	 * -1 means default, so decide based on the file having branch data.
   1474	 * 0/1 means the user chose a mode.
   1475	 */
   1476	if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
   1477	    !branch_call_mode) {
   1478		sort__mode = SORT_MODE__BRANCH;
   1479		symbol_conf.cumulate_callchain = false;
   1480	}
   1481	if (branch_call_mode) {
   1482		callchain_param.key = CCKEY_ADDRESS;
   1483		callchain_param.branch_callstack = true;
   1484		symbol_conf.use_callchain = true;
   1485		callchain_register_param(&callchain_param);
   1486		if (sort_order == NULL)
   1487			sort_order = "srcline,symbol,dso";
   1488	}
   1489
   1490	if (report.mem_mode) {
   1491		if (sort__mode == SORT_MODE__BRANCH) {
   1492			pr_err("branch and mem mode incompatible\n");
   1493			goto error;
   1494		}
   1495		sort__mode = SORT_MODE__MEMORY;
   1496		symbol_conf.cumulate_callchain = false;
   1497	}
   1498
   1499	if (symbol_conf.report_hierarchy) {
   1500		/* disable incompatible options */
   1501		symbol_conf.cumulate_callchain = false;
   1502
   1503		if (field_order) {
   1504			pr_err("Error: --hierarchy and --fields options cannot be used together\n");
   1505			parse_options_usage(report_usage, options, "F", 1);
   1506			parse_options_usage(NULL, options, "hierarchy", 0);
   1507			goto error;
   1508		}
   1509
   1510		perf_hpp_list.need_collapse = true;
   1511	}
   1512
   1513	if (report.use_stdio)
   1514		use_browser = 0;
   1515#ifdef HAVE_SLANG_SUPPORT
   1516	else if (report.use_tui)
   1517		use_browser = 1;
   1518#endif
   1519	else if (report.use_gtk)
   1520		use_browser = 2;
   1521
   1522	/* Force tty output for header output and per-thread stat. */
   1523	if (report.header || report.header_only || report.show_threads)
   1524		use_browser = 0;
   1525	if (report.header || report.header_only)
   1526		report.tool.show_feat_hdr = SHOW_FEAT_HEADER;
   1527	if (report.show_full_info)
   1528		report.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
   1529	if (report.stats_mode || report.tasks_mode)
   1530		use_browser = 0;
   1531	if (report.stats_mode && report.tasks_mode) {
   1532		pr_err("Error: --tasks and --mmaps can't be used together with --stats\n");
   1533		goto error;
   1534	}
   1535
   1536	if (report.total_cycles_mode) {
   1537		if (sort__mode != SORT_MODE__BRANCH)
   1538			report.total_cycles_mode = false;
   1539		else
   1540			sort_order = NULL;
   1541	}
   1542
   1543	if (strcmp(input_name, "-") != 0)
   1544		setup_browser(true);
   1545	else
   1546		use_browser = 0;
   1547
   1548	if (sort_order && strstr(sort_order, "ipc")) {
   1549		parse_options_usage(report_usage, options, "s", 1);
   1550		goto error;
   1551	}
   1552
   1553	if (sort_order && strstr(sort_order, "symbol")) {
   1554		if (sort__mode == SORT_MODE__BRANCH) {
   1555			snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s",
   1556				 sort_order, "ipc_lbr");
   1557			report.symbol_ipc = true;
   1558		} else {
   1559			snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s",
   1560				 sort_order, "ipc_null");
   1561		}
   1562
   1563		sort_order = sort_tmp;
   1564	}
   1565
   1566	if ((last_key != K_SWITCH_INPUT_DATA && last_key != K_RELOAD) &&
   1567	    (setup_sorting(session->evlist) < 0)) {
   1568		if (sort_order)
   1569			parse_options_usage(report_usage, options, "s", 1);
   1570		if (field_order)
   1571			parse_options_usage(sort_order ? NULL : report_usage,
   1572					    options, "F", 1);
   1573		goto error;
   1574	}
   1575
   1576	if ((report.header || report.header_only) && !quiet) {
   1577		perf_session__fprintf_info(session, stdout,
   1578					   report.show_full_info);
   1579		if (report.header_only) {
   1580			if (data.is_pipe) {
   1581				/*
   1582				 * we need to process first few records
   1583				 * which contains PERF_RECORD_HEADER_FEATURE.
   1584				 */
   1585				perf_session__process_events(session);
   1586			}
   1587			ret = 0;
   1588			goto error;
   1589		}
   1590	} else if (use_browser == 0 && !quiet &&
   1591		   !report.stats_mode && !report.tasks_mode) {
   1592		fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
   1593		      stdout);
   1594	}
   1595
   1596	/*
   1597	 * Only in the TUI browser we are doing integrated annotation,
   1598	 * so don't allocate extra space that won't be used in the stdio
   1599	 * implementation.
   1600	 */
   1601	if (ui__has_annotation() || report.symbol_ipc ||
   1602	    report.total_cycles_mode) {
   1603		ret = symbol__annotation_init();
   1604		if (ret < 0)
   1605			goto error;
   1606		/*
   1607 		 * For searching by name on the "Browse map details".
   1608 		 * providing it only in verbose mode not to bloat too
   1609 		 * much struct symbol.
   1610 		 */
   1611		if (verbose > 0) {
   1612			/*
   1613			 * XXX: Need to provide a less kludgy way to ask for
   1614			 * more space per symbol, the u32 is for the index on
   1615			 * the ui browser.
   1616			 * See symbol__browser_index.
   1617			 */
   1618			symbol_conf.priv_size += sizeof(u32);
   1619			symbol_conf.sort_by_name = true;
   1620		}
   1621		annotation_config__init(&report.annotation_opts);
   1622	}
   1623
   1624	if (symbol__init(&session->header.env) < 0)
   1625		goto error;
   1626
   1627	if (report.time_str) {
   1628		ret = perf_time__parse_for_ranges(report.time_str, session,
   1629						  &report.ptime_range,
   1630						  &report.range_size,
   1631						  &report.range_num);
   1632		if (ret < 0)
   1633			goto error;
   1634
   1635		itrace_synth_opts__set_time_range(&itrace_synth_opts,
   1636						  report.ptime_range,
   1637						  report.range_num);
   1638	}
   1639
   1640	if (session->tevent.pevent &&
   1641	    tep_set_function_resolver(session->tevent.pevent,
   1642				      machine__resolve_kernel_addr,
   1643				      &session->machines.host) < 0) {
   1644		pr_err("%s: failed to set libtraceevent function resolver\n",
   1645		       __func__);
   1646		return -1;
   1647	}
   1648
   1649	sort__setup_elide(stdout);
   1650
   1651	ret = __cmd_report(&report);
   1652	if (ret == K_SWITCH_INPUT_DATA || ret == K_RELOAD) {
   1653		perf_session__delete(session);
   1654		last_key = K_SWITCH_INPUT_DATA;
   1655		goto repeat;
   1656	} else
   1657		ret = 0;
   1658
   1659error:
   1660	if (report.ptime_range) {
   1661		itrace_synth_opts__clear_time_range(&itrace_synth_opts);
   1662		zfree(&report.ptime_range);
   1663	}
   1664
   1665	if (report.block_reports) {
   1666		block_info__free_report(report.block_reports,
   1667					report.nr_block_reports);
   1668		report.block_reports = NULL;
   1669	}
   1670
   1671	zstd_fini(&(session->zstd_data));
   1672	perf_session__delete(session);
   1673exit:
   1674	free(sort_order_help);
   1675	free(field_order_help);
   1676	return ret;
   1677}