File Index
Files and directories
Sign in
FILE

synthetic-events.c

File preview with syntax highlighting.

linux-6.19.14/tools/perf/util/synthetic-events.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2
   3#include "util/cgroup.h"
   4#include "util/data.h"
   5#include "util/debug.h"
   6#include "util/dso.h"
   7#include "util/event.h"
   8#include "util/evlist.h"
   9#include "util/machine.h"
  10#include "util/map.h"
  11#include "util/map_symbol.h"
  12#include "util/branch.h"
  13#include "util/memswap.h"
  14#include "util/namespaces.h"
  15#include "util/session.h"
  16#include "util/stat.h"
  17#include "util/symbol.h"
  18#include "util/synthetic-events.h"
  19#include "util/target.h"
  20#include "util/time-utils.h"
  21#include <linux/bitops.h>
  22#include <linux/kernel.h>
  23#include <linux/string.h>
  24#include <linux/zalloc.h>
  25#include <linux/perf_event.h>
  26#include <asm/bug.h>
  27#include <perf/evsel.h>
  28#include <perf/cpumap.h>
  29#include <internal/lib.h> // page_size
  30#include <internal/threadmap.h>
  31#include <perf/threadmap.h>
  32#include <symbol/kallsyms.h>
  33#include <dirent.h>
  34#include <errno.h>
  35#include <inttypes.h>
  36#include <stdio.h>
  37#include <string.h>
  38#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
  39#include <api/fs/fs.h>
  40#include <api/io.h>
  41#include <api/io_dir.h>
  42#include <sys/types.h>
  43#include <sys/stat.h>
  44#include <fcntl.h>
  45#include <unistd.h>
  46
  47#define DEFAULT_PROC_MAP_PARSE_TIMEOUT 500
  48
  49unsigned int proc_map_timeout = DEFAULT_PROC_MAP_PARSE_TIMEOUT;
  50
  51int perf_tool__process_synth_event(const struct perf_tool *tool,
  52				   union perf_event *event,
  53				   struct machine *machine,
  54				   perf_event__handler_t process)
  55{
  56	struct perf_sample synth_sample = {
  57		.pid	   = -1,
  58		.tid	   = -1,
  59		.time	   = -1,
  60		.stream_id = -1,
  61		.cpu	   = -1,
  62		.period	   = 1,
  63		.cpumode   = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK,
  64	};
  65
  66	return process(tool, event, &synth_sample, machine);
  67};
  68
  69/*
  70 * Assumes that the first 4095 bytes of /proc/pid/stat contains
  71 * the comm, tgid and ppid.
  72 */
  73static int perf_event__get_comm_ids(pid_t pid, pid_t tid, char *comm, size_t len,
  74				    pid_t *tgid, pid_t *ppid, bool *kernel)
  75{
  76	char bf[4096];
  77	int fd;
  78	size_t size = 0;
  79	ssize_t n;
  80	char *name, *tgids, *ppids, *vmpeak, *threads;
  81
  82	*tgid = -1;
  83	*ppid = -1;
  84
  85	if (pid)
  86		snprintf(bf, sizeof(bf), "/proc/%d/task/%d/status", pid, tid);
  87	else
  88		snprintf(bf, sizeof(bf), "/proc/%d/status", tid);
  89
  90	fd = open(bf, O_RDONLY);
  91	if (fd < 0) {
  92		pr_debug("couldn't open %s\n", bf);
  93		return -1;
  94	}
  95
  96	n = read(fd, bf, sizeof(bf) - 1);
  97	close(fd);
  98	if (n <= 0) {
  99		pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
 100			   tid);
 101		return -1;
 102	}
 103	bf[n] = '\0';
 104
 105	name = strstr(bf, "Name:");
 106	tgids = strstr(name ?: bf, "Tgid:");
 107	ppids = strstr(tgids ?: bf, "PPid:");
 108	vmpeak = strstr(ppids ?: bf, "VmPeak:");
 109
 110	if (vmpeak)
 111		threads = NULL;
 112	else
 113		threads = strstr(ppids ?: bf, "Threads:");
 114
 115	if (name) {
 116		char *nl;
 117
 118		name = skip_spaces(name + 5);  /* strlen("Name:") */
 119		nl = strchr(name, '\n');
 120		if (nl)
 121			*nl = '\0';
 122
 123		size = strlen(name);
 124		if (size >= len)
 125			size = len - 1;
 126		memcpy(comm, name, size);
 127		comm[size] = '\0';
 128	} else {
 129		pr_debug("Name: string not found for pid %d\n", tid);
 130	}
 131
 132	if (tgids) {
 133		tgids += 5;  /* strlen("Tgid:") */
 134		*tgid = atoi(tgids);
 135	} else {
 136		pr_debug("Tgid: string not found for pid %d\n", tid);
 137	}
 138
 139	if (ppids) {
 140		ppids += 5;  /* strlen("PPid:") */
 141		*ppid = atoi(ppids);
 142	} else {
 143		pr_debug("PPid: string not found for pid %d\n", tid);
 144	}
 145
 146	if (!vmpeak && threads)
 147		*kernel = true;
 148	else
 149		*kernel = false;
 150
 151	return 0;
 152}
 153
 154static int perf_event__prepare_comm(union perf_event *event, pid_t pid, pid_t tid,
 155				    struct machine *machine,
 156				    pid_t *tgid, pid_t *ppid, bool *kernel)
 157{
 158	size_t size;
 159
 160	*ppid = -1;
 161
 162	memset(&event->comm, 0, sizeof(event->comm));
 163
 164	if (machine__is_host(machine)) {
 165		if (perf_event__get_comm_ids(pid, tid, event->comm.comm,
 166					     sizeof(event->comm.comm),
 167					     tgid, ppid, kernel) != 0) {
 168			return -1;
 169		}
 170	} else {
 171		*tgid = machine->pid;
 172	}
 173
 174	if (*tgid < 0)
 175		return -1;
 176
 177	event->comm.pid = *tgid;
 178	event->comm.header.type = PERF_RECORD_COMM;
 179
 180	size = strlen(event->comm.comm) + 1;
 181	size = PERF_ALIGN(size, sizeof(u64));
 182	memset(event->comm.comm + size, 0, machine->id_hdr_size);
 183	event->comm.header.size = (sizeof(event->comm) -
 184				(sizeof(event->comm.comm) - size) +
 185				machine->id_hdr_size);
 186	event->comm.tid = tid;
 187
 188	return 0;
 189}
 190
 191pid_t perf_event__synthesize_comm(const struct perf_tool *tool,
 192					 union perf_event *event, pid_t pid,
 193					 perf_event__handler_t process,
 194					 struct machine *machine)
 195{
 196	pid_t tgid, ppid;
 197	bool kernel_thread;
 198
 199	if (perf_event__prepare_comm(event, 0, pid, machine, &tgid, &ppid,
 200				     &kernel_thread) != 0)
 201		return -1;
 202
 203	if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
 204		return -1;
 205
 206	return tgid;
 207}
 208
 209static void perf_event__get_ns_link_info(pid_t pid, const char *ns,
 210					 struct perf_ns_link_info *ns_link_info)
 211{
 212	struct stat64 st;
 213	char proc_ns[128];
 214
 215	sprintf(proc_ns, "/proc/%u/ns/%s", pid, ns);
 216	if (stat64(proc_ns, &st) == 0) {
 217		ns_link_info->dev = st.st_dev;
 218		ns_link_info->ino = st.st_ino;
 219	}
 220}
 221
 222int perf_event__synthesize_namespaces(const struct perf_tool *tool,
 223				      union perf_event *event,
 224				      pid_t pid, pid_t tgid,
 225				      perf_event__handler_t process,
 226				      struct machine *machine)
 227{
 228	u32 idx;
 229	struct perf_ns_link_info *ns_link_info;
 230
 231	if (!tool || !tool->namespace_events)
 232		return 0;
 233
 234	memset(&event->namespaces, 0, (sizeof(event->namespaces) +
 235	       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
 236	       machine->id_hdr_size));
 237
 238	event->namespaces.pid = tgid;
 239	event->namespaces.tid = pid;
 240
 241	event->namespaces.nr_namespaces = NR_NAMESPACES;
 242
 243	ns_link_info = event->namespaces.link_info;
 244
 245	for (idx = 0; idx < event->namespaces.nr_namespaces; idx++)
 246		perf_event__get_ns_link_info(pid, perf_ns__name(idx),
 247					     &ns_link_info[idx]);
 248
 249	event->namespaces.header.type = PERF_RECORD_NAMESPACES;
 250
 251	event->namespaces.header.size = (sizeof(event->namespaces) +
 252			(NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
 253			machine->id_hdr_size);
 254
 255	if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
 256		return -1;
 257
 258	return 0;
 259}
 260
 261static int perf_event__synthesize_fork(const struct perf_tool *tool,
 262				       union perf_event *event,
 263				       pid_t pid, pid_t tgid, pid_t ppid,
 264				       perf_event__handler_t process,
 265				       struct machine *machine)
 266{
 267	memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
 268
 269	/*
 270	 * for main thread set parent to ppid from status file. For other
 271	 * threads set parent pid to main thread. ie., assume main thread
 272	 * spawns all threads in a process
 273	*/
 274	if (tgid == pid) {
 275		event->fork.ppid = ppid;
 276		event->fork.ptid = ppid;
 277	} else {
 278		event->fork.ppid = tgid;
 279		event->fork.ptid = tgid;
 280	}
 281	event->fork.pid  = tgid;
 282	event->fork.tid  = pid;
 283	event->fork.header.type = PERF_RECORD_FORK;
 284	event->fork.header.misc = PERF_RECORD_MISC_FORK_EXEC;
 285
 286	event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);
 287
 288	if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
 289		return -1;
 290
 291	return 0;
 292}
 293
 294static bool read_proc_maps_line(struct io *io, __u64 *start, __u64 *end,
 295				u32 *prot, u32 *flags, __u64 *offset,
 296				u32 *maj, u32 *min,
 297				__u64 *inode,
 298				ssize_t pathname_size, char *pathname)
 299{
 300	__u64 temp;
 301	int ch;
 302	char *start_pathname = pathname;
 303
 304	if (io__get_hex(io, start) != '-')
 305		return false;
 306	if (io__get_hex(io, end) != ' ')
 307		return false;
 308
 309	/* map protection and flags bits */
 310	*prot = 0;
 311	ch = io__get_char(io);
 312	if (ch == 'r')
 313		*prot |= PROT_READ;
 314	else if (ch != '-')
 315		return false;
 316	ch = io__get_char(io);
 317	if (ch == 'w')
 318		*prot |= PROT_WRITE;
 319	else if (ch != '-')
 320		return false;
 321	ch = io__get_char(io);
 322	if (ch == 'x')
 323		*prot |= PROT_EXEC;
 324	else if (ch != '-')
 325		return false;
 326	ch = io__get_char(io);
 327	if (ch == 's')
 328		*flags = MAP_SHARED;
 329	else if (ch == 'p')
 330		*flags = MAP_PRIVATE;
 331	else
 332		return false;
 333	if (io__get_char(io) != ' ')
 334		return false;
 335
 336	if (io__get_hex(io, offset) != ' ')
 337		return false;
 338
 339	if (io__get_hex(io, &temp) != ':')
 340		return false;
 341	*maj = temp;
 342	if (io__get_hex(io, &temp) != ' ')
 343		return false;
 344	*min = temp;
 345
 346	ch = io__get_dec(io, inode);
 347	if (ch != ' ') {
 348		*pathname = '\0';
 349		return ch == '\n';
 350	}
 351	do {
 352		ch = io__get_char(io);
 353	} while (ch == ' ');
 354	while (true) {
 355		if (ch < 0)
 356			return false;
 357		if (ch == '\0' || ch == '\n' ||
 358		    (pathname + 1 - start_pathname) >= pathname_size) {
 359			*pathname = '\0';
 360			return true;
 361		}
 362		*pathname++ = ch;
 363		ch = io__get_char(io);
 364	}
 365}
 366
 367static void perf_record_mmap2__read_build_id(struct perf_record_mmap2 *event,
 368					     struct machine *machine,
 369					     bool is_kernel)
 370{
 371	struct build_id bid = { .size = 0, };
 372	struct nsinfo *nsi;
 373	struct nscookie nc;
 374	struct dso *dso = NULL;
 375	struct dso_id dso_id = dso_id_empty;
 376	int rc;
 377
 378	if (is_kernel) {
 379		rc = sysfs__read_build_id("/sys/kernel/notes", &bid);
 380		goto out;
 381	}
 382
 383	if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) {
 384		build_id__init(&dso_id.build_id, event->build_id, event->build_id_size);
 385	} else {
 386		dso_id.maj = event->maj;
 387		dso_id.min = event->min;
 388		dso_id.ino = event->ino;
 389		dso_id.ino_generation = event->ino_generation;
 390		dso_id.mmap2_valid = true;
 391		dso_id.mmap2_ino_generation_valid = true;
 392	}
 393
 394	dso = dsos__findnew_id(&machine->dsos, event->filename, &dso_id);
 395	if (dso && dso__has_build_id(dso)) {
 396		bid = *dso__bid(dso);
 397		rc = 0;
 398		goto out;
 399	}
 400
 401	nsi = nsinfo__new(event->pid);
 402	nsinfo__mountns_enter(nsi, &nc);
 403
 404	rc = filename__read_build_id(event->filename, &bid) > 0 ? 0 : -1;
 405
 406	nsinfo__mountns_exit(&nc);
 407	nsinfo__put(nsi);
 408
 409out:
 410	if (rc == 0) {
 411		memcpy(event->build_id, bid.data, sizeof(bid.data));
 412		event->build_id_size = (u8) bid.size;
 413		event->header.misc |= PERF_RECORD_MISC_MMAP_BUILD_ID;
 414		event->__reserved_1 = 0;
 415		event->__reserved_2 = 0;
 416
 417		if (dso && !dso__has_build_id(dso))
 418			dso__set_build_id(dso, &bid);
 419	} else {
 420		if (event->filename[0] == '/') {
 421			pr_debug2("Failed to read build ID for %s\n",
 422				  event->filename);
 423		}
 424	}
 425	dso__put(dso);
 426}
 427
 428int perf_event__synthesize_mmap_events(const struct perf_tool *tool,
 429				       union perf_event *event,
 430				       pid_t pid, pid_t tgid,
 431				       perf_event__handler_t process,
 432				       struct machine *machine,
 433				       bool mmap_data)
 434{
 435	unsigned long long t;
 436	char bf[BUFSIZ];
 437	struct io io;
 438	bool truncation = false;
 439	unsigned long long timeout = proc_map_timeout * 1000000ULL;
 440	int rc = 0;
 441	const char *hugetlbfs_mnt = hugetlbfs__mountpoint();
 442	int hugetlbfs_mnt_len = hugetlbfs_mnt ? strlen(hugetlbfs_mnt) : 0;
 443
 444	if (machine__is_default_guest(machine))
 445		return 0;
 446
 447	snprintf(bf, sizeof(bf), "%s/proc/%d/task/%d/maps",
 448		machine->root_dir, pid, pid);
 449
 450	io.fd = open(bf, O_RDONLY, 0);
 451	if (io.fd < 0) {
 452		/*
 453		 * We raced with a task exiting - just return:
 454		 */
 455		pr_debug("couldn't open %s\n", bf);
 456		return -1;
 457	}
 458	io__init(&io, io.fd, bf, sizeof(bf));
 459
 460	event->header.type = PERF_RECORD_MMAP2;
 461	t = rdclock();
 462
 463	while (!io.eof) {
 464		static const char anonstr[] = "//anon";
 465		size_t size, aligned_size;
 466
 467		/* ensure null termination since stack will be reused. */
 468		event->mmap2.filename[0] = '\0';
 469
 470		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
 471		if (!read_proc_maps_line(&io,
 472					&event->mmap2.start,
 473					&event->mmap2.len,
 474					&event->mmap2.prot,
 475					&event->mmap2.flags,
 476					&event->mmap2.pgoff,
 477					&event->mmap2.maj,
 478					&event->mmap2.min,
 479					&event->mmap2.ino,
 480					sizeof(event->mmap2.filename),
 481					event->mmap2.filename))
 482			continue;
 483
 484		if ((rdclock() - t) > timeout) {
 485			pr_warning("Reading %s/proc/%d/task/%d/maps time out. "
 486				   "You may want to increase "
 487				   "the time limit by --proc-map-timeout\n",
 488				   machine->root_dir, pid, pid);
 489			truncation = true;
 490			goto out;
 491		}
 492
 493		event->mmap2.ino_generation = 0;
 494
 495		/*
 496		 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
 497		 */
 498		if (machine__is_host(machine))
 499			event->header.misc = PERF_RECORD_MISC_USER;
 500		else
 501			event->header.misc = PERF_RECORD_MISC_GUEST_USER;
 502
 503		if ((event->mmap2.prot & PROT_EXEC) == 0) {
 504			if (!mmap_data || (event->mmap2.prot & PROT_READ) == 0)
 505				continue;
 506
 507			event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
 508		}
 509
 510out:
 511		if (truncation)
 512			event->header.misc |= PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT;
 513
 514		if (!strcmp(event->mmap2.filename, ""))
 515			strcpy(event->mmap2.filename, anonstr);
 516
 517		if (hugetlbfs_mnt_len &&
 518		    !strncmp(event->mmap2.filename, hugetlbfs_mnt,
 519			     hugetlbfs_mnt_len)) {
 520			strcpy(event->mmap2.filename, anonstr);
 521			event->mmap2.flags |= MAP_HUGETLB;
 522		}
 523
 524		size = strlen(event->mmap2.filename) + 1;
 525		aligned_size = PERF_ALIGN(size, sizeof(u64));
 526		event->mmap2.len -= event->mmap.start;
 527		event->mmap2.header.size = (sizeof(event->mmap2) -
 528					(sizeof(event->mmap2.filename) - aligned_size));
 529		memset(event->mmap2.filename + size, 0, machine->id_hdr_size +
 530			(aligned_size - size));
 531		event->mmap2.header.size += machine->id_hdr_size;
 532		event->mmap2.pid = tgid;
 533		event->mmap2.tid = pid;
 534
 535		if (!symbol_conf.no_buildid_mmap2)
 536			perf_record_mmap2__read_build_id(&event->mmap2, machine, false);
 537
 538		if (perf_tool__process_synth_event(tool, event, machine, process) != 0) {
 539			rc = -1;
 540			break;
 541		}
 542
 543		if (truncation)
 544			break;
 545	}
 546
 547	close(io.fd);
 548	return rc;
 549}
 550
 551#ifdef HAVE_FILE_HANDLE
 552static int perf_event__synthesize_cgroup(const struct perf_tool *tool,
 553					 union perf_event *event,
 554					 char *path, size_t mount_len,
 555					 perf_event__handler_t process,
 556					 struct machine *machine)
 557{
 558	size_t event_size = sizeof(event->cgroup) - sizeof(event->cgroup.path);
 559	size_t path_len = strlen(path) - mount_len + 1;
 560	struct {
 561		struct file_handle fh;
 562		uint64_t cgroup_id;
 563	} handle;
 564	int mount_id;
 565
 566	while (path_len % sizeof(u64))
 567		path[mount_len + path_len++] = '\0';
 568
 569	memset(&event->cgroup, 0, event_size);
 570
 571	event->cgroup.header.type = PERF_RECORD_CGROUP;
 572	event->cgroup.header.size = event_size + path_len + machine->id_hdr_size;
 573
 574	handle.fh.handle_bytes = sizeof(handle.cgroup_id);
 575	if (name_to_handle_at(AT_FDCWD, path, &handle.fh, &mount_id, 0) < 0) {
 576		pr_debug("stat failed: %s\n", path);
 577		return -1;
 578	}
 579
 580	event->cgroup.id = handle.cgroup_id;
 581	strncpy(event->cgroup.path, path + mount_len, path_len);
 582	memset(event->cgroup.path + path_len, 0, machine->id_hdr_size);
 583
 584	if (perf_tool__process_synth_event(tool, event, machine, process) < 0) {
 585		pr_debug("process synth event failed\n");
 586		return -1;
 587	}
 588
 589	return 0;
 590}
 591
 592static int perf_event__walk_cgroup_tree(const struct perf_tool *tool,
 593					union perf_event *event,
 594					char *path, size_t mount_len,
 595					perf_event__handler_t process,
 596					struct machine *machine)
 597{
 598	size_t pos = strlen(path);
 599	DIR *d;
 600	struct dirent *dent;
 601	int ret = 0;
 602
 603	if (perf_event__synthesize_cgroup(tool, event, path, mount_len,
 604					  process, machine) < 0)
 605		return -1;
 606
 607	d = opendir(path);
 608	if (d == NULL) {
 609		pr_debug("failed to open directory: %s\n", path);
 610		return -1;
 611	}
 612
 613	while ((dent = readdir(d)) != NULL) {
 614		if (dent->d_type != DT_DIR)
 615			continue;
 616		if (!strcmp(dent->d_name, ".") ||
 617		    !strcmp(dent->d_name, ".."))
 618			continue;
 619
 620		/* any sane path should be less than PATH_MAX */
 621		if (strlen(path) + strlen(dent->d_name) + 1 >= PATH_MAX)
 622			continue;
 623
 624		if (path[pos - 1] != '/')
 625			strcat(path, "/");
 626		strcat(path, dent->d_name);
 627
 628		ret = perf_event__walk_cgroup_tree(tool, event, path,
 629						   mount_len, process, machine);
 630		if (ret < 0)
 631			break;
 632
 633		path[pos] = '\0';
 634	}
 635
 636	closedir(d);
 637	return ret;
 638}
 639
 640int perf_event__synthesize_cgroups(const struct perf_tool *tool,
 641				   perf_event__handler_t process,
 642				   struct machine *machine)
 643{
 644	union perf_event event;
 645	char cgrp_root[PATH_MAX];
 646	size_t mount_len;  /* length of mount point in the path */
 647
 648	if (!tool || !tool->cgroup_events)
 649		return 0;
 650
 651	if (cgroupfs_find_mountpoint(cgrp_root, PATH_MAX, "perf_event") < 0) {
 652		pr_debug("cannot find cgroup mount point\n");
 653		return -1;
 654	}
 655
 656	mount_len = strlen(cgrp_root);
 657	/* make sure the path starts with a slash (after mount point) */
 658	strcat(cgrp_root, "/");
 659
 660	if (perf_event__walk_cgroup_tree(tool, &event, cgrp_root, mount_len,
 661					 process, machine) < 0)
 662		return -1;
 663
 664	return 0;
 665}
 666#else
 667int perf_event__synthesize_cgroups(const struct perf_tool *tool __maybe_unused,
 668				   perf_event__handler_t process __maybe_unused,
 669				   struct machine *machine __maybe_unused)
 670{
 671	return -1;
 672}
 673#endif
 674
 675struct perf_event__synthesize_modules_maps_cb_args {
 676	const struct perf_tool *tool;
 677	perf_event__handler_t process;
 678	struct machine *machine;
 679	union perf_event *event;
 680};
 681
 682static int perf_event__synthesize_modules_maps_cb(struct map *map, void *data)
 683{
 684	struct perf_event__synthesize_modules_maps_cb_args *args = data;
 685	union perf_event *event = args->event;
 686	struct dso *dso;
 687	size_t size;
 688
 689	if (!__map__is_kmodule(map))
 690		return 0;
 691
 692	dso = map__dso(map);
 693	if (!symbol_conf.no_buildid_mmap2) {
 694		size = PERF_ALIGN(dso__long_name_len(dso) + 1, sizeof(u64));
 695		event->mmap2.header.type = PERF_RECORD_MMAP2;
 696		event->mmap2.header.size = (sizeof(event->mmap2) -
 697					(sizeof(event->mmap2.filename) - size));
 698		memset(event->mmap2.filename + size, 0, args->machine->id_hdr_size);
 699		event->mmap2.header.size += args->machine->id_hdr_size;
 700		event->mmap2.start = map__start(map);
 701		event->mmap2.len   = map__size(map);
 702		event->mmap2.pid   = args->machine->pid;
 703
 704		memcpy(event->mmap2.filename, dso__long_name(dso), dso__long_name_len(dso) + 1);
 705
 706		/* Clear stale build ID from previous module iteration */
 707		event->mmap2.header.misc &= ~PERF_RECORD_MISC_MMAP_BUILD_ID;
 708		memset(event->mmap2.build_id, 0, sizeof(event->mmap2.build_id));
 709		event->mmap2.build_id_size = 0;
 710
 711		perf_record_mmap2__read_build_id(&event->mmap2, args->machine, false);
 712	} else {
 713		size = PERF_ALIGN(dso__long_name_len(dso) + 1, sizeof(u64));
 714		event->mmap.header.type = PERF_RECORD_MMAP;
 715		event->mmap.header.size = (sizeof(event->mmap) -
 716					(sizeof(event->mmap.filename) - size));
 717		memset(event->mmap.filename + size, 0, args->machine->id_hdr_size);
 718		event->mmap.header.size += args->machine->id_hdr_size;
 719		event->mmap.start = map__start(map);
 720		event->mmap.len   = map__size(map);
 721		event->mmap.pid   = args->machine->pid;
 722
 723		memcpy(event->mmap.filename, dso__long_name(dso), dso__long_name_len(dso) + 1);
 724	}
 725
 726	if (perf_tool__process_synth_event(args->tool, event, args->machine, args->process) != 0)
 727		return -1;
 728
 729	return 0;
 730}
 731
 732int perf_event__synthesize_modules(const struct perf_tool *tool, perf_event__handler_t process,
 733				   struct machine *machine)
 734{
 735	int rc;
 736	struct maps *maps = machine__kernel_maps(machine);
 737	struct perf_event__synthesize_modules_maps_cb_args args = {
 738		.tool = tool,
 739		.process = process,
 740		.machine = machine,
 741	};
 742	size_t size = symbol_conf.no_buildid_mmap2
 743		? sizeof(args.event->mmap)
 744		: sizeof(args.event->mmap2);
 745
 746	args.event = zalloc(size + machine->id_hdr_size);
 747	if (args.event == NULL) {
 748		pr_debug("Not enough memory synthesizing mmap event "
 749			 "for kernel modules\n");
 750		return -1;
 751	}
 752
 753	/*
 754	 * kernel uses 0 for user space maps, see kernel/perf_event.c
 755	 * __perf_event_mmap
 756	 */
 757	if (machine__is_host(machine))
 758		args.event->header.misc = PERF_RECORD_MISC_KERNEL;
 759	else
 760		args.event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
 761
 762	rc = maps__for_each_map(maps, perf_event__synthesize_modules_maps_cb, &args);
 763
 764	free(args.event);
 765	return rc;
 766}
 767
 768static int filter_task(const struct dirent *dirent)
 769{
 770	return isdigit(dirent->d_name[0]);
 771}
 772
 773static int __event__synthesize_thread(union perf_event *comm_event,
 774				      union perf_event *mmap_event,
 775				      union perf_event *fork_event,
 776				      union perf_event *namespaces_event,
 777				      pid_t pid, int full, perf_event__handler_t process,
 778				      const struct perf_tool *tool, struct machine *machine,
 779				      bool needs_mmap, bool mmap_data)
 780{
 781	char filename[PATH_MAX];
 782	struct io_dir iod;
 783	struct io_dirent64 *dent;
 784	pid_t tgid, ppid;
 785	int rc = 0;
 786
 787	/* special case: only send one comm event using passed in pid */
 788	if (!full) {
 789		tgid = perf_event__synthesize_comm(tool, comm_event, pid,
 790						   process, machine);
 791
 792		if (tgid == -1)
 793			return -1;
 794
 795		if (perf_event__synthesize_namespaces(tool, namespaces_event, pid,
 796						      tgid, process, machine) < 0)
 797			return -1;
 798
 799		/*
 800		 * send mmap only for thread group leader
 801		 * see thread__init_maps()
 802		 */
 803		if (pid == tgid && needs_mmap &&
 804		    perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
 805						       process, machine, mmap_data))
 806			return -1;
 807
 808		return 0;
 809	}
 810
 811	if (machine__is_default_guest(machine))
 812		return 0;
 813
 814	snprintf(filename, sizeof(filename), "%s/proc/%d/task",
 815		 machine->root_dir, pid);
 816
 817	io_dir__init(&iod, open(filename, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
 818	if (iod.dirfd < 0)
 819		return -1;
 820
 821	while ((dent = io_dir__readdir(&iod)) != NULL) {
 822		char *end;
 823		pid_t _pid;
 824		bool kernel_thread = false;
 825
 826		if (!isdigit(dent->d_name[0]))
 827			continue;
 828
 829		_pid = strtol(dent->d_name, &end, 10);
 830		if (*end)
 831			continue;
 832
 833		/* some threads may exit just after scan, ignore it */
 834		if (perf_event__prepare_comm(comm_event, pid, _pid, machine,
 835					     &tgid, &ppid, &kernel_thread) != 0)
 836			continue;
 837
 838		rc = -1;
 839		if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
 840						ppid, process, machine) < 0)
 841			break;
 842
 843		if (perf_event__synthesize_namespaces(tool, namespaces_event, _pid,
 844						      tgid, process, machine) < 0)
 845			break;
 846
 847		/*
 848		 * Send the prepared comm event
 849		 */
 850		if (perf_tool__process_synth_event(tool, comm_event, machine, process) != 0)
 851			break;
 852
 853		rc = 0;
 854		if (_pid == pid && !kernel_thread && needs_mmap) {
 855			/* process the parent's maps too */
 856			rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
 857						process, machine, mmap_data);
 858			if (rc)
 859				break;
 860		}
 861	}
 862
 863	close(iod.dirfd);
 864
 865	return rc;
 866}
 867
 868int perf_event__synthesize_thread_map(const struct perf_tool *tool,
 869				      struct perf_thread_map *threads,
 870				      perf_event__handler_t process,
 871				      struct machine *machine,
 872				      bool needs_mmap, bool mmap_data)
 873{
 874	union perf_event *comm_event, *mmap_event, *fork_event;
 875	union perf_event *namespaces_event;
 876	int err = -1, thread, j;
 877
 878	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
 879	if (comm_event == NULL)
 880		goto out;
 881
 882	mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size);
 883	if (mmap_event == NULL)
 884		goto out_free_comm;
 885
 886	fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
 887	if (fork_event == NULL)
 888		goto out_free_mmap;
 889
 890	namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
 891				  (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
 892				  machine->id_hdr_size);
 893	if (namespaces_event == NULL)
 894		goto out_free_fork;
 895
 896	err = 0;
 897	for (thread = 0; thread < threads->nr; ++thread) {
 898		if (__event__synthesize_thread(comm_event, mmap_event,
 899					       fork_event, namespaces_event,
 900					       perf_thread_map__pid(threads, thread), 0,
 901					       process, tool, machine,
 902					       needs_mmap, mmap_data)) {
 903			err = -1;
 904			break;
 905		}
 906
 907		/*
 908		 * comm.pid is set to thread group id by
 909		 * perf_event__synthesize_comm
 910		 */
 911		if ((int) comm_event->comm.pid != perf_thread_map__pid(threads, thread)) {
 912			bool need_leader = true;
 913
 914			/* is thread group leader in thread_map? */
 915			for (j = 0; j < threads->nr; ++j) {
 916				if ((int) comm_event->comm.pid == perf_thread_map__pid(threads, j)) {
 917					need_leader = false;
 918					break;
 919				}
 920			}
 921
 922			/* if not, generate events for it */
 923			if (need_leader &&
 924			    __event__synthesize_thread(comm_event, mmap_event,
 925						       fork_event, namespaces_event,
 926						       comm_event->comm.pid, 0,
 927						       process, tool, machine,
 928						       needs_mmap, mmap_data)) {
 929				err = -1;
 930				break;
 931			}
 932		}
 933	}
 934	free(namespaces_event);
 935out_free_fork:
 936	free(fork_event);
 937out_free_mmap:
 938	free(mmap_event);
 939out_free_comm:
 940	free(comm_event);
 941out:
 942	return err;
 943}
 944
 945static int __perf_event__synthesize_threads(const struct perf_tool *tool,
 946					    perf_event__handler_t process,
 947					    struct machine *machine,
 948					    bool needs_mmap,
 949					    bool mmap_data,
 950					    struct dirent **dirent,
 951					    int start,
 952					    int num)
 953{
 954	union perf_event *comm_event, *mmap_event, *fork_event;
 955	union perf_event *namespaces_event;
 956	int err = -1;
 957	char *end;
 958	pid_t pid;
 959	int i;
 960
 961	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
 962	if (comm_event == NULL)
 963		goto out;
 964
 965	mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size);
 966	if (mmap_event == NULL)
 967		goto out_free_comm;
 968
 969	fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
 970	if (fork_event == NULL)
 971		goto out_free_mmap;
 972
 973	namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
 974				  (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
 975				  machine->id_hdr_size);
 976	if (namespaces_event == NULL)
 977		goto out_free_fork;
 978
 979	for (i = start; i < start + num; i++) {
 980		if (!isdigit(dirent[i]->d_name[0]))
 981			continue;
 982
 983		pid = (pid_t)strtol(dirent[i]->d_name, &end, 10);
 984		/* only interested in proper numerical dirents */
 985		if (*end)
 986			continue;
 987		/*
 988		 * We may race with exiting thread, so don't stop just because
 989		 * one thread couldn't be synthesized.
 990		 */
 991		__event__synthesize_thread(comm_event, mmap_event, fork_event,
 992					   namespaces_event, pid, 1, process,
 993					   tool, machine, needs_mmap, mmap_data);
 994	}
 995	err = 0;
 996
 997	free(namespaces_event);
 998out_free_fork:
 999	free(fork_event);
