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