brintos

brintos / linux-shallow public Read only

0
0
Text · 72.3 KiB · dbaf07b Raw
2675 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <errno.h>3#include <signal.h>4#include <inttypes.h>5#include <linux/err.h>6#include <linux/kernel.h>7#include <linux/zalloc.h>8#include <api/fs/fs.h>9 10#include <byteswap.h>11#include <unistd.h>12#include <sys/types.h>13#include <sys/mman.h>14#include <perf/cpumap.h>15 16#include "map_symbol.h"17#include "branch.h"18#include "debug.h"19#include "env.h"20#include "evlist.h"21#include "evsel.h"22#include "memswap.h"23#include "map.h"24#include "symbol.h"25#include "session.h"26#include "tool.h"27#include "perf_regs.h"28#include "asm/bug.h"29#include "auxtrace.h"30#include "thread.h"31#include "thread-stack.h"32#include "sample-raw.h"33#include "stat.h"34#include "tsc.h"35#include "ui/progress.h"36#include "util.h"37#include "arch/common.h"38#include "units.h"39#include "annotate.h"40#include <internal/lib.h>41 42static int perf_session__deliver_event(struct perf_session *session,43				       union perf_event *event,44				       const struct perf_tool *tool,45				       u64 file_offset,46				       const char *file_path);47 48static int perf_session__open(struct perf_session *session)49{50	struct perf_data *data = session->data;51 52	if (perf_session__read_header(session) < 0) {53		pr_err("incompatible file format (rerun with -v to learn more)\n");54		return -1;55	}56 57	if (perf_header__has_feat(&session->header, HEADER_AUXTRACE)) {58		/* Auxiliary events may reference exited threads, hold onto dead ones. */59		symbol_conf.keep_exited_threads = true;60	}61 62	if (perf_data__is_pipe(data))63		return 0;64 65	if (perf_header__has_feat(&session->header, HEADER_STAT))66		return 0;67 68	if (!evlist__valid_sample_type(session->evlist)) {69		pr_err("non matching sample_type\n");70		return -1;71	}72 73	if (!evlist__valid_sample_id_all(session->evlist)) {74		pr_err("non matching sample_id_all\n");75		return -1;76	}77 78	if (!evlist__valid_read_format(session->evlist)) {79		pr_err("non matching read_format\n");80		return -1;81	}82 83	return 0;84}85 86void perf_session__set_id_hdr_size(struct perf_session *session)87{88	u16 id_hdr_size = evlist__id_hdr_size(session->evlist);89 90	machines__set_id_hdr_size(&session->machines, id_hdr_size);91}92 93int perf_session__create_kernel_maps(struct perf_session *session)94{95	int ret = machine__create_kernel_maps(&session->machines.host);96 97	if (ret >= 0)98		ret = machines__create_guest_kernel_maps(&session->machines);99	return ret;100}101 102static void perf_session__destroy_kernel_maps(struct perf_session *session)103{104	machines__destroy_kernel_maps(&session->machines);105}106 107static bool perf_session__has_comm_exec(struct perf_session *session)108{109	struct evsel *evsel;110 111	evlist__for_each_entry(session->evlist, evsel) {112		if (evsel->core.attr.comm_exec)113			return true;114	}115 116	return false;117}118 119static void perf_session__set_comm_exec(struct perf_session *session)120{121	bool comm_exec = perf_session__has_comm_exec(session);122 123	machines__set_comm_exec(&session->machines, comm_exec);124}125 126static int ordered_events__deliver_event(struct ordered_events *oe,127					 struct ordered_event *event)128{129	struct perf_session *session = container_of(oe, struct perf_session,130						    ordered_events);131 132	return perf_session__deliver_event(session, event->event,133					   session->tool, event->file_offset,134					   event->file_path);135}136 137struct perf_session *__perf_session__new(struct perf_data *data,138					 struct perf_tool *tool,139					 bool trace_event_repipe)140{141	int ret = -ENOMEM;142	struct perf_session *session = zalloc(sizeof(*session));143 144	if (!session)145		goto out;146 147	session->trace_event_repipe = trace_event_repipe;148	session->tool   = tool;149	session->decomp_data.zstd_decomp = &session->zstd_data;150	session->active_decomp = &session->decomp_data;151	INIT_LIST_HEAD(&session->auxtrace_index);152	machines__init(&session->machines);153	ordered_events__init(&session->ordered_events,154			     ordered_events__deliver_event, NULL);155 156	perf_env__init(&session->header.env);157	if (data) {158		ret = perf_data__open(data);159		if (ret < 0)160			goto out_delete;161 162		session->data = data;163 164		if (perf_data__is_read(data)) {165			ret = perf_session__open(session);166			if (ret < 0)167				goto out_delete;168 169			/*170			 * set session attributes that are present in perf.data171			 * but not in pipe-mode.172			 */173			if (!data->is_pipe) {174				perf_session__set_id_hdr_size(session);175				perf_session__set_comm_exec(session);176			}177 178			evlist__init_trace_event_sample_raw(session->evlist);179 180			/* Open the directory data. */181			if (data->is_dir) {182				ret = perf_data__open_dir(data);183				if (ret)184					goto out_delete;185			}186 187			if (!symbol_conf.kallsyms_name &&188			    !symbol_conf.vmlinux_name)189				symbol_conf.kallsyms_name = perf_data__kallsyms_name(data);190		}191	} else  {192		session->machines.host.env = &perf_env;193	}194 195	session->machines.host.single_address_space =196		perf_env__single_address_space(session->machines.host.env);197 198	if (!data || perf_data__is_write(data)) {199		/*200		 * In O_RDONLY mode this will be performed when reading the201		 * kernel MMAP event, in perf_event__process_mmap().202		 */203		if (perf_session__create_kernel_maps(session) < 0)204			pr_warning("Cannot read kernel map\n");205	}206 207	/*208	 * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is209	 * processed, so evlist__sample_id_all is not meaningful here.210	 */211	if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps &&212	    tool->ordered_events && !evlist__sample_id_all(session->evlist)) {213		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");214		tool->ordered_events = false;215	}216 217	return session;218 219 out_delete:220	perf_session__delete(session);221 out:222	return ERR_PTR(ret);223}224 225static void perf_decomp__release_events(struct decomp *next)226{227	struct decomp *decomp;228	size_t mmap_len;229 230	do {231		decomp = next;232		if (decomp == NULL)233			break;234		next = decomp->next;235		mmap_len = decomp->mmap_len;236		munmap(decomp, mmap_len);237	} while (1);238}239 240void perf_session__delete(struct perf_session *session)241{242	if (session == NULL)243		return;244	auxtrace__free(session);245	auxtrace_index__free(&session->auxtrace_index);246	debuginfo_cache__delete();247	perf_session__destroy_kernel_maps(session);248	perf_decomp__release_events(session->decomp_data.decomp);249	perf_env__exit(&session->header.env);250	machines__exit(&session->machines);251	if (session->data) {252		if (perf_data__is_read(session->data))253			evlist__delete(session->evlist);254		perf_data__close(session->data);255	}256#ifdef HAVE_LIBTRACEEVENT257	trace_event__cleanup(&session->tevent);258#endif259	free(session);260}261 262static void swap_sample_id_all(union perf_event *event, void *data)263{264	void *end = (void *) event + event->header.size;265	int size = end - data;266 267	BUG_ON(size % sizeof(u64));268	mem_bswap_64(data, size);269}270 271static void perf_event__all64_swap(union perf_event *event,272				   bool sample_id_all __maybe_unused)273{274	struct perf_event_header *hdr = &event->header;275	mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr));276}277 278static void perf_event__comm_swap(union perf_event *event, bool sample_id_all)279{280	event->comm.pid = bswap_32(event->comm.pid);281	event->comm.tid = bswap_32(event->comm.tid);282 283	if (sample_id_all) {284		void *data = &event->comm.comm;285 286		data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));287		swap_sample_id_all(event, data);288	}289}290 291static void perf_event__mmap_swap(union perf_event *event,292				  bool sample_id_all)293{294	event->mmap.pid	  = bswap_32(event->mmap.pid);295	event->mmap.tid	  = bswap_32(event->mmap.tid);296	event->mmap.start = bswap_64(event->mmap.start);297	event->mmap.len	  = bswap_64(event->mmap.len);298	event->mmap.pgoff = bswap_64(event->mmap.pgoff);299 300	if (sample_id_all) {301		void *data = &event->mmap.filename;302 303		data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));304		swap_sample_id_all(event, data);305	}306}307 308static void perf_event__mmap2_swap(union perf_event *event,309				  bool sample_id_all)310{311	event->mmap2.pid   = bswap_32(event->mmap2.pid);312	event->mmap2.tid   = bswap_32(event->mmap2.tid);313	event->mmap2.start = bswap_64(event->mmap2.start);314	event->mmap2.len   = bswap_64(event->mmap2.len);315	event->mmap2.pgoff = bswap_64(event->mmap2.pgoff);316 317	if (!(event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) {318		event->mmap2.maj   = bswap_32(event->mmap2.maj);319		event->mmap2.min   = bswap_32(event->mmap2.min);320		event->mmap2.ino   = bswap_64(event->mmap2.ino);321		event->mmap2.ino_generation = bswap_64(event->mmap2.ino_generation);322	}323 324	if (sample_id_all) {325		void *data = &event->mmap2.filename;326 327		data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));328		swap_sample_id_all(event, data);329	}330}331static void perf_event__task_swap(union perf_event *event, bool sample_id_all)332{333	event->fork.pid	 = bswap_32(event->fork.pid);334	event->fork.tid	 = bswap_32(event->fork.tid);335	event->fork.ppid = bswap_32(event->fork.ppid);336	event->fork.ptid = bswap_32(event->fork.ptid);337	event->fork.time = bswap_64(event->fork.time);338 339	if (sample_id_all)340		swap_sample_id_all(event, &event->fork + 1);341}342 343static void perf_event__read_swap(union perf_event *event, bool sample_id_all)344{345	event->read.pid		 = bswap_32(event->read.pid);346	event->read.tid		 = bswap_32(event->read.tid);347	event->read.value	 = bswap_64(event->read.value);348	event->read.time_enabled = bswap_64(event->read.time_enabled);349	event->read.time_running = bswap_64(event->read.time_running);350	event->read.id		 = bswap_64(event->read.id);351 352	if (sample_id_all)353		swap_sample_id_all(event, &event->read + 1);354}355 356static void perf_event__aux_swap(union perf_event *event, bool sample_id_all)357{358	event->aux.aux_offset = bswap_64(event->aux.aux_offset);359	event->aux.aux_size   = bswap_64(event->aux.aux_size);360	event->aux.flags      = bswap_64(event->aux.flags);361 362	if (sample_id_all)363		swap_sample_id_all(event, &event->aux + 1);364}365 366static void perf_event__itrace_start_swap(union perf_event *event,367					  bool sample_id_all)368{369	event->itrace_start.pid	 = bswap_32(event->itrace_start.pid);370	event->itrace_start.tid	 = bswap_32(event->itrace_start.tid);371 372	if (sample_id_all)373		swap_sample_id_all(event, &event->itrace_start + 1);374}375 376static void perf_event__switch_swap(union perf_event *event, bool sample_id_all)377{378	if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) {379		event->context_switch.next_prev_pid =380				bswap_32(event->context_switch.next_prev_pid);381		event->context_switch.next_prev_tid =382				bswap_32(event->context_switch.next_prev_tid);383	}384 385	if (sample_id_all)386		swap_sample_id_all(event, &event->context_switch + 1);387}388 389static void perf_event__text_poke_swap(union perf_event *event, bool sample_id_all)390{391	event->text_poke.addr    = bswap_64(event->text_poke.addr);392	event->text_poke.old_len = bswap_16(event->text_poke.old_len);393	event->text_poke.new_len = bswap_16(event->text_poke.new_len);394 395	if (sample_id_all) {396		size_t len = sizeof(event->text_poke.old_len) +397			     sizeof(event->text_poke.new_len) +398			     event->text_poke.old_len +399			     event->text_poke.new_len;400		void *data = &event->text_poke.old_len;401 402		data += PERF_ALIGN(len, sizeof(u64));403		swap_sample_id_all(event, data);404	}405}406 407static void perf_event__throttle_swap(union perf_event *event,408				      bool sample_id_all)409{410	event->throttle.time	  = bswap_64(event->throttle.time);411	event->throttle.id	  = bswap_64(event->throttle.id);412	event->throttle.stream_id = bswap_64(event->throttle.stream_id);413 414	if (sample_id_all)415		swap_sample_id_all(event, &event->throttle + 1);416}417 418static void perf_event__namespaces_swap(union perf_event *event,419					bool sample_id_all)420{421	u64 i;422 423	event->namespaces.pid		= bswap_32(event->namespaces.pid);424	event->namespaces.tid		= bswap_32(event->namespaces.tid);425	event->namespaces.nr_namespaces	= bswap_64(event->namespaces.nr_namespaces);426 427	for (i = 0; i < event->namespaces.nr_namespaces; i++) {428		struct perf_ns_link_info *ns = &event->namespaces.link_info[i];429 430		ns->dev = bswap_64(ns->dev);431		ns->ino = bswap_64(ns->ino);432	}433 434	if (sample_id_all)435		swap_sample_id_all(event, &event->namespaces.link_info[i]);436}437 438static void perf_event__cgroup_swap(union perf_event *event, bool sample_id_all)439{440	event->cgroup.id = bswap_64(event->cgroup.id);441 442	if (sample_id_all) {443		void *data = &event->cgroup.path;444 445		data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));446		swap_sample_id_all(event, data);447	}448}449 450static u8 revbyte(u8 b)451{452	int rev = (b >> 4) | ((b & 0xf) << 4);453	rev = ((rev & 0xcc) >> 2) | ((rev & 0x33) << 2);454	rev = ((rev & 0xaa) >> 1) | ((rev & 0x55) << 1);455	return (u8) rev;456}457 458/*459 * XXX this is hack in attempt to carry flags bitfield460 * through endian village. ABI says:461 *462 * Bit-fields are allocated from right to left (least to most significant)463 * on little-endian implementations and from left to right (most to least464 * significant) on big-endian implementations.465 *466 * The above seems to be byte specific, so we need to reverse each467 * byte of the bitfield. 'Internet' also says this might be implementation468 * specific and we probably need proper fix and carry perf_event_attr469 * bitfield flags in separate data file FEAT_ section. Thought this seems470 * to work for now.471 */472static void swap_bitfield(u8 *p, unsigned len)473{474	unsigned i;475 476	for (i = 0; i < len; i++) {477		*p = revbyte(*p);478		p++;479	}480}481 482/* exported for swapping attributes in file header */483void perf_event__attr_swap(struct perf_event_attr *attr)484{485	attr->type		= bswap_32(attr->type);486	attr->size		= bswap_32(attr->size);487 488#define bswap_safe(f, n) 					\489	(attr->size > (offsetof(struct perf_event_attr, f) + 	\490		       sizeof(attr->f) * (n)))491#define bswap_field(f, sz) 			\492do { 						\493	if (bswap_safe(f, 0))			\494		attr->f = bswap_##sz(attr->f);	\495} while(0)496#define bswap_field_16(f) bswap_field(f, 16)497#define bswap_field_32(f) bswap_field(f, 32)498#define bswap_field_64(f) bswap_field(f, 64)499 500	bswap_field_64(config);501	bswap_field_64(sample_period);502	bswap_field_64(sample_type);503	bswap_field_64(read_format);504	bswap_field_32(wakeup_events);505	bswap_field_32(bp_type);506	bswap_field_64(bp_addr);507	bswap_field_64(bp_len);508	bswap_field_64(branch_sample_type);509	bswap_field_64(sample_regs_user);510	bswap_field_32(sample_stack_user);511	bswap_field_32(aux_watermark);512	bswap_field_16(sample_max_stack);513	bswap_field_32(aux_sample_size);514 515	/*516	 * After read_format are bitfields. Check read_format because517	 * we are unable to use offsetof on bitfield.518	 */519	if (bswap_safe(read_format, 1))520		swap_bitfield((u8 *) (&attr->read_format + 1),521			      sizeof(u64));522#undef bswap_field_64523#undef bswap_field_32524#undef bswap_field525#undef bswap_safe526}527 528static void perf_event__hdr_attr_swap(union perf_event *event,529				      bool sample_id_all __maybe_unused)530{531	size_t size;532 533	perf_event__attr_swap(&event->attr.attr);534 535	size = event->header.size;536	size -= perf_record_header_attr_id(event) - (void *)event;537	mem_bswap_64(perf_record_header_attr_id(event), size);538}539 540static void perf_event__event_update_swap(union perf_event *event,541					  bool sample_id_all __maybe_unused)542{543	event->event_update.type = bswap_64(event->event_update.type);544	event->event_update.id   = bswap_64(event->event_update.id);545}546 547static void perf_event__event_type_swap(union perf_event *event,548					bool sample_id_all __maybe_unused)549{550	event->event_type.event_type.event_id =551		bswap_64(event->event_type.event_type.event_id);552}553 554static void perf_event__tracing_data_swap(union perf_event *event,555					  bool sample_id_all __maybe_unused)556{557	event->tracing_data.size = bswap_32(event->tracing_data.size);558}559 560static void perf_event__auxtrace_info_swap(union perf_event *event,561					   bool sample_id_all __maybe_unused)562{563	size_t size;564 565	event->auxtrace_info.type = bswap_32(event->auxtrace_info.type);566 567	size = event->header.size;568	size -= (void *)&event->auxtrace_info.priv - (void *)event;569	mem_bswap_64(event->auxtrace_info.priv, size);570}571 572static void perf_event__auxtrace_swap(union perf_event *event,573				      bool sample_id_all __maybe_unused)574{575	event->auxtrace.size      = bswap_64(event->auxtrace.size);576	event->auxtrace.offset    = bswap_64(event->auxtrace.offset);577	event->auxtrace.reference = bswap_64(event->auxtrace.reference);578	event->auxtrace.idx       = bswap_32(event->auxtrace.idx);579	event->auxtrace.tid       = bswap_32(event->auxtrace.tid);580	event->auxtrace.cpu       = bswap_32(event->auxtrace.cpu);581}582 583static void perf_event__auxtrace_error_swap(union perf_event *event,584					    bool sample_id_all __maybe_unused)585{586	event->auxtrace_error.type = bswap_32(event->auxtrace_error.type);587	event->auxtrace_error.code = bswap_32(event->auxtrace_error.code);588	event->auxtrace_error.cpu  = bswap_32(event->auxtrace_error.cpu);589	event->auxtrace_error.pid  = bswap_32(event->auxtrace_error.pid);590	event->auxtrace_error.tid  = bswap_32(event->auxtrace_error.tid);591	event->auxtrace_error.fmt  = bswap_32(event->auxtrace_error.fmt);592	event->auxtrace_error.ip   = bswap_64(event->auxtrace_error.ip);593	if (event->auxtrace_error.fmt)594		event->auxtrace_error.time = bswap_64(event->auxtrace_error.time);595	if (event->auxtrace_error.fmt >= 2) {596		event->auxtrace_error.machine_pid = bswap_32(event->auxtrace_error.machine_pid);597		event->auxtrace_error.vcpu = bswap_32(event->auxtrace_error.vcpu);598	}599}600 601static void perf_event__thread_map_swap(union perf_event *event,602					bool sample_id_all __maybe_unused)603{604	unsigned i;605 606	event->thread_map.nr = bswap_64(event->thread_map.nr);607 608	for (i = 0; i < event->thread_map.nr; i++)609		event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid);610}611 612static void perf_event__cpu_map_swap(union perf_event *event,613				     bool sample_id_all __maybe_unused)614{615	struct perf_record_cpu_map_data *data = &event->cpu_map.data;616 617	data->type = bswap_16(data->type);618 619	switch (data->type) {620	case PERF_CPU_MAP__CPUS:621		data->cpus_data.nr = bswap_16(data->cpus_data.nr);622 623		for (unsigned i = 0; i < data->cpus_data.nr; i++)624			data->cpus_data.cpu[i] = bswap_16(data->cpus_data.cpu[i]);625		break;626	case PERF_CPU_MAP__MASK:627		data->mask32_data.long_size = bswap_16(data->mask32_data.long_size);628 629		switch (data->mask32_data.long_size) {630		case 4:631			data->mask32_data.nr = bswap_16(data->mask32_data.nr);632			for (unsigned i = 0; i < data->mask32_data.nr; i++)633				data->mask32_data.mask[i] = bswap_32(data->mask32_data.mask[i]);634			break;635		case 8:636			data->mask64_data.nr = bswap_16(data->mask64_data.nr);637			for (unsigned i = 0; i < data->mask64_data.nr; i++)638				data->mask64_data.mask[i] = bswap_64(data->mask64_data.mask[i]);639			break;640		default:641			pr_err("cpu_map swap: unsupported long size\n");642		}643		break;644	case PERF_CPU_MAP__RANGE_CPUS:645		data->range_cpu_data.start_cpu = bswap_16(data->range_cpu_data.start_cpu);646		data->range_cpu_data.end_cpu = bswap_16(data->range_cpu_data.end_cpu);647		break;648	default:649		break;650	}651}652 653static void perf_event__stat_config_swap(union perf_event *event,654					 bool sample_id_all __maybe_unused)655{656	u64 size;657 658	size  = bswap_64(event->stat_config.nr) * sizeof(event->stat_config.data[0]);659	size += 1; /* nr item itself */660	mem_bswap_64(&event->stat_config.nr, size);661}662 663static void perf_event__stat_swap(union perf_event *event,664				  bool sample_id_all __maybe_unused)665{666	event->stat.id     = bswap_64(event->stat.id);667	event->stat.thread = bswap_32(event->stat.thread);668	event->stat.cpu    = bswap_32(event->stat.cpu);669	event->stat.val    = bswap_64(event->stat.val);670	event->stat.ena    = bswap_64(event->stat.ena);671	event->stat.run    = bswap_64(event->stat.run);672}673 674static void perf_event__stat_round_swap(union perf_event *event,675					bool sample_id_all __maybe_unused)676{677	event->stat_round.type = bswap_64(event->stat_round.type);678	event->stat_round.time = bswap_64(event->stat_round.time);679}680 681static void perf_event__time_conv_swap(union perf_event *event,682				       bool sample_id_all __maybe_unused)683{684	event->time_conv.time_shift = bswap_64(event->time_conv.time_shift);685	event->time_conv.time_mult  = bswap_64(event->time_conv.time_mult);686	event->time_conv.time_zero  = bswap_64(event->time_conv.time_zero);687 688	if (event_contains(event->time_conv, time_cycles)) {689		event->time_conv.time_cycles = bswap_64(event->time_conv.time_cycles);690		event->time_conv.time_mask = bswap_64(event->time_conv.time_mask);691	}692}693 694typedef void (*perf_event__swap_op)(union perf_event *event,695				    bool sample_id_all);696 697static perf_event__swap_op perf_event__swap_ops[] = {698	[PERF_RECORD_MMAP]		  = perf_event__mmap_swap,699	[PERF_RECORD_MMAP2]		  = perf_event__mmap2_swap,700	[PERF_RECORD_COMM]		  = perf_event__comm_swap,701	[PERF_RECORD_FORK]		  = perf_event__task_swap,702	[PERF_RECORD_EXIT]		  = perf_event__task_swap,703	[PERF_RECORD_LOST]		  = perf_event__all64_swap,704	[PERF_RECORD_READ]		  = perf_event__read_swap,705	[PERF_RECORD_THROTTLE]		  = perf_event__throttle_swap,706	[PERF_RECORD_UNTHROTTLE]	  = perf_event__throttle_swap,707	[PERF_RECORD_SAMPLE]		  = perf_event__all64_swap,708	[PERF_RECORD_AUX]		  = perf_event__aux_swap,709	[PERF_RECORD_ITRACE_START]	  = perf_event__itrace_start_swap,710	[PERF_RECORD_LOST_SAMPLES]	  = perf_event__all64_swap,711	[PERF_RECORD_SWITCH]		  = perf_event__switch_swap,712	[PERF_RECORD_SWITCH_CPU_WIDE]	  = perf_event__switch_swap,713	[PERF_RECORD_NAMESPACES]	  = perf_event__namespaces_swap,714	[PERF_RECORD_CGROUP]		  = perf_event__cgroup_swap,715	[PERF_RECORD_TEXT_POKE]		  = perf_event__text_poke_swap,716	[PERF_RECORD_AUX_OUTPUT_HW_ID]	  = perf_event__all64_swap,717	[PERF_RECORD_HEADER_ATTR]	  = perf_event__hdr_attr_swap,718	[PERF_RECORD_HEADER_EVENT_TYPE]	  = perf_event__event_type_swap,719	[PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,720	[PERF_RECORD_HEADER_BUILD_ID]	  = NULL,721	[PERF_RECORD_ID_INDEX]		  = perf_event__all64_swap,722	[PERF_RECORD_AUXTRACE_INFO]	  = perf_event__auxtrace_info_swap,723	[PERF_RECORD_AUXTRACE]		  = perf_event__auxtrace_swap,724	[PERF_RECORD_AUXTRACE_ERROR]	  = perf_event__auxtrace_error_swap,725	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,726	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,727	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,728	[PERF_RECORD_STAT]		  = perf_event__stat_swap,729	[PERF_RECORD_STAT_ROUND]	  = perf_event__stat_round_swap,730	[PERF_RECORD_EVENT_UPDATE]	  = perf_event__event_update_swap,731	[PERF_RECORD_TIME_CONV]		  = perf_event__time_conv_swap,732	[PERF_RECORD_HEADER_MAX]	  = NULL,733};734 735/*736 * When perf record finishes a pass on every buffers, it records this pseudo737 * event.738 * We record the max timestamp t found in the pass n.739 * Assuming these timestamps are monotonic across cpus, we know that if740 * a buffer still has events with timestamps below t, they will be all741 * available and then read in the pass n + 1.742 * Hence when we start to read the pass n + 2, we can safely flush every743 * events with timestamps below t.744 *745 *    ============ PASS n =================746 *       CPU 0         |   CPU 1747 *                     |748 *    cnt1 timestamps  |   cnt2 timestamps749 *          1          |         2750 *          2          |         3751 *          -          |         4  <--- max recorded752 *753 *    ============ PASS n + 1 ==============754 *       CPU 0         |   CPU 1755 *                     |756 *    cnt1 timestamps  |   cnt2 timestamps757 *          3          |         5758 *          4          |         6759 *          5          |         7 <---- max recorded760 *761 *      Flush every events below timestamp 4762 *763 *    ============ PASS n + 2 ==============764 *       CPU 0         |   CPU 1765 *                     |766 *    cnt1 timestamps  |   cnt2 timestamps767 *          6          |         8768 *          7          |         9769 *          -          |         10770 *771 *      Flush every events below timestamp 7772 *      etc...773 */774int perf_event__process_finished_round(const struct perf_tool *tool __maybe_unused,775				       union perf_event *event __maybe_unused,776				       struct ordered_events *oe)777{778	if (dump_trace)779		fprintf(stdout, "\n");780	return ordered_events__flush(oe, OE_FLUSH__ROUND);781}782 783int perf_session__queue_event(struct perf_session *s, union perf_event *event,784			      u64 timestamp, u64 file_offset, const char *file_path)785{786	return ordered_events__queue(&s->ordered_events, event, timestamp, file_offset, file_path);787}788 789static void callchain__lbr_callstack_printf(struct perf_sample *sample)790{791	struct ip_callchain *callchain = sample->callchain;792	struct branch_stack *lbr_stack = sample->branch_stack;793	struct branch_entry *entries = perf_sample__branch_entries(sample);794	u64 kernel_callchain_nr = callchain->nr;795	unsigned int i;796 797	for (i = 0; i < kernel_callchain_nr; i++) {798		if (callchain->ips[i] == PERF_CONTEXT_USER)799			break;800	}801 802	if ((i != kernel_callchain_nr) && lbr_stack->nr) {803		u64 total_nr;804		/*805		 * LBR callstack can only get user call chain,806		 * i is kernel call chain number,807		 * 1 is PERF_CONTEXT_USER.808		 *809		 * The user call chain is stored in LBR registers.810		 * LBR are pair registers. The caller is stored811		 * in "from" register, while the callee is stored812		 * in "to" register.813		 * For example, there is a call stack814		 * "A"->"B"->"C"->"D".815		 * The LBR registers will be recorded like816		 * "C"->"D", "B"->"C", "A"->"B".817		 * So only the first "to" register and all "from"818		 * registers are needed to construct the whole stack.819		 */820		total_nr = i + 1 + lbr_stack->nr + 1;821		kernel_callchain_nr = i + 1;822 823		printf("... LBR call chain: nr:%" PRIu64 "\n", total_nr);824 825		for (i = 0; i < kernel_callchain_nr; i++)826			printf("..... %2d: %016" PRIx64 "\n",827			       i, callchain->ips[i]);828 829		printf("..... %2d: %016" PRIx64 "\n",830		       (int)(kernel_callchain_nr), entries[0].to);831		for (i = 0; i < lbr_stack->nr; i++)832			printf("..... %2d: %016" PRIx64 "\n",833			       (int)(i + kernel_callchain_nr + 1), entries[i].from);834	}835}836 837static void callchain__printf(struct evsel *evsel,838			      struct perf_sample *sample)839{840	unsigned int i;841	struct ip_callchain *callchain = sample->callchain;842 843	if (evsel__has_branch_callstack(evsel))844		callchain__lbr_callstack_printf(sample);845 846	printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);847 848	for (i = 0; i < callchain->nr; i++)849		printf("..... %2d: %016" PRIx64 "\n",850		       i, callchain->ips[i]);851}852 853static void branch_stack__printf(struct perf_sample *sample,854				 struct evsel *evsel)855{856	struct branch_entry *entries = perf_sample__branch_entries(sample);857	bool callstack = evsel__has_branch_callstack(evsel);858	u64 *branch_stack_cntr = sample->branch_stack_cntr;859	uint64_t i;860 861	if (!callstack) {862		printf("%s: nr:%" PRIu64 "\n", "... branch stack", sample->branch_stack->nr);863	} else {864		/* the reason of adding 1 to nr is because after expanding865		 * branch stack it generates nr + 1 callstack records. e.g.,866		 *         B()->C()867		 *         A()->B()868		 * the final callstack should be:869		 *         C()870		 *         B()871		 *         A()872		 */873		printf("%s: nr:%" PRIu64 "\n", "... branch callstack", sample->branch_stack->nr+1);874	}875 876	for (i = 0; i < sample->branch_stack->nr; i++) {877		struct branch_entry *e = &entries[i];878 879		if (!callstack) {880			printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 " %hu cycles %s%s%s%s %x %s %s\n",881				i, e->from, e->to,882				(unsigned short)e->flags.cycles,883				e->flags.mispred ? "M" : " ",884				e->flags.predicted ? "P" : " ",885				e->flags.abort ? "A" : " ",886				e->flags.in_tx ? "T" : " ",887				(unsigned)e->flags.reserved,888				get_branch_type(e),889				e->flags.spec ? branch_spec_desc(e->flags.spec) : "");890		} else {891			if (i == 0) {892				printf("..... %2"PRIu64": %016" PRIx64 "\n"893				       "..... %2"PRIu64": %016" PRIx64 "\n",894						i, e->to, i+1, e->from);895			} else {896				printf("..... %2"PRIu64": %016" PRIx64 "\n", i+1, e->from);897			}898		}899	}900 901	if (branch_stack_cntr) {902		unsigned int br_cntr_width, br_cntr_nr;903 904		perf_env__find_br_cntr_info(evsel__env(evsel), &br_cntr_nr, &br_cntr_width);905		printf("... branch stack counters: nr:%" PRIu64 " (counter width: %u max counter nr:%u)\n",906			sample->branch_stack->nr, br_cntr_width, br_cntr_nr);907		for (i = 0; i < sample->branch_stack->nr; i++)908			printf("..... %2"PRIu64": %016" PRIx64 "\n", i, branch_stack_cntr[i]);909	}910}911 912static void regs_dump__printf(u64 mask, u64 *regs, const char *arch)913{914	unsigned rid, i = 0;915 916	for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) {917		u64 val = regs[i++];918 919		printf(".... %-5s 0x%016" PRIx64 "\n",920		       perf_reg_name(rid, arch), val);921	}922}923 924static const char *regs_abi[] = {925	[PERF_SAMPLE_REGS_ABI_NONE] = "none",926	[PERF_SAMPLE_REGS_ABI_32] = "32-bit",927	[PERF_SAMPLE_REGS_ABI_64] = "64-bit",928};929 930static inline const char *regs_dump_abi(struct regs_dump *d)931{932	if (d->abi > PERF_SAMPLE_REGS_ABI_64)933		return "unknown";934 935	return regs_abi[d->abi];936}937 938static void regs__printf(const char *type, struct regs_dump *regs, const char *arch)939{940	u64 mask = regs->mask;941 942	printf("... %s regs: mask 0x%" PRIx64 " ABI %s\n",943	       type,944	       mask,945	       regs_dump_abi(regs));946 947	regs_dump__printf(mask, regs->regs, arch);948}949 950static void regs_user__printf(struct perf_sample *sample, const char *arch)951{952	struct regs_dump *user_regs = &sample->user_regs;953 954	if (user_regs->regs)955		regs__printf("user", user_regs, arch);956}957 958static void regs_intr__printf(struct perf_sample *sample, const char *arch)959{960	struct regs_dump *intr_regs = &sample->intr_regs;961 962	if (intr_regs->regs)963		regs__printf("intr", intr_regs, arch);964}965 966static void stack_user__printf(struct stack_dump *dump)967{968	printf("... ustack: size %" PRIu64 ", offset 0x%x\n",969	       dump->size, dump->offset);970}971 972static void evlist__print_tstamp(struct evlist *evlist, union perf_event *event, struct perf_sample *sample)973{974	u64 sample_type = __evlist__combined_sample_type(evlist);975 976	if (event->header.type != PERF_RECORD_SAMPLE &&977	    !evlist__sample_id_all(evlist)) {978		fputs("-1 -1 ", stdout);979		return;980	}981 982	if ((sample_type & PERF_SAMPLE_CPU))983		printf("%u ", sample->cpu);984 985	if (sample_type & PERF_SAMPLE_TIME)986		printf("%" PRIu64 " ", sample->time);987}988 989static void sample_read__printf(struct perf_sample *sample, u64 read_format)990{991	printf("... sample_read:\n");992 993	if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)994		printf("...... time enabled %016" PRIx64 "\n",995		       sample->read.time_enabled);996 997	if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)998		printf("...... time running %016" PRIx64 "\n",999		       sample->read.time_running);1000 1001	if (read_format & PERF_FORMAT_GROUP) {1002		struct sample_read_value *value = sample->read.group.values;1003 1004		printf(".... group nr %" PRIu64 "\n", sample->read.group.nr);1005 1006		sample_read_group__for_each(value, sample->read.group.nr, read_format) {1007			printf("..... id %016" PRIx641008			       ", value %016" PRIx64,1009			       value->id, value->value);1010			if (read_format & PERF_FORMAT_LOST)1011				printf(", lost %" PRIu64, value->lost);1012			printf("\n");1013		}1014	} else {1015		printf("..... id %016" PRIx64 ", value %016" PRIx64,1016			sample->read.one.id, sample->read.one.value);1017		if (read_format & PERF_FORMAT_LOST)1018			printf(", lost %" PRIu64, sample->read.one.lost);1019		printf("\n");1020	}1021}1022 1023static void dump_event(struct evlist *evlist, union perf_event *event,1024		       u64 file_offset, struct perf_sample *sample,1025		       const char *file_path)1026{1027	if (!dump_trace)1028		return;1029 1030	printf("\n%#" PRIx64 "@%s [%#x]: event: %d\n",1031	       file_offset, file_path, event->header.size, event->header.type);1032 1033	trace_event(event);1034	if (event->header.type == PERF_RECORD_SAMPLE && evlist->trace_event_sample_raw)1035		evlist->trace_event_sample_raw(evlist, event, sample);1036 1037	if (sample)1038		evlist__print_tstamp(evlist, event, sample);1039 1040	printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,1041	       event->header.size, perf_event__name(event->header.type));1042}1043 1044char *get_page_size_name(u64 size, char *str)1045{1046	if (!size || !unit_number__scnprintf(str, PAGE_SIZE_NAME_LEN, size))1047		snprintf(str, PAGE_SIZE_NAME_LEN, "%s", "N/A");1048 1049	return str;1050}1051 1052static void dump_sample(struct evsel *evsel, union perf_event *event,1053			struct perf_sample *sample, const char *arch)1054{1055	u64 sample_type;1056	char str[PAGE_SIZE_NAME_LEN];1057 1058	if (!dump_trace)1059		return;1060 1061	printf("(IP, 0x%x): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",1062	       event->header.misc, sample->pid, sample->tid, sample->ip,1063	       sample->period, sample->addr);1064 1065	sample_type = evsel->core.attr.sample_type;1066 1067	if (evsel__has_callchain(evsel))1068		callchain__printf(evsel, sample);1069 1070	if (evsel__has_br_stack(evsel))1071		branch_stack__printf(sample, evsel);1072 1073	if (sample_type & PERF_SAMPLE_REGS_USER)1074		regs_user__printf(sample, arch);1075 1076	if (sample_type & PERF_SAMPLE_REGS_INTR)1077		regs_intr__printf(sample, arch);1078 1079	if (sample_type & PERF_SAMPLE_STACK_USER)1080		stack_user__printf(&sample->user_stack);1081 1082	if (sample_type & PERF_SAMPLE_WEIGHT_TYPE) {1083		printf("... weight: %" PRIu64 "", sample->weight);1084			if (sample_type & PERF_SAMPLE_WEIGHT_STRUCT) {1085				printf(",0x%"PRIx16"", sample->ins_lat);1086				printf(",0x%"PRIx16"", sample->p_stage_cyc);1087			}1088		printf("\n");1089	}1090 1091	if (sample_type & PERF_SAMPLE_DATA_SRC)1092		printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);1093 1094	if (sample_type & PERF_SAMPLE_PHYS_ADDR)1095		printf(" .. phys_addr: 0x%"PRIx64"\n", sample->phys_addr);1096 1097	if (sample_type & PERF_SAMPLE_DATA_PAGE_SIZE)1098		printf(" .. data page size: %s\n", get_page_size_name(sample->data_page_size, str));1099 1100	if (sample_type & PERF_SAMPLE_CODE_PAGE_SIZE)1101		printf(" .. code page size: %s\n", get_page_size_name(sample->code_page_size, str));1102 1103	if (sample_type & PERF_SAMPLE_TRANSACTION)1104		printf("... transaction: %" PRIx64 "\n", sample->transaction);1105 1106	if (sample_type & PERF_SAMPLE_READ)1107		sample_read__printf(sample, evsel->core.attr.read_format);1108}1109 1110static void dump_read(struct evsel *evsel, union perf_event *event)1111{1112	struct perf_record_read *read_event = &event->read;1113	u64 read_format;1114 1115	if (!dump_trace)1116		return;1117 1118	printf(": %d %d %s %" PRI_lu64 "\n", event->read.pid, event->read.tid,1119	       evsel__name(evsel), event->read.value);1120 1121	if (!evsel)1122		return;1123 1124	read_format = evsel->core.attr.read_format;1125 1126	if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)1127		printf("... time enabled : %" PRI_lu64 "\n", read_event->time_enabled);1128 1129	if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)1130		printf("... time running : %" PRI_lu64 "\n", read_event->time_running);1131 1132	if (read_format & PERF_FORMAT_ID)1133		printf("... id           : %" PRI_lu64 "\n", read_event->id);1134 1135	if (read_format & PERF_FORMAT_LOST)1136		printf("... lost         : %" PRI_lu64 "\n", read_event->lost);1137}1138 1139static struct machine *machines__find_for_cpumode(struct machines *machines,1140					       union perf_event *event,1141					       struct perf_sample *sample)1142{1143	if (perf_guest &&1144	    ((sample->cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||1145	     (sample->cpumode == PERF_RECORD_MISC_GUEST_USER))) {1146		u32 pid;1147 1148		if (sample->machine_pid)1149			pid = sample->machine_pid;1150		else if (event->header.type == PERF_RECORD_MMAP1151		    || event->header.type == PERF_RECORD_MMAP2)1152			pid = event->mmap.pid;1153		else1154			pid = sample->pid;1155 1156		/*1157		 * Guest code machine is created as needed and does not use1158		 * DEFAULT_GUEST_KERNEL_ID.1159		 */1160		if (symbol_conf.guest_code)1161			return machines__findnew(machines, pid);1162 1163		return machines__find_guest(machines, pid);1164	}1165 1166	return &machines->host;1167}1168 1169static int deliver_sample_value(struct evlist *evlist,1170				const struct perf_tool *tool,1171				union perf_event *event,1172				struct perf_sample *sample,1173				struct sample_read_value *v,1174				struct machine *machine)1175{1176	struct perf_sample_id *sid = evlist__id2sid(evlist, v->id);1177	struct evsel *evsel;1178 1179	if (sid) {1180		sample->id     = v->id;1181		sample->period = v->value - sid->period;1182		sid->period    = v->value;1183	}1184 1185	if (!sid || sid->evsel == NULL) {1186		++evlist->stats.nr_unknown_id;1187		return 0;1188	}1189 1190	/*1191	 * There's no reason to deliver sample1192	 * for zero period, bail out.1193	 */1194	if (!sample->period)1195		return 0;1196 1197	evsel = container_of(sid->evsel, struct evsel, core);1198	return tool->sample(tool, event, sample, evsel, machine);1199}1200 1201static int deliver_sample_group(struct evlist *evlist,1202				const struct perf_tool *tool,1203				union  perf_event *event,1204				struct perf_sample *sample,1205				struct machine *machine,1206				u64 read_format)1207{1208	int ret = -EINVAL;1209	struct sample_read_value *v = sample->read.group.values;1210 1211	if (tool->dont_split_sample_group)1212		return deliver_sample_value(evlist, tool, event, sample, v, machine);1213 1214	sample_read_group__for_each(v, sample->read.group.nr, read_format) {1215		ret = deliver_sample_value(evlist, tool, event, sample, v,1216					   machine);1217		if (ret)1218			break;1219	}1220 1221	return ret;1222}1223 1224static int evlist__deliver_sample(struct evlist *evlist, const struct perf_tool *tool,1225				  union  perf_event *event, struct perf_sample *sample,1226				  struct evsel *evsel, struct machine *machine)1227{1228	/* We know evsel != NULL. */1229	u64 sample_type = evsel->core.attr.sample_type;1230	u64 read_format = evsel->core.attr.read_format;1231 1232	/* Standard sample delivery. */1233	if (!(sample_type & PERF_SAMPLE_READ))1234		return tool->sample(tool, event, sample, evsel, machine);1235 1236	/* For PERF_SAMPLE_READ we have either single or group mode. */1237	if (read_format & PERF_FORMAT_GROUP)1238		return deliver_sample_group(evlist, tool, event, sample,1239					    machine, read_format);1240	else1241		return deliver_sample_value(evlist, tool, event, sample,1242					    &sample->read.one, machine);1243}1244 1245static int machines__deliver_event(struct machines *machines,1246				   struct evlist *evlist,1247				   union perf_event *event,1248				   struct perf_sample *sample,1249				   const struct perf_tool *tool, u64 file_offset,1250				   const char *file_path)1251{1252	struct evsel *evsel;1253	struct machine *machine;1254 1255	dump_event(evlist, event, file_offset, sample, file_path);1256 1257	evsel = evlist__id2evsel(evlist, sample->id);1258 1259	machine = machines__find_for_cpumode(machines, event, sample);1260 1261	switch (event->header.type) {1262	case PERF_RECORD_SAMPLE:1263		if (evsel == NULL) {1264			++evlist->stats.nr_unknown_id;1265			return 0;1266		}1267		if (machine == NULL) {1268			++evlist->stats.nr_unprocessable_samples;1269			dump_sample(evsel, event, sample, perf_env__arch(NULL));1270			return 0;1271		}1272		dump_sample(evsel, event, sample, perf_env__arch(machine->env));1273		return evlist__deliver_sample(evlist, tool, event, sample, evsel, machine);1274	case PERF_RECORD_MMAP:1275		return tool->mmap(tool, event, sample, machine);1276	case PERF_RECORD_MMAP2:1277		if (event->header.misc & PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT)1278			++evlist->stats.nr_proc_map_timeout;1279		return tool->mmap2(tool, event, sample, machine);1280	case PERF_RECORD_COMM:1281		return tool->comm(tool, event, sample, machine);1282	case PERF_RECORD_NAMESPACES:1283		return tool->namespaces(tool, event, sample, machine);1284	case PERF_RECORD_CGROUP:1285		return tool->cgroup(tool, event, sample, machine);1286	case PERF_RECORD_FORK:1287		return tool->fork(tool, event, sample, machine);1288	case PERF_RECORD_EXIT:1289		return tool->exit(tool, event, sample, machine);1290	case PERF_RECORD_LOST:1291		if (tool->lost == perf_event__process_lost)1292			evlist->stats.total_lost += event->lost.lost;1293		return tool->lost(tool, event, sample, machine);1294	case PERF_RECORD_LOST_SAMPLES:1295		if (event->header.misc & PERF_RECORD_MISC_LOST_SAMPLES_BPF)1296			evlist->stats.total_dropped_samples += event->lost_samples.lost;1297		else if (tool->lost_samples == perf_event__process_lost_samples)1298			evlist->stats.total_lost_samples += event->lost_samples.lost;1299		return tool->lost_samples(tool, event, sample, machine);1300	case PERF_RECORD_READ:1301		dump_read(evsel, event);1302		return tool->read(tool, event, sample, evsel, machine);1303	case PERF_RECORD_THROTTLE:1304		return tool->throttle(tool, event, sample, machine);1305	case PERF_RECORD_UNTHROTTLE:1306		return tool->unthrottle(tool, event, sample, machine);1307	case PERF_RECORD_AUX:1308		if (tool->aux == perf_event__process_aux) {1309			if (event->aux.flags & PERF_AUX_FLAG_TRUNCATED)1310				evlist->stats.total_aux_lost += 1;1311			if (event->aux.flags & PERF_AUX_FLAG_PARTIAL)1312				evlist->stats.total_aux_partial += 1;1313			if (event->aux.flags & PERF_AUX_FLAG_COLLISION)1314				evlist->stats.total_aux_collision += 1;1315		}1316		return tool->aux(tool, event, sample, machine);1317	case PERF_RECORD_ITRACE_START:1318		return tool->itrace_start(tool, event, sample, machine);1319	case PERF_RECORD_SWITCH:1320	case PERF_RECORD_SWITCH_CPU_WIDE:1321		return tool->context_switch(tool, event, sample, machine);1322	case PERF_RECORD_KSYMBOL:1323		return tool->ksymbol(tool, event, sample, machine);1324	case PERF_RECORD_BPF_EVENT:1325		return tool->bpf(tool, event, sample, machine);1326	case PERF_RECORD_TEXT_POKE:1327		return tool->text_poke(tool, event, sample, machine);1328	case PERF_RECORD_AUX_OUTPUT_HW_ID:1329		return tool->aux_output_hw_id(tool, event, sample, machine);1330	default:1331		++evlist->stats.nr_unknown_events;1332		return -1;1333	}1334}1335 1336static int perf_session__deliver_event(struct perf_session *session,1337				       union perf_event *event,1338				       const struct perf_tool *tool,1339				       u64 file_offset,1340				       const char *file_path)1341{1342	struct perf_sample sample;1343	int ret = evlist__parse_sample(session->evlist, event, &sample);1344 1345	if (ret) {1346		pr_err("Can't parse sample, err = %d\n", ret);1347		return ret;1348	}1349 1350	ret = auxtrace__process_event(session, event, &sample, tool);1351	if (ret < 0)1352		return ret;1353	if (ret > 0)1354		return 0;1355 1356	ret = machines__deliver_event(&session->machines, session->evlist,1357				      event, &sample, tool, file_offset, file_path);1358 1359	if (dump_trace && sample.aux_sample.size)1360		auxtrace__dump_auxtrace_sample(session, &sample);1361 1362	return ret;1363}1364 1365static s64 perf_session__process_user_event(struct perf_session *session,1366					    union perf_event *event,1367					    u64 file_offset,1368					    const char *file_path)1369{1370	struct ordered_events *oe = &session->ordered_events;1371	const struct perf_tool *tool = session->tool;1372	struct perf_sample sample = { .time = 0, };1373	int fd = perf_data__fd(session->data);1374	int err;1375 1376	if (event->header.type != PERF_RECORD_COMPRESSED || perf_tool__compressed_is_stub(tool))1377		dump_event(session->evlist, event, file_offset, &sample, file_path);1378 1379	/* These events are processed right away */1380	switch (event->header.type) {1381	case PERF_RECORD_HEADER_ATTR:1382		err = tool->attr(tool, event, &session->evlist);1383		if (err == 0) {1384			perf_session__set_id_hdr_size(session);1385			perf_session__set_comm_exec(session);1386		}1387		return err;1388	case PERF_RECORD_EVENT_UPDATE:1389		return tool->event_update(tool, event, &session->evlist);1390	case PERF_RECORD_HEADER_EVENT_TYPE:1391		/*1392		 * Deprecated, but we need to handle it for sake1393		 * of old data files create in pipe mode.1394		 */1395		return 0;1396	case PERF_RECORD_HEADER_TRACING_DATA:1397		/*1398		 * Setup for reading amidst mmap, but only when we1399		 * are in 'file' mode. The 'pipe' fd is in proper1400		 * place already.1401		 */1402		if (!perf_data__is_pipe(session->data))1403			lseek(fd, file_offset, SEEK_SET);1404		return tool->tracing_data(session, event);1405	case PERF_RECORD_HEADER_BUILD_ID:1406		return tool->build_id(session, event);1407	case PERF_RECORD_FINISHED_ROUND:1408		return tool->finished_round(tool, event, oe);1409	case PERF_RECORD_ID_INDEX:1410		return tool->id_index(session, event);1411	case PERF_RECORD_AUXTRACE_INFO:1412		return tool->auxtrace_info(session, event);1413	case PERF_RECORD_AUXTRACE:1414		/*1415		 * Setup for reading amidst mmap, but only when we1416		 * are in 'file' mode.  The 'pipe' fd is in proper1417		 * place already.1418		 */1419		if (!perf_data__is_pipe(session->data))1420			lseek(fd, file_offset + event->header.size, SEEK_SET);1421		return tool->auxtrace(session, event);1422	case PERF_RECORD_AUXTRACE_ERROR:1423		perf_session__auxtrace_error_inc(session, event);1424		return tool->auxtrace_error(session, event);1425	case PERF_RECORD_THREAD_MAP:1426		return tool->thread_map(session, event);1427	case PERF_RECORD_CPU_MAP:1428		return tool->cpu_map(session, event);1429	case PERF_RECORD_STAT_CONFIG:1430		return tool->stat_config(session, event);1431	case PERF_RECORD_STAT:1432		return tool->stat(session, event);1433	case PERF_RECORD_STAT_ROUND:1434		return tool->stat_round(session, event);1435	case PERF_RECORD_TIME_CONV:1436		session->time_conv = event->time_conv;1437		return tool->time_conv(session, event);1438	case PERF_RECORD_HEADER_FEATURE:1439		return tool->feature(session, event);1440	case PERF_RECORD_COMPRESSED:1441		err = tool->compressed(session, event, file_offset, file_path);1442		if (err)1443			dump_event(session->evlist, event, file_offset, &sample, file_path);1444		return err;1445	case PERF_RECORD_FINISHED_INIT:1446		return tool->finished_init(session, event);1447	default:1448		return -EINVAL;1449	}1450}1451 1452int perf_session__deliver_synth_event(struct perf_session *session,1453				      union perf_event *event,1454				      struct perf_sample *sample)1455{1456	struct evlist *evlist = session->evlist;1457	const struct perf_tool *tool = session->tool;1458 1459	events_stats__inc(&evlist->stats, event->header.type);1460 1461	if (event->header.type >= PERF_RECORD_USER_TYPE_START)1462		return perf_session__process_user_event(session, event, 0, NULL);1463 1464	return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0, NULL);1465}1466 1467int perf_session__deliver_synth_attr_event(struct perf_session *session,1468					   const struct perf_event_attr *attr,1469					   u64 id)1470{1471	union {1472		struct {1473			struct perf_record_header_attr attr;1474			u64 ids[1];1475		} attr_id;1476		union perf_event ev;1477	} ev = {1478		.attr_id.attr.header.type = PERF_RECORD_HEADER_ATTR,1479		.attr_id.attr.header.size = sizeof(ev.attr_id),1480		.attr_id.ids[0] = id,1481	};1482 1483	if (attr->size != sizeof(ev.attr_id.attr.attr)) {1484		pr_debug("Unexpected perf_event_attr size\n");1485		return -EINVAL;1486	}1487	ev.attr_id.attr.attr = *attr;1488	return perf_session__deliver_synth_event(session, &ev.ev, NULL);1489}1490 1491static void event_swap(union perf_event *event, bool sample_id_all)1492{1493	perf_event__swap_op swap;1494 1495	swap = perf_event__swap_ops[event->header.type];1496	if (swap)1497		swap(event, sample_id_all);1498}1499 1500int perf_session__peek_event(struct perf_session *session, off_t file_offset,1501			     void *buf, size_t buf_sz,1502			     union perf_event **event_ptr,1503			     struct perf_sample *sample)1504{1505	union perf_event *event;1506	size_t hdr_sz, rest;1507	int fd;1508 1509	if (session->one_mmap && !session->header.needs_swap) {1510		event = file_offset - session->one_mmap_offset +1511			session->one_mmap_addr;1512		goto out_parse_sample;1513	}1514 1515	if (perf_data__is_pipe(session->data))1516		return -1;1517 1518	fd = perf_data__fd(session->data);1519	hdr_sz = sizeof(struct perf_event_header);1520 1521	if (buf_sz < hdr_sz)1522		return -1;1523 1524	if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 ||1525	    readn(fd, buf, hdr_sz) != (ssize_t)hdr_sz)1526		return -1;1527 1528	event = (union perf_event *)buf;1529 1530	if (session->header.needs_swap)1531		perf_event_header__bswap(&event->header);1532 1533	if (event->header.size < hdr_sz || event->header.size > buf_sz)1534		return -1;1535 1536	buf += hdr_sz;1537	rest = event->header.size - hdr_sz;1538 1539	if (readn(fd, buf, rest) != (ssize_t)rest)1540		return -1;1541 1542	if (session->header.needs_swap)1543		event_swap(event, evlist__sample_id_all(session->evlist));1544 1545out_parse_sample:1546 1547	if (sample && event->header.type < PERF_RECORD_USER_TYPE_START &&1548	    evlist__parse_sample(session->evlist, event, sample))1549		return -1;1550 1551	*event_ptr = event;1552 1553	return 0;1554}1555 1556int perf_session__peek_events(struct perf_session *session, u64 offset,1557			      u64 size, peek_events_cb_t cb, void *data)1558{1559	u64 max_offset = offset + size;1560	char buf[PERF_SAMPLE_MAX_SIZE];1561	union perf_event *event;1562	int err;1563 1564	do {1565		err = perf_session__peek_event(session, offset, buf,1566					       PERF_SAMPLE_MAX_SIZE, &event,1567					       NULL);1568		if (err)1569			return err;1570 1571		err = cb(session, event, offset, data);1572		if (err)1573			return err;1574 1575		offset += event->header.size;1576		if (event->header.type == PERF_RECORD_AUXTRACE)1577			offset += event->auxtrace.size;1578 1579	} while (offset < max_offset);1580 1581	return err;1582}1583 1584static s64 perf_session__process_event(struct perf_session *session,1585				       union perf_event *event, u64 file_offset,1586				       const char *file_path)1587{1588	struct evlist *evlist = session->evlist;1589	const struct perf_tool *tool = session->tool;1590	int ret;1591 1592	if (session->header.needs_swap)1593		event_swap(event, evlist__sample_id_all(evlist));1594 1595	if (event->header.type >= PERF_RECORD_HEADER_MAX)1596		return -EINVAL;1597 1598	events_stats__inc(&evlist->stats, event->header.type);1599 1600	if (event->header.type >= PERF_RECORD_USER_TYPE_START)1601		return perf_session__process_user_event(session, event, file_offset, file_path);1602 1603	if (tool->ordered_events) {1604		u64 timestamp = -1ULL;1605 1606		ret = evlist__parse_sample_timestamp(evlist, event, &timestamp);1607		if (ret && ret != -1)1608			return ret;1609 1610		ret = perf_session__queue_event(session, event, timestamp, file_offset, file_path);1611		if (ret != -ETIME)1612			return ret;1613	}1614 1615	return perf_session__deliver_event(session, event, tool, file_offset, file_path);1616}1617 1618void perf_event_header__bswap(struct perf_event_header *hdr)1619{1620	hdr->type = bswap_32(hdr->type);1621	hdr->misc = bswap_16(hdr->misc);1622	hdr->size = bswap_16(hdr->size);1623}1624 1625struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)1626{1627	return machine__findnew_thread(&session->machines.host, -1, pid);1628}1629 1630int perf_session__register_idle_thread(struct perf_session *session)1631{1632	struct thread *thread = machine__idle_thread(&session->machines.host);1633 1634	/* machine__idle_thread() got the thread, so put it */1635	thread__put(thread);1636	return thread ? 0 : -1;1637}1638 1639static void1640perf_session__warn_order(const struct perf_session *session)1641{1642	const struct ordered_events *oe = &session->ordered_events;1643	struct evsel *evsel;1644	bool should_warn = true;1645 1646	evlist__for_each_entry(session->evlist, evsel) {1647		if (evsel->core.attr.write_backward)1648			should_warn = false;1649	}1650 1651	if (!should_warn)1652		return;1653	if (oe->nr_unordered_events != 0)1654		ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);1655}1656 1657static void perf_session__warn_about_errors(const struct perf_session *session)1658{1659	const struct events_stats *stats = &session->evlist->stats;1660 1661	if (session->tool->lost == perf_event__process_lost &&1662	    stats->nr_events[PERF_RECORD_LOST] != 0) {1663		ui__warning("Processed %d events and lost %d chunks!\n\n"1664			    "Check IO/CPU overload!\n\n",1665			    stats->nr_events[0],1666			    stats->nr_events[PERF_RECORD_LOST]);1667	}1668 1669	if (session->tool->lost_samples == perf_event__process_lost_samples) {1670		double drop_rate;1671 1672		drop_rate = (double)stats->total_lost_samples /1673			    (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples);1674		if (drop_rate > 0.05) {1675			ui__warning("Processed %" PRIu64 " samples and lost %3.2f%%!\n\n",1676				    stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples,1677				    drop_rate * 100.0);1678		}1679	}1680 1681	if (session->tool->aux == perf_event__process_aux &&1682	    stats->total_aux_lost != 0) {1683		ui__warning("AUX data lost %" PRIu64 " times out of %u!\n\n",1684			    stats->total_aux_lost,1685			    stats->nr_events[PERF_RECORD_AUX]);1686	}1687 1688	if (session->tool->aux == perf_event__process_aux &&1689	    stats->total_aux_partial != 0) {1690		bool vmm_exclusive = false;1691 1692		(void)sysfs__read_bool("module/kvm_intel/parameters/vmm_exclusive",1693		                       &vmm_exclusive);1694 1695		ui__warning("AUX data had gaps in it %" PRIu64 " times out of %u!\n\n"1696		            "Are you running a KVM guest in the background?%s\n\n",1697			    stats->total_aux_partial,1698			    stats->nr_events[PERF_RECORD_AUX],1699			    vmm_exclusive ?1700			    "\nReloading kvm_intel module with vmm_exclusive=0\n"1701			    "will reduce the gaps to only guest's timeslices." :1702			    "");1703	}1704 1705	if (session->tool->aux == perf_event__process_aux &&1706	    stats->total_aux_collision != 0) {1707		ui__warning("AUX data detected collision  %" PRIu64 " times out of %u!\n\n",1708			    stats->total_aux_collision,1709			    stats->nr_events[PERF_RECORD_AUX]);1710	}1711 1712	if (stats->nr_unknown_events != 0) {1713		ui__warning("Found %u unknown events!\n\n"1714			    "Is this an older tool processing a perf.data "1715			    "file generated by a more recent tool?\n\n"1716			    "If that is not the case, consider "1717			    "reporting to linux-kernel@vger.kernel.org.\n\n",1718			    stats->nr_unknown_events);1719	}1720 1721	if (stats->nr_unknown_id != 0) {1722		ui__warning("%u samples with id not present in the header\n",1723			    stats->nr_unknown_id);1724	}1725 1726	if (stats->nr_invalid_chains != 0) {1727		ui__warning("Found invalid callchains!\n\n"1728			    "%u out of %u events were discarded for this reason.\n\n"1729			    "Consider reporting to linux-kernel@vger.kernel.org.\n\n",1730			    stats->nr_invalid_chains,1731			    stats->nr_events[PERF_RECORD_SAMPLE]);1732	}1733 1734	if (stats->nr_unprocessable_samples != 0) {1735		ui__warning("%u unprocessable samples recorded.\n"1736			    "Do you have a KVM guest running and not using 'perf kvm'?\n",1737			    stats->nr_unprocessable_samples);1738	}1739 1740	perf_session__warn_order(session);1741 1742	events_stats__auxtrace_error_warn(stats);1743 1744	if (stats->nr_proc_map_timeout != 0) {1745		ui__warning("%d map information files for pre-existing threads were\n"1746			    "not processed, if there are samples for addresses they\n"1747			    "will not be resolved, you may find out which are these\n"1748			    "threads by running with -v and redirecting the output\n"1749			    "to a file.\n"1750			    "The time limit to process proc map is too short?\n"1751			    "Increase it by --proc-map-timeout\n",1752			    stats->nr_proc_map_timeout);1753	}1754}1755 1756static int perf_session__flush_thread_stack(struct thread *thread,1757					    void *p __maybe_unused)1758{1759	return thread_stack__flush(thread);1760}1761 1762static int perf_session__flush_thread_stacks(struct perf_session *session)1763{1764	return machines__for_each_thread(&session->machines,1765					 perf_session__flush_thread_stack,1766					 NULL);1767}1768 1769volatile sig_atomic_t session_done;1770 1771static int __perf_session__process_decomp_events(struct perf_session *session);1772 1773static int __perf_session__process_pipe_events(struct perf_session *session)1774{1775	struct ordered_events *oe = &session->ordered_events;1776	const struct perf_tool *tool = session->tool;1777	struct ui_progress prog;1778	union perf_event *event;1779	uint32_t size, cur_size = 0;1780	void *buf = NULL;1781	s64 skip = 0;1782	u64 head;1783	ssize_t err;1784	void *p;1785	bool update_prog = false;1786 1787	/*1788	 * If it's from a file saving pipe data (by redirection), it would have1789	 * a file name other than "-".  Then we can get the total size and show1790	 * the progress.1791	 */1792	if (strcmp(session->data->path, "-") && session->data->file.size) {1793		ui_progress__init_size(&prog, session->data->file.size,1794				       "Processing events...");1795		update_prog = true;1796	}1797 1798	head = 0;1799	cur_size = sizeof(union perf_event);1800 1801	buf = malloc(cur_size);1802	if (!buf)1803		return -errno;1804	ordered_events__set_copy_on_queue(oe, true);1805more:1806	event = buf;1807	err = perf_data__read(session->data, event,1808			      sizeof(struct perf_event_header));1809	if (err <= 0) {1810		if (err == 0)1811			goto done;1812 1813		pr_err("failed to read event header\n");1814		goto out_err;1815	}1816 1817	if (session->header.needs_swap)1818		perf_event_header__bswap(&event->header);1819 1820	size = event->header.size;1821	if (size < sizeof(struct perf_event_header)) {1822		pr_err("bad event header size\n");1823		goto out_err;1824	}1825 1826	if (size > cur_size) {1827		void *new = realloc(buf, size);1828		if (!new) {1829			pr_err("failed to allocate memory to read event\n");1830			goto out_err;1831		}1832		buf = new;1833		cur_size = size;1834		event = buf;1835	}1836	p = event;1837	p += sizeof(struct perf_event_header);1838 1839	if (size - sizeof(struct perf_event_header)) {1840		err = perf_data__read(session->data, p,1841				      size - sizeof(struct perf_event_header));1842		if (err <= 0) {1843			if (err == 0) {1844				pr_err("unexpected end of event stream\n");1845				goto done;1846			}1847 1848			pr_err("failed to read event data\n");1849			goto out_err;1850		}1851	}1852 1853	if ((skip = perf_session__process_event(session, event, head, "pipe")) < 0) {1854		pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",1855		       head, event->header.size, event->header.type);1856		err = -EINVAL;1857		goto out_err;1858	}1859 1860	head += size;1861 1862	if (skip > 0)1863		head += skip;1864 1865	err = __perf_session__process_decomp_events(session);1866	if (err)1867		goto out_err;1868 1869	if (update_prog)1870		ui_progress__update(&prog, size);1871 1872	if (!session_done())1873		goto more;1874done:1875	/* do the final flush for ordered samples */1876	err = ordered_events__flush(oe, OE_FLUSH__FINAL);1877	if (err)1878		goto out_err;1879	err = auxtrace__flush_events(session, tool);1880	if (err)1881		goto out_err;1882	err = perf_session__flush_thread_stacks(session);1883out_err:1884	free(buf);1885	if (update_prog)1886		ui_progress__finish();1887	if (!tool->no_warn)1888		perf_session__warn_about_errors(session);1889	ordered_events__free(&session->ordered_events);1890	auxtrace__free_events(session);1891	return err;1892}1893 1894static union perf_event *1895prefetch_event(char *buf, u64 head, size_t mmap_size,1896	       bool needs_swap, union perf_event *error)1897{1898	union perf_event *event;1899	u16 event_size;1900 1901	/*1902	 * Ensure we have enough space remaining to read1903	 * the size of the event in the headers.1904	 */1905	if (head + sizeof(event->header) > mmap_size)1906		return NULL;1907 1908	event = (union perf_event *)(buf + head);1909	if (needs_swap)1910		perf_event_header__bswap(&event->header);1911 1912	event_size = event->header.size;1913	if (head + event_size <= mmap_size)1914		return event;1915 1916	/* We're not fetching the event so swap back again */1917	if (needs_swap)1918		perf_event_header__bswap(&event->header);1919 1920	/* Check if the event fits into the next mmapped buf. */1921	if (event_size <= mmap_size - head % page_size) {1922		/* Remap buf and fetch again. */1923		return NULL;1924	}1925 1926	/* Invalid input. Event size should never exceed mmap_size. */1927	pr_debug("%s: head=%#" PRIx64 " event->header.size=%#x, mmap_size=%#zx:"1928		 " fuzzed or compressed perf.data?\n", __func__, head, event_size, mmap_size);1929 1930	return error;1931}1932 1933static union perf_event *1934fetch_mmaped_event(u64 head, size_t mmap_size, char *buf, bool needs_swap)1935{1936	return prefetch_event(buf, head, mmap_size, needs_swap, ERR_PTR(-EINVAL));1937}1938 1939static union perf_event *1940fetch_decomp_event(u64 head, size_t mmap_size, char *buf, bool needs_swap)1941{1942	return prefetch_event(buf, head, mmap_size, needs_swap, NULL);1943}1944 1945static int __perf_session__process_decomp_events(struct perf_session *session)1946{1947	s64 skip;1948	u64 size;1949	struct decomp *decomp = session->active_decomp->decomp_last;1950 1951	if (!decomp)1952		return 0;1953 1954	while (decomp->head < decomp->size && !session_done()) {1955		union perf_event *event = fetch_decomp_event(decomp->head, decomp->size, decomp->data,1956							     session->header.needs_swap);1957 1958		if (!event)1959			break;1960 1961		size = event->header.size;1962 1963		if (size < sizeof(struct perf_event_header) ||1964		    (skip = perf_session__process_event(session, event, decomp->file_pos,1965							decomp->file_path)) < 0) {1966			pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",1967				decomp->file_pos + decomp->head, event->header.size, event->header.type);1968			return -EINVAL;1969		}1970 1971		if (skip)1972			size += skip;1973 1974		decomp->head += size;1975	}1976 1977	return 0;1978}1979 1980/*1981 * On 64bit we can mmap the data file in one go. No need for tiny mmap1982 * slices. On 32bit we use 32MB.1983 */1984#if BITS_PER_LONG == 641985#define MMAP_SIZE ULLONG_MAX1986#define NUM_MMAPS 11987#else1988#define MMAP_SIZE (32 * 1024 * 1024ULL)1989#define NUM_MMAPS 1281990#endif1991 1992struct reader;1993 1994typedef s64 (*reader_cb_t)(struct perf_session *session,1995			   union perf_event *event,1996			   u64 file_offset,1997			   const char *file_path);1998 1999struct reader {2000	int		 fd;2001	const char	 *path;2002	u64		 data_size;2003	u64		 data_offset;2004	reader_cb_t	 process;2005	bool		 in_place_update;2006	char		 *mmaps[NUM_MMAPS];2007	size_t		 mmap_size;2008	int		 mmap_idx;2009	char		 *mmap_cur;2010	u64		 file_pos;2011	u64		 file_offset;2012	u64		 head;2013	u64		 size;2014	bool		 done;2015	struct zstd_data   zstd_data;2016	struct decomp_data decomp_data;2017};2018 2019static int2020reader__init(struct reader *rd, bool *one_mmap)2021{2022	u64 data_size = rd->data_size;2023	char **mmaps = rd->mmaps;2024 2025	rd->head = rd->data_offset;2026	data_size += rd->data_offset;2027 2028	rd->mmap_size = MMAP_SIZE;2029	if (rd->mmap_size > data_size) {2030		rd->mmap_size = data_size;2031		if (one_mmap)2032			*one_mmap = true;2033	}2034 2035	memset(mmaps, 0, sizeof(rd->mmaps));2036 2037	if (zstd_init(&rd->zstd_data, 0))2038		return -1;2039	rd->decomp_data.zstd_decomp = &rd->zstd_data;2040 2041	return 0;2042}2043 2044static void2045reader__release_decomp(struct reader *rd)2046{2047	perf_decomp__release_events(rd->decomp_data.decomp);2048	zstd_fini(&rd->zstd_data);2049}2050 2051static int2052reader__mmap(struct reader *rd, struct perf_session *session)2053{2054	int mmap_prot, mmap_flags;2055	char *buf, **mmaps = rd->mmaps;2056	u64 page_offset;2057 2058	mmap_prot  = PROT_READ;2059	mmap_flags = MAP_SHARED;2060 2061	if (rd->in_place_update) {2062		mmap_prot  |= PROT_WRITE;2063	} else if (session->header.needs_swap) {2064		mmap_prot  |= PROT_WRITE;2065		mmap_flags = MAP_PRIVATE;2066	}2067 2068	if (mmaps[rd->mmap_idx]) {2069		munmap(mmaps[rd->mmap_idx], rd->mmap_size);2070		mmaps[rd->mmap_idx] = NULL;2071	}2072 2073	page_offset = page_size * (rd->head / page_size);2074	rd->file_offset += page_offset;2075	rd->head -= page_offset;2076 2077	buf = mmap(NULL, rd->mmap_size, mmap_prot, mmap_flags, rd->fd,2078		   rd->file_offset);2079	if (buf == MAP_FAILED) {2080		pr_err("failed to mmap file\n");2081		return -errno;2082	}2083	mmaps[rd->mmap_idx] = rd->mmap_cur = buf;2084	rd->mmap_idx = (rd->mmap_idx + 1) & (ARRAY_SIZE(rd->mmaps) - 1);2085	rd->file_pos = rd->file_offset + rd->head;2086	if (session->one_mmap) {2087		session->one_mmap_addr = buf;2088		session->one_mmap_offset = rd->file_offset;2089	}2090 2091	return 0;2092}2093 2094enum {2095	READER_OK,2096	READER_NODATA,2097};2098 2099static int2100reader__read_event(struct reader *rd, struct perf_session *session,2101		   struct ui_progress *prog)2102{2103	u64 size;2104	int err = READER_OK;2105	union perf_event *event;2106	s64 skip;2107 2108	event = fetch_mmaped_event(rd->head, rd->mmap_size, rd->mmap_cur,2109				   session->header.needs_swap);2110	if (IS_ERR(event))2111		return PTR_ERR(event);2112 2113	if (!event)2114		return READER_NODATA;2115 2116	size = event->header.size;2117 2118	skip = -EINVAL;2119 2120	if (size < sizeof(struct perf_event_header) ||2121	    (skip = rd->process(session, event, rd->file_pos, rd->path)) < 0) {2122		pr_err("%#" PRIx64 " [%#x]: failed to process type: %d [%s]\n",2123		       rd->file_offset + rd->head, event->header.size,2124		       event->header.type, strerror(-skip));2125		err = skip;2126		goto out;2127	}2128 2129	if (skip)2130		size += skip;2131 2132	rd->size += size;2133	rd->head += size;2134	rd->file_pos += size;2135 2136	err = __perf_session__process_decomp_events(session);2137	if (err)2138		goto out;2139 2140	ui_progress__update(prog, size);2141 2142out:2143	return err;2144}2145 2146static inline bool2147reader__eof(struct reader *rd)2148{2149	return (rd->file_pos >= rd->data_size + rd->data_offset);2150}2151 2152static int2153reader__process_events(struct reader *rd, struct perf_session *session,2154		       struct ui_progress *prog)2155{2156	int err;2157 2158	err = reader__init(rd, &session->one_mmap);2159	if (err)2160		goto out;2161 2162	session->active_decomp = &rd->decomp_data;2163 2164remap:2165	err = reader__mmap(rd, session);2166	if (err)2167		goto out;2168 2169more:2170	err = reader__read_event(rd, session, prog);2171	if (err < 0)2172		goto out;2173	else if (err == READER_NODATA)2174		goto remap;2175 2176	if (session_done())2177		goto out;2178 2179	if (!reader__eof(rd))2180		goto more;2181 2182out:2183	session->active_decomp = &session->decomp_data;2184	return err;2185}2186 2187static s64 process_simple(struct perf_session *session,2188			  union perf_event *event,2189			  u64 file_offset,2190			  const char *file_path)2191{2192	return perf_session__process_event(session, event, file_offset, file_path);2193}2194 2195static int __perf_session__process_events(struct perf_session *session)2196{2197	struct reader rd = {2198		.fd		= perf_data__fd(session->data),2199		.path		= session->data->file.path,2200		.data_size	= session->header.data_size,2201		.data_offset	= session->header.data_offset,2202		.process	= process_simple,2203		.in_place_update = session->data->in_place_update,2204	};2205	struct ordered_events *oe = &session->ordered_events;2206	const struct perf_tool *tool = session->tool;2207	struct ui_progress prog;2208	int err;2209 2210	if (rd.data_size == 0)2211		return -1;2212 2213	ui_progress__init_size(&prog, rd.data_size, "Processing events...");2214 2215	err = reader__process_events(&rd, session, &prog);2216	if (err)2217		goto out_err;2218	/* do the final flush for ordered samples */2219	err = ordered_events__flush(oe, OE_FLUSH__FINAL);2220	if (err)2221		goto out_err;2222	err = auxtrace__flush_events(session, tool);2223	if (err)2224		goto out_err;2225	err = perf_session__flush_thread_stacks(session);2226out_err:2227	ui_progress__finish();2228	if (!tool->no_warn)2229		perf_session__warn_about_errors(session);2230	/*2231	 * We may switching perf.data output, make ordered_events2232	 * reusable.2233	 */2234	ordered_events__reinit(&session->ordered_events);2235	auxtrace__free_events(session);2236	reader__release_decomp(&rd);2237	session->one_mmap = false;2238	return err;2239}2240 2241/*2242 * Processing 2 MB of data from each reader in sequence,2243 * because that's the way the ordered events sorting works2244 * most efficiently.2245 */2246#define READER_MAX_SIZE (2 * 1024 * 1024)2247 2248/*2249 * This function reads, merge and process directory data.2250 * It assumens the version 1 of directory data, where each2251 * data file holds per-cpu data, already sorted by kernel.2252 */2253static int __perf_session__process_dir_events(struct perf_session *session)2254{2255	struct perf_data *data = session->data;2256	const struct perf_tool *tool = session->tool;2257	int i, ret, readers, nr_readers;2258	struct ui_progress prog;2259	u64 total_size = perf_data__size(session->data);2260	struct reader *rd;2261 2262	ui_progress__init_size(&prog, total_size, "Processing events...");2263 2264	nr_readers = 1;2265	for (i = 0; i < data->dir.nr; i++) {2266		if (data->dir.files[i].size)2267			nr_readers++;2268	}2269 2270	rd = zalloc(nr_readers * sizeof(struct reader));2271	if (!rd)2272		return -ENOMEM;2273 2274	rd[0] = (struct reader) {2275		.fd		 = perf_data__fd(session->data),2276		.path		 = session->data->file.path,2277		.data_size	 = session->header.data_size,2278		.data_offset	 = session->header.data_offset,2279		.process	 = process_simple,2280		.in_place_update = session->data->in_place_update,2281	};2282	ret = reader__init(&rd[0], NULL);2283	if (ret)2284		goto out_err;2285	ret = reader__mmap(&rd[0], session);2286	if (ret)2287		goto out_err;2288	readers = 1;2289 2290	for (i = 0; i < data->dir.nr; i++) {2291		if (!data->dir.files[i].size)2292			continue;2293		rd[readers] = (struct reader) {2294			.fd		 = data->dir.files[i].fd,2295			.path		 = data->dir.files[i].path,2296			.data_size	 = data->dir.files[i].size,2297			.data_offset	 = 0,2298			.process	 = process_simple,2299			.in_place_update = session->data->in_place_update,2300		};2301		ret = reader__init(&rd[readers], NULL);2302		if (ret)2303			goto out_err;2304		ret = reader__mmap(&rd[readers], session);2305		if (ret)2306			goto out_err;2307		readers++;2308	}2309 2310	i = 0;2311	while (readers) {2312		if (session_done())2313			break;2314 2315		if (rd[i].done) {2316			i = (i + 1) % nr_readers;2317			continue;2318		}2319		if (reader__eof(&rd[i])) {2320			rd[i].done = true;2321			readers--;2322			continue;2323		}2324 2325		session->active_decomp = &rd[i].decomp_data;2326		ret = reader__read_event(&rd[i], session, &prog);2327		if (ret < 0) {2328			goto out_err;2329		} else if (ret == READER_NODATA) {2330			ret = reader__mmap(&rd[i], session);2331			if (ret)2332				goto out_err;2333		}2334 2335		if (rd[i].size >= READER_MAX_SIZE) {2336			rd[i].size = 0;2337			i = (i + 1) % nr_readers;2338		}2339	}2340 2341	ret = ordered_events__flush(&session->ordered_events, OE_FLUSH__FINAL);2342	if (ret)2343		goto out_err;2344 2345	ret = perf_session__flush_thread_stacks(session);2346out_err:2347	ui_progress__finish();2348 2349	if (!tool->no_warn)2350		perf_session__warn_about_errors(session);2351 2352	/*2353	 * We may switching perf.data output, make ordered_events2354	 * reusable.2355	 */2356	ordered_events__reinit(&session->ordered_events);2357 2358	session->one_mmap = false;2359 2360	session->active_decomp = &session->decomp_data;2361	for (i = 0; i < nr_readers; i++)2362		reader__release_decomp(&rd[i]);2363	zfree(&rd);2364 2365	return ret;2366}2367 2368int perf_session__process_events(struct perf_session *session)2369{2370	if (perf_session__register_idle_thread(session) < 0)2371		return -ENOMEM;2372 2373	if (perf_data__is_pipe(session->data))2374		return __perf_session__process_pipe_events(session);2375 2376	if (perf_data__is_dir(session->data) && session->data->dir.nr)2377		return __perf_session__process_dir_events(session);2378 2379	return __perf_session__process_events(session);2380}2381 2382bool perf_session__has_traces(struct perf_session *session, const char *msg)2383{2384	struct evsel *evsel;2385 2386	evlist__for_each_entry(session->evlist, evsel) {2387		if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT)2388			return true;2389	}2390 2391	pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);2392	return false;2393}2394 2395int map__set_kallsyms_ref_reloc_sym(struct map *map, const char *symbol_name, u64 addr)2396{2397	char *bracket;2398	struct ref_reloc_sym *ref;2399	struct kmap *kmap;2400 2401	ref = zalloc(sizeof(struct ref_reloc_sym));2402	if (ref == NULL)2403		return -ENOMEM;2404 2405	ref->name = strdup(symbol_name);2406	if (ref->name == NULL) {2407		free(ref);2408		return -ENOMEM;2409	}2410 2411	bracket = strchr(ref->name, ']');2412	if (bracket)2413		*bracket = '\0';2414 2415	ref->addr = addr;2416 2417	kmap = map__kmap(map);2418	if (kmap)2419		kmap->ref_reloc_sym = ref;2420 2421	return 0;2422}2423 2424size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp)2425{2426	return machines__fprintf_dsos(&session->machines, fp);2427}2428 2429size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,2430					  bool (skip)(struct dso *dso, int parm), int parm)2431{2432	return machines__fprintf_dsos_buildid(&session->machines, fp, skip, parm);2433}2434 2435size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)2436{2437	size_t ret;2438	const char *msg = "";2439 2440	if (perf_header__has_feat(&session->header, HEADER_AUXTRACE))2441		msg = " (excludes AUX area (e.g. instruction trace) decoded / synthesized events)";2442 2443	ret = fprintf(fp, "\nAggregated stats:%s\n", msg);2444 2445	ret += events_stats__fprintf(&session->evlist->stats, fp);2446	return ret;2447}2448 2449size_t perf_session__fprintf(struct perf_session *session, FILE *fp)2450{2451	/*2452	 * FIXME: Here we have to actually print all the machines in this2453	 * session, not just the host...2454	 */2455	return machine__fprintf(&session->machines.host, fp);2456}2457 2458void perf_session__dump_kmaps(struct perf_session *session)2459{2460	int save_verbose = verbose;2461 2462	fflush(stdout);2463	fprintf(stderr, "Kernel and module maps:\n");2464	verbose = 0; /* Suppress verbose to print a summary only */2465	maps__fprintf(machine__kernel_maps(&session->machines.host), stderr);2466	verbose = save_verbose;2467}2468 2469struct evsel *perf_session__find_first_evtype(struct perf_session *session,2470					      unsigned int type)2471{2472	struct evsel *pos;2473 2474	evlist__for_each_entry(session->evlist, pos) {2475		if (pos->core.attr.type == type)2476			return pos;2477	}2478	return NULL;2479}2480 2481int perf_session__cpu_bitmap(struct perf_session *session,2482			     const char *cpu_list, unsigned long *cpu_bitmap)2483{2484	int i, err = -1;2485	struct perf_cpu_map *map;2486	int nr_cpus = min(session->header.env.nr_cpus_avail, MAX_NR_CPUS);2487	struct perf_cpu cpu;2488 2489	for (i = 0; i < PERF_TYPE_MAX; ++i) {2490		struct evsel *evsel;2491 2492		evsel = perf_session__find_first_evtype(session, i);2493		if (!evsel)2494			continue;2495 2496		if (!(evsel->core.attr.sample_type & PERF_SAMPLE_CPU)) {2497			pr_err("File does not contain CPU events. "2498			       "Remove -C option to proceed.\n");2499			return -1;2500		}2501	}2502 2503	map = perf_cpu_map__new(cpu_list);2504	if (map == NULL) {2505		pr_err("Invalid cpu_list\n");2506		return -1;2507	}2508 2509	perf_cpu_map__for_each_cpu(cpu, i, map) {2510		if (cpu.cpu >= nr_cpus) {2511			pr_err("Requested CPU %d too large. "2512			       "Consider raising MAX_NR_CPUS\n", cpu.cpu);2513			goto out_delete_map;2514		}2515 2516		__set_bit(cpu.cpu, cpu_bitmap);2517	}2518 2519	err = 0;2520 2521out_delete_map:2522	perf_cpu_map__put(map);2523	return err;2524}2525 2526void perf_session__fprintf_info(struct perf_session *session, FILE *fp,2527				bool full)2528{2529	if (session == NULL || fp == NULL)2530		return;2531 2532	fprintf(fp, "# ========\n");2533	perf_header__fprintf_info(session, fp, full);2534	fprintf(fp, "# ========\n#\n");2535}2536 2537static int perf_session__register_guest(struct perf_session *session, pid_t machine_pid)2538{2539	struct machine *machine = machines__findnew(&session->machines, machine_pid);2540	struct thread *thread;2541 2542	if (!machine)2543		return -ENOMEM;2544 2545	machine->single_address_space = session->machines.host.single_address_space;2546 2547	thread = machine__idle_thread(machine);2548	if (!thread)2549		return -ENOMEM;2550	thread__put(thread);2551 2552	machine->kallsyms_filename = perf_data__guest_kallsyms_name(session->data, machine_pid);2553 2554	return 0;2555}2556 2557static int perf_session__set_guest_cpu(struct perf_session *session, pid_t pid,2558				       pid_t tid, int guest_cpu)2559{2560	struct machine *machine = &session->machines.host;2561	struct thread *thread = machine__findnew_thread(machine, pid, tid);2562 2563	if (!thread)2564		return -ENOMEM;2565	thread__set_guest_cpu(thread, guest_cpu);2566	thread__put(thread);2567 2568	return 0;2569}2570 2571int perf_event__process_id_index(struct perf_session *session,2572				 union perf_event *event)2573{2574	struct evlist *evlist = session->evlist;2575	struct perf_record_id_index *ie = &event->id_index;2576	size_t sz = ie->header.size - sizeof(*ie);2577	size_t i, nr, max_nr;2578	size_t e1_sz = sizeof(struct id_index_entry);2579	size_t e2_sz = sizeof(struct id_index_entry_2);2580	size_t etot_sz = e1_sz + e2_sz;2581	struct id_index_entry_2 *e2;2582	pid_t last_pid = 0;2583 2584	max_nr = sz / e1_sz;2585	nr = ie->nr;2586	if (nr > max_nr) {2587		printf("Too big: nr %zu max_nr %zu\n", nr, max_nr);2588		return -EINVAL;2589	}2590 2591	if (sz >= nr * etot_sz) {2592		max_nr = sz / etot_sz;2593		if (nr > max_nr) {2594			printf("Too big2: nr %zu max_nr %zu\n", nr, max_nr);2595			return -EINVAL;2596		}2597		e2 = (void *)ie + sizeof(*ie) + nr * e1_sz;2598	} else {2599		e2 = NULL;2600	}2601 2602	if (dump_trace)2603		fprintf(stdout, " nr: %zu\n", nr);2604 2605	for (i = 0; i < nr; i++, (e2 ? e2++ : 0)) {2606		struct id_index_entry *e = &ie->entries[i];2607		struct perf_sample_id *sid;2608		int ret;2609 2610		if (dump_trace) {2611			fprintf(stdout,	" ... id: %"PRI_lu64, e->id);2612			fprintf(stdout,	"  idx: %"PRI_lu64, e->idx);2613			fprintf(stdout,	"  cpu: %"PRI_ld64, e->cpu);2614			fprintf(stdout, "  tid: %"PRI_ld64, e->tid);2615			if (e2) {2616				fprintf(stdout, "  machine_pid: %"PRI_ld64, e2->machine_pid);2617				fprintf(stdout, "  vcpu: %"PRI_lu64"\n", e2->vcpu);2618			} else {2619				fprintf(stdout, "\n");2620			}2621		}2622 2623		sid = evlist__id2sid(evlist, e->id);2624		if (!sid)2625			return -ENOENT;2626 2627		sid->idx = e->idx;2628		sid->cpu.cpu = e->cpu;2629		sid->tid = e->tid;2630 2631		if (!e2)2632			continue;2633 2634		sid->machine_pid = e2->machine_pid;2635		sid->vcpu.cpu = e2->vcpu;2636 2637		if (!sid->machine_pid)2638			continue;2639 2640		if (sid->machine_pid != last_pid) {2641			ret = perf_session__register_guest(session, sid->machine_pid);2642			if (ret)2643				return ret;2644			last_pid = sid->machine_pid;2645			perf_guest = true;2646		}2647 2648		ret = perf_session__set_guest_cpu(session, sid->machine_pid, e->tid, e2->vcpu);2649		if (ret)2650			return ret;2651	}2652	return 0;2653}2654 2655int perf_session__dsos_hit_all(struct perf_session *session)2656{2657	struct rb_node *nd;2658	int err;2659 2660	err = machine__hit_all_dsos(&session->machines.host);2661	if (err)2662		return err;2663 2664	for (nd = rb_first_cached(&session->machines.guests); nd;2665	     nd = rb_next(nd)) {2666		struct machine *pos = rb_entry(nd, struct machine, rb_node);2667 2668		err = machine__hit_all_dsos(pos);2669		if (err)2670			return err;2671	}2672 2673	return 0;2674}2675