1000out_free_mmap:
1001	free(mmap_event);
1002out_free_comm:
1003	free(comm_event);
1004out:
1005	return err;
1006}
1007
1008struct synthesize_threads_arg {
1009	const struct perf_tool *tool;
1010	perf_event__handler_t process;
1011	struct machine *machine;
1012	bool needs_mmap;
1013	bool mmap_data;
1014	struct dirent **dirent;
1015	int num;
1016	int start;
1017};
1018
1019static void *synthesize_threads_worker(void *arg)
1020{
1021	struct synthesize_threads_arg *args = arg;
1022
1023	__perf_event__synthesize_threads(args->tool, args->process,
1024					 args->machine,
1025					 args->needs_mmap, args->mmap_data,
1026					 args->dirent,
1027					 args->start, args->num);
1028	return NULL;
1029}
1030
1031int perf_event__synthesize_threads(const struct perf_tool *tool,
1032				   perf_event__handler_t process,
1033				   struct machine *machine,
1034				   bool needs_mmap, bool mmap_data,
1035				   unsigned int nr_threads_synthesize)
1036{
1037	struct synthesize_threads_arg *args = NULL;
1038	pthread_t *synthesize_threads = NULL;
1039	char proc_path[PATH_MAX];
1040	struct dirent **dirent;
1041	int num_per_thread;
1042	int m, n, i, j;
1043	int thread_nr;
1044	int base = 0;
1045	int err = -1;
1046
1047
1048	if (machine__is_default_guest(machine))
1049		return 0;
1050
1051	snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
1052	n = scandir(proc_path, &dirent, filter_task, NULL);
1053	if (n < 0)
1054		return err;
1055
1056	if (nr_threads_synthesize == UINT_MAX)
1057		thread_nr = sysconf(_SC_NPROCESSORS_ONLN);
1058	else
1059		thread_nr = nr_threads_synthesize;
1060
1061	if (thread_nr <= 1) {
1062		err = __perf_event__synthesize_threads(tool, process,
1063						       machine,
1064						       needs_mmap, mmap_data,
1065						       dirent, base, n);
1066		goto free_dirent;
1067	}
1068	if (thread_nr > n)
1069		thread_nr = n;
1070
1071	synthesize_threads = calloc(thread_nr, sizeof(pthread_t));
1072	if (synthesize_threads == NULL)
1073		goto free_dirent;
1074
1075	args = calloc(thread_nr, sizeof(*args));
1076	if (args == NULL)
1077		goto free_threads;
1078
1079	num_per_thread = n / thread_nr;
1080	m = n % thread_nr;
1081	for (i = 0; i < thread_nr; i++) {
1082		args[i].tool = tool;
1083		args[i].process = process;
1084		args[i].machine = machine;
1085		args[i].needs_mmap = needs_mmap;
1086		args[i].mmap_data = mmap_data;
1087		args[i].dirent = dirent;
1088	}
1089	for (i = 0; i < m; i++) {
1090		args[i].num = num_per_thread + 1;
1091		args[i].start = i * args[i].num;
1092	}
1093	if (i != 0)
1094		base = args[i-1].start + args[i-1].num;
1095	for (j = i; j < thread_nr; j++) {
1096		args[j].num = num_per_thread;
1097		args[j].start = base + (j - i) * args[i].num;
1098	}
1099
1100	for (i = 0; i < thread_nr; i++) {
1101		if (pthread_create(&synthesize_threads[i], NULL,
1102				   synthesize_threads_worker, &args[i]))
1103			goto out_join;
1104	}
1105	err = 0;
1106out_join:
1107	for (i = 0; i < thread_nr; i++)
1108		pthread_join(synthesize_threads[i], NULL);
1109	free(args);
1110free_threads:
1111	free(synthesize_threads);
1112free_dirent:
1113	for (i = 0; i < n; i++)
1114		zfree(&dirent[i]);
1115	free(dirent);
1116
1117	return err;
1118}
1119
1120int __weak perf_event__synthesize_extra_kmaps(const struct perf_tool *tool __maybe_unused,
1121					      perf_event__handler_t process __maybe_unused,
1122					      struct machine *machine __maybe_unused)
1123{
1124	return 0;
1125}
1126
1127static int __perf_event__synthesize_kernel_mmap(const struct perf_tool *tool,
1128						perf_event__handler_t process,
1129						struct machine *machine)
1130{
1131	union perf_event *event;
1132	size_t size = symbol_conf.no_buildid_mmap2 ?
1133			sizeof(event->mmap) : sizeof(event->mmap2);
1134	struct map *map = machine__kernel_map(machine);
1135	struct kmap *kmap;
1136	int err;
1137
1138	if (map == NULL)
1139		return -1;
1140
1141	kmap = map__kmap(map);
1142	if (!kmap->ref_reloc_sym)
1143		return -1;
1144
1145	/*
1146	 * We should get this from /sys/kernel/sections/.text, but till that is
1147	 * available use this, and after it is use this as a fallback for older
1148	 * kernels.
1149	 */
1150	event = zalloc(size + machine->id_hdr_size);
1151	if (event == NULL) {
1152		pr_debug("Not enough memory synthesizing mmap event "
1153			 "for kernel modules\n");
1154		return -1;
1155	}
1156
1157	if (machine__is_host(machine)) {
1158		/*
1159		 * kernel uses PERF_RECORD_MISC_USER for user space maps,
1160		 * see kernel/perf_event.c __perf_event_mmap
1161		 */
1162		event->header.misc = PERF_RECORD_MISC_KERNEL;
1163	} else {
1164		event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
1165	}
1166
1167	if (!symbol_conf.no_buildid_mmap2) {
1168		size = snprintf(event->mmap2.filename, sizeof(event->mmap2.filename),
1169				"%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1;
1170		size = PERF_ALIGN(size, sizeof(u64));
1171		event->mmap2.header.type = PERF_RECORD_MMAP2;
1172		event->mmap2.header.size = (sizeof(event->mmap2) -
1173				(sizeof(event->mmap2.filename) - size) + machine->id_hdr_size);
1174		event->mmap2.pgoff = kmap->ref_reloc_sym->addr;
1175		event->mmap2.start = map__start(map);
1176		event->mmap2.len   = map__end(map) - event->mmap.start;
1177		event->mmap2.pid   = machine->pid;
1178
1179		perf_record_mmap2__read_build_id(&event->mmap2, machine, true);
1180	} else {
1181		size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
1182				"%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1;
1183		size = PERF_ALIGN(size, sizeof(u64));
1184		event->mmap.header.type = PERF_RECORD_MMAP;
1185		event->mmap.header.size = (sizeof(event->mmap) -
1186				(sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
1187		event->mmap.pgoff = kmap->ref_reloc_sym->addr;
1188		event->mmap.start = map__start(map);
1189		event->mmap.len   = map__end(map) - event->mmap.start;
1190		event->mmap.pid   = machine->pid;
1191	}
1192
1193	err = perf_tool__process_synth_event(tool, event, machine, process);
1194	free(event);
1195
1196	return err;
1197}
1198
1199int perf_event__synthesize_kernel_mmap(const struct perf_tool *tool,
1200				       perf_event__handler_t process,
1201				       struct machine *machine)
1202{
1203	int err;
1204
1205	err = __perf_event__synthesize_kernel_mmap(tool, process, machine);
1206	if (err < 0)
1207		return err;
1208
1209	return perf_event__synthesize_extra_kmaps(tool, process, machine);
1210}
1211
1212int perf_event__synthesize_thread_map2(const struct perf_tool *tool,
1213				      struct perf_thread_map *threads,
1214				      perf_event__handler_t process,
1215				      struct machine *machine)
1216{
1217	union perf_event *event;
1218	int i, err, size;
1219
1220	size  = sizeof(event->thread_map);
1221	size +=	threads->nr * sizeof(event->thread_map.entries[0]);
1222
1223	event = zalloc(size);
1224	if (!event)
1225		return -ENOMEM;
1226
1227	event->header.type = PERF_RECORD_THREAD_MAP;
1228	event->header.size = size;
1229	event->thread_map.nr = threads->nr;
1230
1231	for (i = 0; i < threads->nr; i++) {
1232		struct perf_record_thread_map_entry *entry = &event->thread_map.entries[i];
1233		char *comm = perf_thread_map__comm(threads, i);
1234
1235		if (!comm)
1236			comm = (char *) "";
1237
1238		entry->pid = perf_thread_map__pid(threads, i);
1239		strncpy((char *) &entry->comm, comm, sizeof(entry->comm));
1240	}
1241
1242	err = process(tool, event, NULL, machine);
1243
1244	free(event);
1245	return err;
1246}
1247
1248struct synthesize_cpu_map_data {
1249	const struct perf_cpu_map *map;
1250	int nr;
1251	int min_cpu;
1252	int max_cpu;
1253	int has_any_cpu;
1254	int type;
1255	size_t size;
1256	struct perf_record_cpu_map_data *data;
1257};
1258
1259static void synthesize_cpus(struct synthesize_cpu_map_data *data)
1260{
1261	data->data->type = PERF_CPU_MAP__CPUS;
1262	data->data->cpus_data.nr = data->nr;
1263	for (int i = 0; i < data->nr; i++)
1264		data->data->cpus_data.cpu[i] = perf_cpu_map__cpu(data->map, i).cpu;
1265}
1266
1267static void synthesize_mask(struct synthesize_cpu_map_data *data)
1268{
1269	int idx;
1270	struct perf_cpu cpu;
1271
1272	/* Due to padding, the 4bytes per entry mask variant is always smaller. */
1273	data->data->type = PERF_CPU_MAP__MASK;
1274	data->data->mask32_data.nr = BITS_TO_U32(data->max_cpu);
1275	data->data->mask32_data.long_size = 4;
1276
1277	perf_cpu_map__for_each_cpu(cpu, idx, data->map) {
1278		int bit_word = cpu.cpu / 32;
1279		u32 bit_mask = 1U << (cpu.cpu & 31);
1280
1281		data->data->mask32_data.mask[bit_word] |= bit_mask;
1282	}
1283}
1284
1285static void synthesize_range_cpus(struct synthesize_cpu_map_data *data)
1286{
1287	data->data->type = PERF_CPU_MAP__RANGE_CPUS;
1288	data->data->range_cpu_data.any_cpu = data->has_any_cpu;
1289	data->data->range_cpu_data.start_cpu = data->min_cpu;
1290	data->data->range_cpu_data.end_cpu = data->max_cpu;
1291}
1292
1293static void *cpu_map_data__alloc(struct synthesize_cpu_map_data *syn_data,
1294				 size_t header_size)
1295{
1296	size_t size_cpus, size_mask;
1297
1298	syn_data->nr = perf_cpu_map__nr(syn_data->map);
1299	syn_data->has_any_cpu = (perf_cpu_map__cpu(syn_data->map, 0).cpu == -1) ? 1 : 0;
1300
1301	syn_data->min_cpu = perf_cpu_map__cpu(syn_data->map, syn_data->has_any_cpu).cpu;
1302	syn_data->max_cpu = perf_cpu_map__max(syn_data->map).cpu;
1303	if (syn_data->max_cpu - syn_data->min_cpu + 1 == syn_data->nr - syn_data->has_any_cpu) {
1304		/* A consecutive range of CPUs can be encoded using a range. */
1305		assert(sizeof(u16) + sizeof(struct perf_record_range_cpu_map) == sizeof(u64));
1306		syn_data->type = PERF_CPU_MAP__RANGE_CPUS;
1307		syn_data->size = header_size + sizeof(u64);
1308		return zalloc(syn_data->size);
1309	}
1310
1311	size_cpus = sizeof(u16) + sizeof(struct cpu_map_entries) + syn_data->nr * sizeof(u16);
1312	/* Due to padding, the 4bytes per entry mask variant is always smaller. */
1313	size_mask = sizeof(u16) + sizeof(struct perf_record_mask_cpu_map32) +
1314		BITS_TO_U32(syn_data->max_cpu) * sizeof(__u32);
1315	if (syn_data->has_any_cpu || size_cpus < size_mask) {
1316		/* Follow the CPU map encoding. */
1317		syn_data->type = PERF_CPU_MAP__CPUS;
1318		syn_data->size = header_size + PERF_ALIGN(size_cpus, sizeof(u64));
1319		return zalloc(syn_data->size);
1320	}
1321	/* Encode using a bitmask. */
1322	syn_data->type = PERF_CPU_MAP__MASK;
1323	syn_data->size = header_size + PERF_ALIGN(size_mask, sizeof(u64));
1324	return zalloc(syn_data->size);
1325}
1326
1327static void cpu_map_data__synthesize(struct synthesize_cpu_map_data *data)
1328{
1329	switch (data->type) {
1330	case PERF_CPU_MAP__CPUS:
1331		synthesize_cpus(data);
1332		break;
1333	case PERF_CPU_MAP__MASK:
1334		synthesize_mask(data);
1335		break;
1336	case PERF_CPU_MAP__RANGE_CPUS:
1337		synthesize_range_cpus(data);
1338		break;
1339	default:
1340		break;
1341	}
1342}
1343
1344static struct perf_record_cpu_map *cpu_map_event__new(const struct perf_cpu_map *map)
1345{
1346	struct synthesize_cpu_map_data syn_data = { .map = map };
1347	struct perf_record_cpu_map *event;
1348
1349
1350	event = cpu_map_data__alloc(&syn_data, sizeof(struct perf_event_header));
1351	if (!event)
1352		return NULL;
1353
1354	syn_data.data = &event->data;
1355	event->header.type = PERF_RECORD_CPU_MAP;
1356	event->header.size = syn_data.size;
1357	cpu_map_data__synthesize(&syn_data);
1358	return event;
1359}
1360
1361
1362int perf_event__synthesize_cpu_map(const struct perf_tool *tool,
1363				   const struct perf_cpu_map *map,
1364				   perf_event__handler_t process,
1365				   struct machine *machine)
1366{
1367	struct perf_record_cpu_map *event;
1368	int err;
1369
1370	event = cpu_map_event__new(map);
1371	if (!event)
1372		return -ENOMEM;
1373
1374	err = process(tool, (union perf_event *) event, NULL, machine);
1375
1376	free(event);
1377	return err;
1378}
1379
1380int perf_event__synthesize_stat_config(const struct perf_tool *tool,
1381				       struct perf_stat_config *config,
1382				       perf_event__handler_t process,
1383				       struct machine *machine)
1384{
1385	struct perf_record_stat_config *event;
1386	int size, i = 0, err;
1387
1388	size  = sizeof(*event);
1389	size += (PERF_STAT_CONFIG_TERM__MAX * sizeof(event->data[0]));
1390
1391	event = zalloc(size);
1392	if (!event)
1393		return -ENOMEM;
1394
1395	event->header.type = PERF_RECORD_STAT_CONFIG;
1396	event->header.size = size;
1397	event->nr          = PERF_STAT_CONFIG_TERM__MAX;
1398
1399#define ADD(__term, __val)					\
1400	event->data[i].tag = PERF_STAT_CONFIG_TERM__##__term;	\
1401	event->data[i].val = __val;				\
1402	i++;
1403
1404	ADD(AGGR_MODE,	config->aggr_mode)
1405	ADD(INTERVAL,	config->interval)
1406	ADD(SCALE,	config->scale)
1407	ADD(AGGR_LEVEL,	config->aggr_level)
1408
1409	WARN_ONCE(i != PERF_STAT_CONFIG_TERM__MAX,
1410		  "stat config terms unbalanced\n");
1411#undef ADD
1412
1413	err = process(tool, (union perf_event *) event, NULL, machine);
1414
1415	free(event);
1416	return err;
1417}
1418
1419int perf_event__synthesize_stat(const struct perf_tool *tool,
1420				struct perf_cpu cpu, u32 thread, u64 id,
1421				struct perf_counts_values *count,
1422				perf_event__handler_t process,
1423				struct machine *machine)
1424{
1425	struct perf_record_stat event;
1426
1427	event.header.type = PERF_RECORD_STAT;
1428	event.header.size = sizeof(event);
1429	event.header.misc = 0;
1430
1431	event.id        = id;
1432	event.cpu       = cpu.cpu;
1433	event.thread    = thread;
1434	event.val       = count->val;
1435	event.ena       = count->ena;
1436	event.run       = count->run;
1437
1438	return process(tool, (union perf_event *) &event, NULL, machine);
1439}
1440
1441int perf_event__synthesize_stat_round(const struct perf_tool *tool,
1442				      u64 evtime, u64 type,
1443				      perf_event__handler_t process,
1444				      struct machine *machine)
1445{
1446	struct perf_record_stat_round event;
1447
1448	event.header.type = PERF_RECORD_STAT_ROUND;
1449	event.header.size = sizeof(event);
1450	event.header.misc = 0;
1451
1452	event.time = evtime;
1453	event.type = type;
1454
1455	return process(tool, (union perf_event *) &event, NULL, machine);
1456}
1457
1458size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, u64 read_format)
1459{
1460	size_t sz, result = sizeof(struct perf_record_sample);
1461
1462	if (type & PERF_SAMPLE_IDENTIFIER)
1463		result += sizeof(u64);
1464
1465	if (type & PERF_SAMPLE_IP)
1466		result += sizeof(u64);
1467
1468	if (type & PERF_SAMPLE_TID)
1469		result += sizeof(u64);
1470
1471	if (type & PERF_SAMPLE_TIME)
1472		result += sizeof(u64);
1473
1474	if (type & PERF_SAMPLE_ADDR)
1475		result += sizeof(u64);
1476
1477	if (type & PERF_SAMPLE_ID)
1478		result += sizeof(u64);
1479
1480	if (type & PERF_SAMPLE_STREAM_ID)
1481		result += sizeof(u64);
1482
1483	if (type & PERF_SAMPLE_CPU)
1484		result += sizeof(u64);
1485
1486	if (type & PERF_SAMPLE_PERIOD)
1487		result += sizeof(u64);
1488
1489	if (type & PERF_SAMPLE_READ) {
1490		result += sizeof(u64);
1491		if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1492			result += sizeof(u64);
1493		if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1494			result += sizeof(u64);
1495		/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
1496		if (read_format & PERF_FORMAT_GROUP) {
1497			sz = sample_read_value_size(read_format);
1498			result += sz * sample->read.group.nr;
1499		} else {
1500			result += sizeof(u64);
1501			if (read_format & PERF_FORMAT_LOST)
1502				result += sizeof(u64);
1503		}
1504	}
1505
1506	if (type & PERF_SAMPLE_CALLCHAIN) {
1507		sz = (sample->callchain->nr + 1) * sizeof(u64);
1508		result += sz;
1509	}
1510
1511	if (type & PERF_SAMPLE_RAW) {
1512		result += sizeof(u32);
1513		result += sample->raw_size;
1514	}
1515
1516	if (type & PERF_SAMPLE_BRANCH_STACK) {
1517		sz = sample->branch_stack->nr * sizeof(struct branch_entry);
1518		/* nr, hw_idx */
1519		sz += 2 * sizeof(u64);
1520		result += sz;
1521	}
1522
1523	if (type & PERF_SAMPLE_REGS_USER) {
1524		if (sample->user_regs && sample->user_regs->abi) {
1525			result += sizeof(u64);
1526			sz = hweight64(sample->user_regs->mask) * sizeof(u64);
1527			result += sz;
1528		} else {
1529			result += sizeof(u64);
1530		}
1531	}
1532
1533	if (type & PERF_SAMPLE_STACK_USER) {
1534		sz = sample->user_stack.size;
1535		result += sizeof(u64);
1536		if (sz) {
1537			result += sz;
1538			result += sizeof(u64);
1539		}
1540	}
1541
1542	if (type & PERF_SAMPLE_WEIGHT_TYPE)
1543		result += sizeof(u64);
1544
1545	if (type & PERF_SAMPLE_DATA_SRC)
1546		result += sizeof(u64);
1547
1548	if (type & PERF_SAMPLE_TRANSACTION)
1549		result += sizeof(u64);
1550
1551	if (type & PERF_SAMPLE_REGS_INTR) {
1552		if (sample->intr_regs && sample->intr_regs->abi) {
1553			result += sizeof(u64);
1554			sz = hweight64(sample->intr_regs->mask) * sizeof(u64);
1555			result += sz;
1556		} else {
1557			result += sizeof(u64);
1558		}
1559	}
1560
1561	if (type & PERF_SAMPLE_PHYS_ADDR)
1562		result += sizeof(u64);
1563
1564	if (type & PERF_SAMPLE_CGROUP)
1565		result += sizeof(u64);
1566
1567	if (type & PERF_SAMPLE_DATA_PAGE_SIZE)
1568		result += sizeof(u64);
1569
1570	if (type & PERF_SAMPLE_CODE_PAGE_SIZE)
1571		result += sizeof(u64);
1572
1573	if (type & PERF_SAMPLE_AUX) {
1574		result += sizeof(u64);
1575		result += sample->aux_sample.size;
1576	}
1577
1578	return result;
1579}
1580
1581static void perf_synthesize_sample_weight(const struct perf_sample *data,
1582					       __u64 *array, u64 type __maybe_unused)
1583{
1584	*array = data->weight;
1585
1586	if (type & PERF_SAMPLE_WEIGHT_STRUCT) {
1587		*array &= 0xffffffff;
1588		*array |= ((u64)data->ins_lat << 32);
1589		*array |= ((u64)data->weight3 << 48);
1590	}
1591}
1592
1593static __u64 *copy_read_group_values(__u64 *array, __u64 read_format,
1594				     const struct perf_sample *sample)
1595{
1596	size_t sz = sample_read_value_size(read_format);
1597	struct sample_read_value *v = sample->read.group.values;
1598
1599	sample_read_group__for_each(v, sample->read.group.nr, read_format) {
1600		/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
1601		memcpy(array, v, sz);
1602		array = (void *)array + sz;
1603	}
1604	return array;
1605}
1606
1607int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format,
1608				  const struct perf_sample *sample)
1609{
1610	__u64 *array;
1611	size_t sz;
1612	/*
1613	 * used for cross-endian analysis. See git commit 65014ab3
1614	 * for why this goofiness is needed.
1615	 */
1616	union u64_swap u;
1617
1618	array = event->sample.array;
1619
1620	if (type & PERF_SAMPLE_IDENTIFIER) {
1621		*array = sample->id;
1622		array++;
1623	}
1624
1625	if (type & PERF_SAMPLE_IP) {
1626		*array = sample->ip;
1627		array++;
1628	}
1629
1630	if (type & PERF_SAMPLE_TID) {
1631		u.val32[0] = sample->pid;
1632		u.val32[1] = sample->tid;
1633		*array = u.val64;
1634		array++;
1635	}
1636
1637	if (type & PERF_SAMPLE_TIME) {
1638		*array = sample->time;
1639		array++;
1640	}
1641
1642	if (type & PERF_SAMPLE_ADDR) {
1643		*array = sample->addr;
1644		array++;
1645	}
1646
1647	if (type & PERF_SAMPLE_ID) {
1648		*array = sample->id;
1649		array++;
1650	}
1651
1652	if (type & PERF_SAMPLE_STREAM_ID) {
1653		*array = sample->stream_id;
1654		array++;
1655	}
1656
1657	if (type & PERF_SAMPLE_CPU) {
1658		u.val32[0] = sample->cpu;
1659		u.val32[1] = 0;
1660		*array = u.val64;
1661		array++;
1662	}
1663
1664	if (type & PERF_SAMPLE_PERIOD) {
1665		*array = sample->period;
1666		array++;
1667	}
1668
1669	if (type & PERF_SAMPLE_READ) {
1670		if (read_format & PERF_FORMAT_GROUP)
1671			*array = sample->read.group.nr;
1672		else
1673			*array = sample->read.one.value;
1674		array++;
1675
1676		if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
1677			*array = sample->read.time_enabled;
1678			array++;
1679		}
1680
1681		if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
1682			*array = sample->read.time_running;
1683			array++;
1684		}
1685
1686		/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
1687		if (read_format & PERF_FORMAT_GROUP) {
1688			array = copy_read_group_values(array, read_format,
1689						       sample);
1690		} else {
1691			*array = sample->read.one.id;
1692			array++;
1693
1694			if (read_format & PERF_FORMAT_LOST) {
1695				*array = sample->read.one.lost;
1696				array++;
1697			}
1698		}
1699	}
1700
1701	if (type & PERF_SAMPLE_CALLCHAIN) {
1702		sz = (sample->callchain->nr + 1) * sizeof(u64);
1703		memcpy(array, sample->callchain, sz);
1704		array = (void *)array + sz;
1705	}
1706
1707	if (type & PERF_SAMPLE_RAW) {
1708		u32 *array32 = (void *)array;
1709
1710		*array32 = sample->raw_size;
1711		array32++;
1712
1713		memcpy(array32, sample->raw_data, sample->raw_size);
1714		array = (void *)(array32 + (sample->raw_size / sizeof(u32)));
1715
1716		/* make sure the array is 64-bit aligned */
1717		BUG_ON(((long)array) % sizeof(u64));
1718	}
1719
1720	if (type & PERF_SAMPLE_BRANCH_STACK) {
1721		sz = sample->branch_stack->nr * sizeof(struct branch_entry);
1722		/* nr, hw_idx */
1723		sz += 2 * sizeof(u64);
1724		memcpy(array, sample->branch_stack, sz);
1725		array = (void *)array + sz;
1726	}
1727
1728	if (type & PERF_SAMPLE_REGS_USER) {
1729		if (sample->user_regs && sample->user_regs->abi) {
1730			*array++ = sample->user_regs->abi;
1731			sz = hweight64(sample->user_regs->mask) * sizeof(u64);
1732			memcpy(array, sample->user_regs->regs, sz);
1733			array = (void *)array + sz;
1734		} else {
1735			*array++ = 0;
1736		}
1737	}
1738
1739	if (type & PERF_SAMPLE_STACK_USER) {
1740		sz = sample->user_stack.size;
1741		*array++ = sz;
1742		if (sz) {
1743			memcpy(array, sample->user_stack.data, sz);
1744			array = (void *)array + sz;
1745			*array++ = sz;
1746		}
1747	}
1748
1749	if (type & PERF_SAMPLE_WEIGHT_TYPE) {
1750		perf_synthesize_sample_weight(sample, array, type);
1751		array++;
1752	}
1753
1754	if (type & PERF_SAMPLE_DATA_SRC) {
1755		*array = sample->data_src;
1756		array++;
1757	}
1758
1759	if (type & PERF_SAMPLE_TRANSACTION) {
1760		*array = sample->transaction;
1761		array++;
1762	}
1763
1764	if (type & PERF_SAMPLE_REGS_INTR) {
1765		if (sample->intr_regs && sample->intr_regs->abi) {
1766			*array++ = sample->intr_regs->abi;
1767			sz = hweight64(sample->intr_regs->mask) * sizeof(u64);
1768			memcpy(array, sample->intr_regs->regs, sz);
1769			array = (void *)array + sz;
1770		} else {
1771			*array++ = 0;
1772		}
1773	}
1774
1775	if (type & PERF_SAMPLE_PHYS_ADDR) {
1776		*array = sample->phys_addr;
1777		array++;
1778	}
1779
1780	if (type & PERF_SAMPLE_CGROUP) {
1781		*array = sample->cgroup;
1782		array++;
1783	}
1784
1785	if (type & PERF_SAMPLE_DATA_PAGE_SIZE) {
1786		*array = sample->data_page_size;
1787		array++;
1788	}
1789
1790	if (type & PERF_SAMPLE_CODE_PAGE_SIZE) {
1791		*array = sample->code_page_size;
1792		array++;
1793	}
1794
1795	if (type & PERF_SAMPLE_AUX) {
1796		sz = sample->aux_sample.size;
1797		*array++ = sz;
1798		memcpy(array, sample->aux_sample.data, sz);
1799		array = (void *)array + sz;
1800	}
1801
1802	return 0;
1803}
1804
1805int perf_event__synthesize_id_sample(__u64 *array, u64 type, const struct perf_sample *sample)
1806{
1807	__u64 *start = array;
1808
1809	/*
1810	 * used for cross-endian analysis. See git commit 65014ab3
1811	 * for why this goofiness is needed.
1812	 */
1813	union u64_swap u;
1814
1815	if (type & PERF_SAMPLE_TID) {
1816		u.val32[0] = sample->pid;
1817		u.val32[1] = sample->tid;
1818		*array = u.val64;
1819		array++;
1820	}
1821
1822	if (type & PERF_SAMPLE_TIME) {
1823		*array = sample->time;
1824		array++;
1825	}
1826
1827	if (type & PERF_SAMPLE_ID) {
1828		*array = sample->id;
1829		array++;
1830	}
1831
1832	if (type & PERF_SAMPLE_STREAM_ID) {
1833		*array = sample->stream_id;
1834		array++;
1835	}
1836
1837	if (type & PERF_SAMPLE_CPU) {
1838		u.val32[0] = sample->cpu;
1839		u.val32[1] = 0;
1840		*array = u.val64;
1841		array++;
1842	}
1843
1844	if (type & PERF_SAMPLE_IDENTIFIER) {
1845		*array = sample->id;
1846		array++;
1847	}
1848
1849	return (void *)array - (void *)start;
1850}
1851
1852int __perf_event__synthesize_id_index(const struct perf_tool *tool, perf_event__handler_t process,
1853				      struct evlist *evlist, struct machine *machine, size_t from)
1854{
1855	union perf_event *ev;
1856	struct evsel *evsel;
1857	size_t nr = 0, i = 0, sz, max_nr, n, pos;
1858	size_t e1_sz = sizeof(struct id_index_entry);
1859	size_t e2_sz = sizeof(struct id_index_entry_2);
1860	size_t etot_sz = e1_sz + e2_sz;
1861	bool e2_needed = false;
1862	int err;
1863
1864	max_nr = (UINT16_MAX - sizeof(struct perf_record_id_index)) / etot_sz;
1865
1866	pos = 0;
1867	evlist__for_each_entry(evlist, evsel) {
1868		if (pos++ < from)
1869			continue;
1870		nr += evsel->core.ids;
1871	}
1872
1873	if (!nr)
1874		return 0;
1875
1876	pr_debug2("Synthesizing id index\n");
1877
1878	n = nr > max_nr ? max_nr : nr;
1879	sz = sizeof(struct perf_record_id_index) + n * etot_sz;
1880	ev = zalloc(sz);
1881	if (!ev)
1882		return -ENOMEM;
1883
1884	sz = sizeof(struct perf_record_id_index) + n * e1_sz;
1885
1886	ev->id_index.header.type = PERF_RECORD_ID_INDEX;
1887	ev->id_index.nr = n;
1888
1889	pos = 0;
1890	evlist__for_each_entry(evlist, evsel) {
1891		u32 j;
1892
1893		if (pos++ < from)
1894			continue;
1895		for (j = 0; j < evsel->core.ids; j++, i++) {
1896			struct id_index_entry *e;
1897			struct id_index_entry_2 *e2;
1898			struct perf_sample_id *sid;
1899
1900			if (i >= n) {
1901				ev->id_index.header.size = sz + (e2_needed ? n * e2_sz : 0);
1902				err = process(tool, ev, NULL, machine);
1903				if (err)
1904					goto out_err;
1905				nr -= n;
1906				i = 0;
1907				e2_needed = false;
1908			}
1909
1910			e = &ev->id_index.entries[i];
1911
1912			e->id = evsel->core.id[j];
1913
1914			sid = evlist__id2sid(evlist, e->id);
1915			if (!sid) {
1916				free(ev);
1917				return -ENOENT;
1918			}
1919
1920			e->idx = sid->idx;
1921			e->cpu = sid->cpu.cpu;
1922			e->tid = sid->tid;
1923
1924			if (sid->machine_pid)
1925				e2_needed = true;
1926
1927			e2 = (void *)ev + sz;
1928			e2[i].machine_pid = sid->machine_pid;
1929			e2[i].vcpu        = sid->vcpu.cpu;
1930		}
1931	}
1932
1933	sz = sizeof(struct perf_record_id_index) + nr * e1_sz;
1934	ev->id_index.header.size = sz + (e2_needed ? nr * e2_sz : 0);
1935	ev->id_index.nr = nr;
1936
1937	err = process(tool, ev, NULL, machine);
1938out_err:
1939	free(ev);
1940
1941	return err;
1942}
1943
1944int perf_event__synthesize_id_index(const struct perf_tool *tool, perf_event__handler_t process,
1945				    struct evlist *evlist, struct machine *machine)
1946{
1947	return __perf_event__synthesize_id_index(tool, process, evlist, machine, 0);
1948}
1949
1950int __machine__synthesize_threads(struct machine *machine, const struct perf_tool *tool,
1951				  struct target *target, struct perf_thread_map *threads,
1952				  perf_event__handler_t process, bool needs_mmap,
1953				  bool data_mmap, unsigned int nr_threads_synthesize)
1954{
1955	/*
1956	 * When perf runs in non-root PID namespace, and the namespace's proc FS
1957	 * is not mounted, nsinfo__is_in_root_namespace() returns false.
1958	 * In this case, the proc FS is coming for the parent namespace, thus
1959	 * perf tool will wrongly gather process info from its parent PID
1960	 * namespace.
1961	 *
1962	 * To avoid the confusion that the perf tool runs in a child PID
1963	 * namespace but it synthesizes thread info from its parent PID
1964	 * namespace, returns failure with warning.
1965	 */
1966	if (!nsinfo__is_in_root_namespace()) {
1967		pr_err("Perf runs in non-root PID namespace but it tries to ");
1968		pr_err("gather process info from its parent PID namespace.\n");
1969		pr_err("Please mount the proc file system properly, e.g. ");
1970		pr_err("add the option '--mount-proc' for unshare command.\n");
1971		return -EPERM;
1972	}
1973
1974	if (target__has_task(target))
1975		return perf_event__synthesize_thread_map(tool, threads, process, machine,
1976							 needs_mmap, data_mmap);
1977	else if (target__has_cpu(target))
1978		return perf_event__synthesize_threads(tool, process, machine,
1979						      needs_mmap, data_mmap,
1980						      nr_threads_synthesize);
1981	/* command specified */
1982	return 0;
1983}
1984
1985int machine__synthesize_threads(struct machine *machine, struct target *target,
1986				struct perf_thread_map *threads, bool needs_mmap,
1987				bool data_mmap, unsigned int nr_threads_synthesize)
1988{
1989	return __machine__synthesize_threads(machine, NULL, target, threads,
1990					     perf_event__process, needs_mmap,
1991					     data_mmap, nr_threads_synthesize);
1992}
1993
1994static struct perf_record_event_update *event_update_event__new(size_t size, u64 type, u64 id)
1995{
1996	struct perf_record_event_update *ev;
1997
1998	size += sizeof(*ev);
1999	size  = PERF_ALIGN(size, sizeof(u64));
2000
2001	ev = zalloc(size);
2002	if (ev) {
2003		ev->header.type = PERF_RECORD_EVENT_UPDATE;
2004		ev->header.size = (u16)size;
2005		ev->type	= type;
2006		ev->id		= id;
2007	}
2008	return ev;
2009}
2010
2011int perf_event__synthesize_event_update_unit(const struct perf_tool *tool, struct evsel *evsel,
2012					     perf_event__handler_t process)
2013{
2014	size_t size = strlen(evsel->unit);
2015	struct perf_record_event_update *ev;
2016	int err;
2017
2018	ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->core.id[0]);
2019	if (ev == NULL)
2020		return -ENOMEM;
2021
2022	strlcpy(ev->unit, evsel->unit, size + 1);
2023	err = process(tool, (union perf_event *)ev, NULL, NULL);
2024	free(ev);
2025	return err;
2026}
2027
2028int perf_event__synthesize_event_update_scale(const struct perf_tool *tool, struct evsel *evsel,
2029					      perf_event__handler_t process)
2030{
2031	struct perf_record_event_update *ev;
2032	struct perf_record_event_update_scale *ev_data;
2033	int err;
2034
2035	ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->core.id[0]);
2036	if (ev == NULL)
2037		return -ENOMEM;
2038
2039	ev->scale.scale = evsel->scale;
2040	err = process(tool, (union perf_event *)ev, NULL, NULL);
2041	free(ev);
2042	return err;
2043}
2044
2045int perf_event__synthesize_event_update_name(const struct perf_tool *tool, struct evsel *evsel,
2046					     perf_event__handler_t process)
2047{
2048	struct perf_record_event_update *ev;
2049	size_t len = strlen(evsel__name(evsel));
2050	int err;
2051
2052	ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->core.id[0]);
2053	if (ev == NULL)
2054		return -ENOMEM;
2055
2056	strlcpy(ev->name, evsel->name, len + 1);
2057	err = process(tool, (union perf_event *)ev, NULL, NULL);
2058	free(ev);
2059	return err;
2060}
2061
2062int perf_event__synthesize_event_update_cpus(const struct perf_tool *tool, struct evsel *evsel,
2063					     perf_event__handler_t process)
2064{
2065	struct synthesize_cpu_map_data syn_data = { .map = evsel->core.pmu_cpus };
2066	struct perf_record_event_update *ev;
2067	int err;
2068
2069	ev = cpu_map_data__alloc(&syn_data, sizeof(struct perf_event_header) + 2 * sizeof(u64));
2070	if (!ev)
2071		return -ENOMEM;
2072
2073	syn_data.data = &ev->cpus.cpus;
2074	ev->header.type = PERF_RECORD_EVENT_UPDATE;
2075	ev->header.size = (u16)syn_data.size;
2076	ev->type	= PERF_EVENT_UPDATE__CPUS;
2077	ev->id		= evsel->core.id[0];
2078	cpu_map_data__synthesize(&syn_data);
2079
2080	err = process(tool, (union perf_event *)ev, NULL, NULL);
2081	free(ev);
2082	return err;
2083}
2084
2085int perf_event__synthesize_attrs(const struct perf_tool *tool, struct evlist *evlist,
2086				 perf_event__handler_t process)
2087{
2088	struct evsel *evsel;
2089	int err = 0;
2090
2091	evlist__for_each_entry(evlist, evsel) {
2092		err = perf_event__synthesize_attr(tool, &evsel->core.attr, evsel->core.ids,
2093						  evsel->core.id, process);
2094		if (err) {
2095			pr_debug("failed to create perf header attribute\n");
2096			return err;
2097		}
2098	}
2099
2100	return err;
2101}
2102
2103static bool has_unit(struct evsel *evsel)
2104{
2105	return evsel->unit && *evsel->unit;
2106}
2107
2108static bool has_scale(struct evsel *evsel)
2109{
2110	return evsel->scale != 1;
2111}
2112
2113int perf_event__synthesize_extra_attr(const struct perf_tool *tool, struct evlist *evsel_list,
2114				      perf_event__handler_t process, bool is_pipe)
2115{
2116	struct evsel *evsel;
2117	int err;
2118
2119	/*
2120	 * Synthesize other events stuff not carried within
2121	 * attr event - unit, scale, name
2122	 */
2123	evlist__for_each_entry(evsel_list, evsel) {
2124		if (!evsel->supported)
2125			continue;
2126
2127		/*
2128		 * Synthesize unit and scale only if it's defined.
2129		 */
2130		if (has_unit(evsel)) {
2131			err = perf_event__synthesize_event_update_unit(tool, evsel, process);
2132			if (err < 0) {
2133				pr_err("Couldn't synthesize evsel unit.\n");
2134				return err;
2135			}
2136		}
2137
2138		if (has_scale(evsel)) {
2139			err = perf_event__synthesize_event_update_scale(tool, evsel, process);
2140			if (err < 0) {
2141				pr_err("Couldn't synthesize evsel evsel.\n");
2142				return err;
2143			}
2144		}
2145
2146		if (evsel->core.pmu_cpus) {
2147			err = perf_event__synthesize_event_update_cpus(tool, evsel, process);
2148			if (err < 0) {
2149				pr_err("Couldn't synthesize evsel cpus.\n");
2150				return err;
2151			}
2152		}
2153
2154		/*
2155		 * Name is needed only for pipe output,
2156		 * perf.data carries event names.
2157		 */
2158		if (is_pipe) {
2159			err = perf_event__synthesize_event_update_name(tool, evsel, process);
2160			if (err < 0) {
2161				pr_err("Couldn't synthesize evsel name.\n");
2162				return err;
2163			}
2164		}
2165	}
2166	return 0;
2167}
2168
2169int perf_event__synthesize_attr(const struct perf_tool *tool, struct perf_event_attr *attr,
2170				u32 ids, u64 *id, perf_event__handler_t process)
2171{
2172	union perf_event *ev;
2173	size_t size;
2174	int err;
2175
2176	size = sizeof(struct perf_event_attr);
2177	size = PERF_ALIGN(size, sizeof(u64));
2178	size += sizeof(struct perf_event_header);
2179	size += ids * sizeof(u64);
2180
2181	ev = zalloc(size);
2182
2183	if (ev == NULL)
2184		return -ENOMEM;
2185
2186	ev->attr.attr = *attr;
2187	memcpy(perf_record_header_attr_id(ev), id, ids * sizeof(u64));
2188
2189	ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
2190	ev->attr.header.size = (u16)size;
2191
2192	if (ev->attr.header.size == size)
2193		err = process(tool, ev, NULL, NULL);
2194	else
2195		err = -E2BIG;
2196
2197	free(ev);
2198
2199	return err;
2200}
2201
2202#ifdef HAVE_LIBTRACEEVENT
2203int perf_event__synthesize_tracing_data(const struct perf_tool *tool, int fd, struct evlist *evlist,
2204					perf_event__handler_t process)
2205{
2206	union perf_event ev;
2207	struct tracing_data *tdata;
2208	ssize_t size = 0, aligned_size = 0, padding;
2209	struct feat_fd ff;
2210
2211	/*
2212	 * We are going to store the size of the data followed
2213	 * by the data contents. Since the fd descriptor is a pipe,
2214	 * we cannot seek back to store the size of the data once
2215	 * we know it. Instead we:
2216	 *
2217	 * - write the tracing data to the temp file
2218	 * - get/write the data size to pipe
2219	 * - write the tracing data from the temp file
2220	 *   to the pipe
2221	 */
2222	tdata = tracing_data_get(&evlist->core.entries, fd, true);
2223	if (!tdata)
2224		return -1;
2225
2226	memset(&ev, 0, sizeof(ev.tracing_data));
2227
2228	ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
2229	size = tdata->size;
2230	aligned_size = PERF_ALIGN(size, sizeof(u64));
2231	padding = aligned_size - size;
2232	ev.tracing_data.header.size = sizeof(ev.tracing_data);
2233	ev.tracing_data.size = aligned_size;
2234
2235	process(tool, &ev, NULL, NULL);
2236
2237	/*
2238	 * The put function will copy all the tracing data
2239	 * stored in temp file to the pipe.
2240	 */
2241	tracing_data_put(tdata);
2242
2243	ff = (struct feat_fd){ .fd = fd };
2244	if (write_padded(&ff, NULL, 0, padding))
2245		return -1;
2246
2247	return aligned_size;
2248}
2249#endif
2250
2251int perf_event__synthesize_build_id(const struct perf_tool *tool,
2252				    struct perf_sample *sample,
2253				    struct machine *machine,
2254				    perf_event__handler_t process,
2255				    const struct evsel *evsel,
2256				    __u16 misc,
2257				    const struct build_id *bid,
2258				    const char *filename)
2259{
2260	union perf_event ev;
2261	size_t len;
2262
2263	len = sizeof(ev.build_id) + strlen(filename) + 1;
2264	len = PERF_ALIGN(len, sizeof(u64));
2265
2266	memset(&ev, 0, len);
2267
2268	ev.build_id.size = bid->size;
2269	if (ev.build_id.size > sizeof(ev.build_id.build_id))
2270		ev.build_id.size = sizeof(ev.build_id.build_id);
2271	memcpy(ev.build_id.build_id, bid->data, ev.build_id.size);
2272	ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
2273	ev.build_id.header.misc = misc | PERF_RECORD_MISC_BUILD_ID_SIZE;
2274	ev.build_id.pid = machine->pid;
2275	ev.build_id.header.size = len;
2276	strcpy(ev.build_id.filename, filename);
2277
2278	if (evsel) {
2279		void *array = &ev;
2280		int ret;
2281
2282		array += ev.header.size;
2283		ret = perf_event__synthesize_id_sample(array, evsel->core.attr.sample_type, sample);
2284		if (ret < 0)
2285			return ret;
2286
2287		if (ret & 7) {
2288			pr_err("Bad id sample size %d\n", ret);
2289			return -EINVAL;
2290		}
2291
2292		ev.header.size += ret;
2293	}
2294
2295	return process(tool, &ev, sample, machine);
2296}
2297
2298int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool,
2299					  struct perf_sample *sample,
2300					  struct machine *machine,
2301					  perf_event__handler_t process,
2302					  const struct evsel *evsel,
2303					  __u16 misc,
2304					  __u32 pid, __u32 tid,
2305					  __u64 start, __u64 len, __u64 pgoff,
2306					  const struct build_id *bid,
2307					  __u32 prot, __u32 flags,
2308					  const char *filename)
2309{
2310	union perf_event ev;
2311	size_t ev_len;
2312	void *array;
2313	int ret;
2314
2315	ev_len = sizeof(ev.mmap2) - sizeof(ev.mmap2.filename) + strlen(filename) + 1;
2316	ev_len = PERF_ALIGN(ev_len, sizeof(u64));
2317
2318	memset(&ev, 0, ev_len);
2319
2320	ev.mmap2.header.type = PERF_RECORD_MMAP2;
2321	ev.mmap2.header.misc = misc | PERF_RECORD_MISC_MMAP_BUILD_ID;
2322	ev.mmap2.header.size = ev_len;
2323
2324	ev.mmap2.pid = pid;
2325	ev.mmap2.tid = tid;
2326	ev.mmap2.start = start;
2327	ev.mmap2.len = len;
2328	ev.mmap2.pgoff = pgoff;
2329
2330	ev.mmap2.build_id_size = bid->size;
2331	if (ev.mmap2.build_id_size > sizeof(ev.mmap2.build_id))
2332		ev.build_id.size = sizeof(ev.mmap2.build_id);
2333	memcpy(ev.mmap2.build_id, bid->data, ev.mmap2.build_id_size);
2334
2335	ev.mmap2.prot = prot;
2336	ev.mmap2.flags = flags;
2337
2338	memcpy(ev.mmap2.filename, filename, min(strlen(filename), sizeof(ev.mmap.filename)));
2339
2340	array = &ev;
2341	array += ev.header.size;
2342	ret = perf_event__synthesize_id_sample(array, evsel->core.attr.sample_type, sample);
2343	if (ret < 0)
2344		return ret;
2345
2346	if (ret & 7) {
2347		pr_err("Bad id sample size %d\n", ret);
2348		return -EINVAL;
2349	}
2350
2351	ev.header.size += ret;
2352
2353	return process(tool, &ev, sample, machine);
2354}
2355
2356int perf_event__synthesize_stat_events(struct perf_stat_config *config, const struct perf_tool *tool,
2357				       struct evlist *evlist, perf_event__handler_t process, bool attrs)
2358{
2359	int err;
2360
2361	if (attrs) {
2362		err = perf_event__synthesize_attrs(tool, evlist, process);
2363		if (err < 0) {
2364			pr_err("Couldn't synthesize attrs.\n");
2365			return err;
2366		}
2367	}
2368
2369	err = perf_event__synthesize_extra_attr(tool, evlist, process, attrs);
2370	err = perf_event__synthesize_thread_map2(tool, evlist->core.threads, process, NULL);
2371	if (err < 0) {
2372		pr_err("Couldn't synthesize thread map.\n");
2373		return err;
2374	}
2375
2376	err = perf_event__synthesize_cpu_map(tool, evlist->core.user_requested_cpus, process, NULL);
2377	if (err < 0) {
2378		pr_err("Couldn't synthesize thread map.\n");
2379		return err;
2380	}
2381
2382	err = perf_event__synthesize_stat_config(tool, config, process, NULL);
2383	if (err < 0) {
2384		pr_err("Couldn't synthesize config.\n");
2385		return err;
2386	}
2387
2388	return 0;
2389}
2390
2391extern const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE];
2392
2393int perf_event__synthesize_features(const struct perf_tool *tool, struct perf_session *session,
2394				    struct evlist *evlist, perf_event__handler_t process)
2395{
2396	struct perf_header *header = &session->header;
2397	struct perf_record_header_feature *fe;
2398	struct feat_fd ff;
2399	size_t sz, sz_hdr;
2400	int feat, ret;
2401
2402	sz_hdr = sizeof(fe->header);
2403	sz = sizeof(union perf_event);
2404	/* get a nice alignment */
2405	sz = PERF_ALIGN(sz, page_size);
2406
2407	memset(&ff, 0, sizeof(ff));
2408
2409	ff.buf = malloc(sz);
2410	if (!ff.buf)
2411		return -ENOMEM;
2412
2413	ff.size = sz - sz_hdr;
2414	ff.ph = &session->header;
2415
2416	for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
2417		if (!feat_ops[feat].synthesize) {
2418			pr_debug("No record header feature for header :%d\n", feat);
2419			continue;
2420		}
2421
2422		ff.offset = sizeof(*fe);
2423
2424		ret = feat_ops[feat].write(&ff, evlist);
2425		if (ret || ff.offset <= (ssize_t)sizeof(*fe)) {
2426			pr_debug("Error writing feature\n");
2427			continue;
2428		}
2429		/* ff.buf may have changed due to realloc in do_write() */
2430		fe = ff.buf;
2431		memset(fe, 0, sizeof(*fe));
2432
2433		fe->feat_id = feat;
2434		fe->header.type = PERF_RECORD_HEADER_FEATURE;
2435		fe->header.size = ff.offset;
2436
2437		ret = process(tool, ff.buf, NULL, NULL);
2438		if (ret) {
2439			free(ff.buf);
2440			return ret;
2441		}
2442	}
2443
2444	/* Send HEADER_LAST_FEATURE mark. */
2445	fe = ff.buf;
2446	fe->feat_id     = HEADER_LAST_FEATURE;
2447	fe->header.type = PERF_RECORD_HEADER_FEATURE;
2448	fe->header.size = sizeof(*fe);
2449
2450	ret = process(tool, ff.buf, NULL, NULL);
2451
2452	free(ff.buf);
2453	return ret;
2454}
2455
2456int perf_event__synthesize_for_pipe(const struct perf_tool *tool,
2457				    struct perf_session *session,
2458				    struct perf_data *data,
2459				    perf_event__handler_t process)
2460{
2461	int err;
2462	int ret = 0;
2463	struct evlist *evlist = session->evlist;
2464
2465	/*
2466	 * We need to synthesize events first, because some
2467	 * features works on top of them (on report side).
2468	 */
2469	err = perf_event__synthesize_attrs(tool, evlist, process);
2470	if (err < 0) {
2471		pr_err("Couldn't synthesize attrs.\n");
2472		return err;
2473	}
2474	ret += err;
2475
2476	err = perf_event__synthesize_features(tool, session, evlist, process);
2477	if (err < 0) {
2478		pr_err("Couldn't synthesize features.\n");
2479		return err;
2480	}
2481	ret += err;
2482
2483#ifdef HAVE_LIBTRACEEVENT
2484	if (have_tracepoints(&evlist->core.entries)) {
2485		int fd = perf_data__fd(data);
2486
2487		/*
2488		 * FIXME err <= 0 here actually means that
2489		 * there were no tracepoints so its not really
2490		 * an error, just that we don't need to
2491		 * synthesize anything.  We really have to
2492		 * return this more properly and also
2493		 * propagate errors that now are calling die()
2494		 */
2495		err = perf_event__synthesize_tracing_data(tool,	fd, evlist,
2496							  process);
2497		if (err <= 0) {
2498			pr_err("Couldn't record tracing data.\n");
2499			return err;
2500		}
2501		ret += err;
2502	}
2503#else
2504	(void)data;
2505#endif
2506
2507	return ret;
2508}
2509
2510int parse_synth_opt(char *synth)
2511{
2512	char *p, *q;
2513	int ret = 0;
2514
2515	if (synth == NULL)
2516		return -1;
2517
2518	for (q = synth; (p = strsep(&q, ",")); p = q) {
2519		if (!strcasecmp(p, "no") || !strcasecmp(p, "none"))
2520			return 0;
2521
2522		if (!strcasecmp(p, "all"))
2523			return PERF_SYNTH_ALL;
2524
2525		if (!strcasecmp(p, "task"))
2526			ret |= PERF_SYNTH_TASK;
2527		else if (!strcasecmp(p, "mmap"))
2528			ret |= PERF_SYNTH_TASK | PERF_SYNTH_MMAP;
2529		else if (!strcasecmp(p, "cgroup"))
2530			ret |= PERF_SYNTH_CGROUP;
2531		else
2532			return -1;
2533	}
2534
2535	return ret;
2536}
~/ Read-only file preview.