^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include "util/debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include "util/dso.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "util/event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "util/evlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "util/machine.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "util/map.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "util/map_symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "util/branch.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "util/memswap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "util/namespaces.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "util/session.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "util/stat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "util/symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "util/synthetic-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "util/target.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "util/time-utils.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "util/cgroup.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <perf/evsel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <internal/cpumap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <perf/cpumap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <internal/lib.h> // page_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <internal/threadmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <perf/threadmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <symbol/kallsyms.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <dirent.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <api/fs/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <api/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define DEFAULT_PROC_MAP_PARSE_TIMEOUT 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned int proc_map_timeout = DEFAULT_PROC_MAP_PARSE_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int perf_tool__process_synth_event(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct machine *machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct perf_sample synth_sample = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .pid = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .tid = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .time = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .stream_id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .cpu = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .period = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return process(tool, event, &synth_sample, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * Assumes that the first 4095 bytes of /proc/pid/stat contains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * the comm, tgid and ppid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pid_t *tgid, pid_t *ppid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) char bf[4096];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) size_t size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ssize_t n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) char *name, *tgids, *ppids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *tgid = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *ppid = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) snprintf(bf, sizeof(bf), "/proc/%d/status", pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) fd = open(bf, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) pr_debug("couldn't open %s\n", bf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) n = read(fd, bf, sizeof(bf) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (n <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) bf[n] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) name = strstr(bf, "Name:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) tgids = strstr(bf, "Tgid:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ppids = strstr(bf, "PPid:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) char *nl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) name = skip_spaces(name + 5); /* strlen("Name:") */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) nl = strchr(name, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (nl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *nl = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) size = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (size >= len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) size = len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) memcpy(comm, name, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) comm[size] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pr_debug("Name: string not found for pid %d\n", pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (tgids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) tgids += 5; /* strlen("Tgid:") */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *tgid = atoi(tgids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) pr_debug("Tgid: string not found for pid %d\n", pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (ppids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ppids += 5; /* strlen("PPid:") */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) *ppid = atoi(ppids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) pr_debug("PPid: string not found for pid %d\n", pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct machine *machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) pid_t *tgid, pid_t *ppid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) *ppid = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) memset(&event->comm, 0, sizeof(event->comm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (machine__is_host(machine)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (perf_event__get_comm_ids(pid, event->comm.comm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) sizeof(event->comm.comm),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) tgid, ppid) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *tgid = machine->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (*tgid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) event->comm.pid = *tgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) event->comm.header.type = PERF_RECORD_COMM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) size = strlen(event->comm.comm) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) size = PERF_ALIGN(size, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) memset(event->comm.comm + size, 0, machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) event->comm.header.size = (sizeof(event->comm) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) (sizeof(event->comm.comm) - size) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) event->comm.tid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) pid_t perf_event__synthesize_comm(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) union perf_event *event, pid_t pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) pid_t tgid, ppid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return tgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static void perf_event__get_ns_link_info(pid_t pid, const char *ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct perf_ns_link_info *ns_link_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct stat64 st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) char proc_ns[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) sprintf(proc_ns, "/proc/%u/ns/%s", pid, ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (stat64(proc_ns, &st) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ns_link_info->dev = st.st_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ns_link_info->ino = st.st_ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int perf_event__synthesize_namespaces(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) pid_t pid, pid_t tgid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct perf_ns_link_info *ns_link_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!tool || !tool->namespace_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) memset(&event->namespaces, 0, (sizeof(event->namespaces) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) machine->id_hdr_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) event->namespaces.pid = tgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) event->namespaces.tid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) event->namespaces.nr_namespaces = NR_NAMESPACES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ns_link_info = event->namespaces.link_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) for (idx = 0; idx < event->namespaces.nr_namespaces; idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) perf_event__get_ns_link_info(pid, perf_ns__name(idx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) &ns_link_info[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) event->namespaces.header.type = PERF_RECORD_NAMESPACES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) event->namespaces.header.size = (sizeof(event->namespaces) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int perf_event__synthesize_fork(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pid_t pid, pid_t tgid, pid_t ppid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * for main thread set parent to ppid from status file. For other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * threads set parent pid to main thread. ie., assume main thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * spawns all threads in a process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (tgid == pid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) event->fork.ppid = ppid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) event->fork.ptid = ppid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) event->fork.ppid = tgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) event->fork.ptid = tgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) event->fork.pid = tgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) event->fork.tid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) event->fork.header.type = PERF_RECORD_FORK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) event->fork.header.misc = PERF_RECORD_MISC_FORK_EXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static bool read_proc_maps_line(struct io *io, __u64 *start, __u64 *end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u32 *prot, u32 *flags, __u64 *offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) u32 *maj, u32 *min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) __u64 *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ssize_t pathname_size, char *pathname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) __u64 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) char *start_pathname = pathname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (io__get_hex(io, start) != '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (io__get_hex(io, end) != ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* map protection and flags bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *prot = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ch = io__get_char(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (ch == 'r')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) *prot |= PROT_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) else if (ch != '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ch = io__get_char(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ch == 'w')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *prot |= PROT_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) else if (ch != '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ch = io__get_char(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (ch == 'x')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *prot |= PROT_EXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) else if (ch != '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ch = io__get_char(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (ch == 's')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) *flags = MAP_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) else if (ch == 'p')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) *flags = MAP_PRIVATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (io__get_char(io) != ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (io__get_hex(io, offset) != ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (io__get_hex(io, &temp) != ':')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) *maj = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (io__get_hex(io, &temp) != ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) *min = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ch = io__get_dec(io, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (ch != ' ') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) *pathname = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return ch == '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) ch = io__get_char(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) } while (ch == ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (ch < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (ch == '\0' || ch == '\n' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) (pathname + 1 - start_pathname) >= pathname_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) *pathname = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) *pathname++ = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ch = io__get_char(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int perf_event__synthesize_mmap_events(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) pid_t pid, pid_t tgid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct machine *machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) bool mmap_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) unsigned long long t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) char bf[BUFSIZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct io io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) bool truncation = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) unsigned long long timeout = proc_map_timeout * 1000000ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) const char *hugetlbfs_mnt = hugetlbfs__mountpoint();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) int hugetlbfs_mnt_len = hugetlbfs_mnt ? strlen(hugetlbfs_mnt) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (machine__is_default_guest(machine))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) snprintf(bf, sizeof(bf), "%s/proc/%d/task/%d/maps",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) machine->root_dir, pid, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) io.fd = open(bf, O_RDONLY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (io.fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * We raced with a task exiting - just return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) pr_debug("couldn't open %s\n", bf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) io__init(&io, io.fd, bf, sizeof(bf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) event->header.type = PERF_RECORD_MMAP2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) t = rdclock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) while (!io.eof) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static const char anonstr[] = "//anon";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) size_t size, aligned_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* ensure null termination since stack will be reused. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) event->mmap2.filename[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!read_proc_maps_line(&io,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) &event->mmap2.start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) &event->mmap2.len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) &event->mmap2.prot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) &event->mmap2.flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) &event->mmap2.pgoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) &event->mmap2.maj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) &event->mmap2.min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) &event->mmap2.ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) sizeof(event->mmap2.filename),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) event->mmap2.filename))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if ((rdclock() - t) > timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) pr_warning("Reading %s/proc/%d/task/%d/maps time out. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) "You may want to increase "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) "the time limit by --proc-map-timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) machine->root_dir, pid, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) truncation = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) event->mmap2.ino_generation = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (machine__is_host(machine))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) event->header.misc = PERF_RECORD_MISC_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) event->header.misc = PERF_RECORD_MISC_GUEST_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if ((event->mmap2.prot & PROT_EXEC) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!mmap_data || (event->mmap2.prot & PROT_READ) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (truncation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) event->header.misc |= PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (!strcmp(event->mmap2.filename, ""))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) strcpy(event->mmap2.filename, anonstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (hugetlbfs_mnt_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) !strncmp(event->mmap2.filename, hugetlbfs_mnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) hugetlbfs_mnt_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) strcpy(event->mmap2.filename, anonstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) event->mmap2.flags |= MAP_HUGETLB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) size = strlen(event->mmap2.filename) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) aligned_size = PERF_ALIGN(size, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) event->mmap2.len -= event->mmap.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) event->mmap2.header.size = (sizeof(event->mmap2) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) (sizeof(event->mmap2.filename) - aligned_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) memset(event->mmap2.filename + size, 0, machine->id_hdr_size +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) (aligned_size - size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) event->mmap2.header.size += machine->id_hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) event->mmap2.pid = tgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) event->mmap2.tid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (perf_tool__process_synth_event(tool, event, machine, process) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (truncation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) close(io.fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) #ifdef HAVE_FILE_HANDLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static int perf_event__synthesize_cgroup(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) char *path, size_t mount_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) size_t event_size = sizeof(event->cgroup) - sizeof(event->cgroup.path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) size_t path_len = strlen(path) - mount_len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct file_handle fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) uint64_t cgroup_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) } handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int mount_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) while (path_len % sizeof(u64))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) path[mount_len + path_len++] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) memset(&event->cgroup, 0, event_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) event->cgroup.header.type = PERF_RECORD_CGROUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) event->cgroup.header.size = event_size + path_len + machine->id_hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) handle.fh.handle_bytes = sizeof(handle.cgroup_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (name_to_handle_at(AT_FDCWD, path, &handle.fh, &mount_id, 0) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) pr_debug("stat failed: %s\n", path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) event->cgroup.id = handle.cgroup_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) strncpy(event->cgroup.path, path + mount_len, path_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) memset(event->cgroup.path + path_len, 0, machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (perf_tool__process_synth_event(tool, event, machine, process) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) pr_debug("process synth event failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static int perf_event__walk_cgroup_tree(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) char *path, size_t mount_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) size_t pos = strlen(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) DIR *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct dirent *dent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (perf_event__synthesize_cgroup(tool, event, path, mount_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) process, machine) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) d = opendir(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (d == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pr_debug("failed to open directory: %s\n", path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) while ((dent = readdir(d)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (dent->d_type != DT_DIR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (!strcmp(dent->d_name, ".") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) !strcmp(dent->d_name, ".."))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* any sane path should be less than PATH_MAX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (strlen(path) + strlen(dent->d_name) + 1 >= PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (path[pos - 1] != '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) strcat(path, "/");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) strcat(path, dent->d_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) ret = perf_event__walk_cgroup_tree(tool, event, path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) mount_len, process, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) path[pos] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) closedir(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int perf_event__synthesize_cgroups(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) union perf_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) char cgrp_root[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) size_t mount_len; /* length of mount point in the path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (!tool || !tool->cgroup_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (cgroupfs_find_mountpoint(cgrp_root, PATH_MAX, "perf_event") < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) pr_debug("cannot find cgroup mount point\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) mount_len = strlen(cgrp_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* make sure the path starts with a slash (after mount point) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) strcat(cgrp_root, "/");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (perf_event__walk_cgroup_tree(tool, &event, cgrp_root, mount_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) process, machine) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) int perf_event__synthesize_cgroups(struct perf_tool *tool __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) perf_event__handler_t process __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct machine *machine __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) int perf_event__synthesize_modules(struct perf_tool *tool, perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct map *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct maps *maps = machine__kernel_maps(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) union perf_event *event = zalloc((sizeof(event->mmap) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) machine->id_hdr_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (event == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) pr_debug("Not enough memory synthesizing mmap event "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) "for kernel modules\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) event->header.type = PERF_RECORD_MMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * kernel uses 0 for user space maps, see kernel/perf_event.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * __perf_event_mmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (machine__is_host(machine))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) event->header.misc = PERF_RECORD_MISC_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) maps__for_each_entry(maps, pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (!__map__is_kmodule(pos))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) event->mmap.header.type = PERF_RECORD_MMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) event->mmap.header.size = (sizeof(event->mmap) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) (sizeof(event->mmap.filename) - size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) memset(event->mmap.filename + size, 0, machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) event->mmap.header.size += machine->id_hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) event->mmap.start = pos->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) event->mmap.len = pos->end - pos->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) event->mmap.pid = machine->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) memcpy(event->mmap.filename, pos->dso->long_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) pos->dso->long_name_len + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (perf_tool__process_synth_event(tool, event, machine, process) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) free(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static int __event__synthesize_thread(union perf_event *comm_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) union perf_event *mmap_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) union perf_event *fork_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) union perf_event *namespaces_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) pid_t pid, int full, perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) struct perf_tool *tool, struct machine *machine, bool mmap_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) char filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) DIR *tasks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct dirent *dirent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) pid_t tgid, ppid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /* special case: only send one comm event using passed in pid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (!full) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) tgid = perf_event__synthesize_comm(tool, comm_event, pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) process, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (tgid == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (perf_event__synthesize_namespaces(tool, namespaces_event, pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) tgid, process, machine) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * send mmap only for thread group leader
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * see thread__init_maps()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (pid == tgid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) process, machine, mmap_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (machine__is_default_guest(machine))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) snprintf(filename, sizeof(filename), "%s/proc/%d/task",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) machine->root_dir, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) tasks = opendir(filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (tasks == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) pr_debug("couldn't open %s\n", filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) while ((dirent = readdir(tasks)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) pid_t _pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) _pid = strtol(dirent->d_name, &end, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (*end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (perf_event__prepare_comm(comm_event, _pid, machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) &tgid, &ppid) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ppid, process, machine) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (perf_event__synthesize_namespaces(tool, namespaces_event, _pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) tgid, process, machine) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * Send the prepared comm event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (perf_tool__process_synth_event(tool, comm_event, machine, process) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (_pid == pid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* process the parent's maps too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) process, machine, mmap_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) closedir(tasks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) int perf_event__synthesize_thread_map(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct perf_thread_map *threads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) struct machine *machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) bool mmap_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) union perf_event *comm_event, *mmap_event, *fork_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) union perf_event *namespaces_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) int err = -1, thread, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (comm_event == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (mmap_event == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) goto out_free_comm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (fork_event == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) goto out_free_mmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (namespaces_event == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) goto out_free_fork;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) for (thread = 0; thread < threads->nr; ++thread) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (__event__synthesize_thread(comm_event, mmap_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) fork_event, namespaces_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) perf_thread_map__pid(threads, thread), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) process, tool, machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) mmap_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * comm.pid is set to thread group id by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * perf_event__synthesize_comm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if ((int) comm_event->comm.pid != perf_thread_map__pid(threads, thread)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) bool need_leader = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /* is thread group leader in thread_map? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) for (j = 0; j < threads->nr; ++j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if ((int) comm_event->comm.pid == perf_thread_map__pid(threads, j)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) need_leader = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /* if not, generate events for it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (need_leader &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) __event__synthesize_thread(comm_event, mmap_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) fork_event, namespaces_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) comm_event->comm.pid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) process, tool, machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) mmap_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) free(namespaces_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) out_free_fork:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) free(fork_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) out_free_mmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) free(mmap_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) out_free_comm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) free(comm_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static int __perf_event__synthesize_threads(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) struct machine *machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) bool mmap_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) struct dirent **dirent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) int start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) union perf_event *comm_event, *mmap_event, *fork_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) union perf_event *namespaces_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) pid_t pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (comm_event == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (mmap_event == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) goto out_free_comm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (fork_event == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) goto out_free_mmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (namespaces_event == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) goto out_free_fork;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) for (i = start; i < start + num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (!isdigit(dirent[i]->d_name[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) pid = (pid_t)strtol(dirent[i]->d_name, &end, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) /* only interested in proper numerical dirents */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (*end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * We may race with exiting thread, so don't stop just because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * one thread couldn't be synthesized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) __event__synthesize_thread(comm_event, mmap_event, fork_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) namespaces_event, pid, 1, process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) tool, machine, mmap_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) free(namespaces_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) out_free_fork:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) free(fork_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) out_free_mmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) free(mmap_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) out_free_comm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) free(comm_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct synthesize_threads_arg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) struct perf_tool *tool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) perf_event__handler_t process;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) struct machine *machine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) bool mmap_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) struct dirent **dirent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) int num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) int start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static void *synthesize_threads_worker(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct synthesize_threads_arg *args = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) __perf_event__synthesize_threads(args->tool, args->process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) args->machine, args->mmap_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) args->dirent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) args->start, args->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) int perf_event__synthesize_threads(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) struct machine *machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) bool mmap_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) unsigned int nr_threads_synthesize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) struct synthesize_threads_arg *args = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) pthread_t *synthesize_threads = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) char proc_path[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct dirent **dirent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) int num_per_thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) int m, n, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) int thread_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) int base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (machine__is_default_guest(machine))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) n = scandir(proc_path, &dirent, 0, alphasort);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (n < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (nr_threads_synthesize == UINT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) thread_nr = sysconf(_SC_NPROCESSORS_ONLN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) thread_nr = nr_threads_synthesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (thread_nr <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) err = __perf_event__synthesize_threads(tool, process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) machine, mmap_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) dirent, base, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) goto free_dirent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (thread_nr > n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) thread_nr = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) synthesize_threads = calloc(sizeof(pthread_t), thread_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (synthesize_threads == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) goto free_dirent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) args = calloc(sizeof(*args), thread_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (args == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) goto free_threads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) num_per_thread = n / thread_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) m = n % thread_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) for (i = 0; i < thread_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) args[i].tool = tool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) args[i].process = process;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) args[i].machine = machine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) args[i].mmap_data = mmap_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) args[i].dirent = dirent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) for (i = 0; i < m; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) args[i].num = num_per_thread + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) args[i].start = i * args[i].num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (i != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) base = args[i-1].start + args[i-1].num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) for (j = i; j < thread_nr; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) args[j].num = num_per_thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) args[j].start = base + (j - i) * args[i].num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) for (i = 0; i < thread_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (pthread_create(&synthesize_threads[i], NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) synthesize_threads_worker, &args[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) goto out_join;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) out_join:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) for (i = 0; i < thread_nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) pthread_join(synthesize_threads[i], NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) free(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) free_threads:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) free(synthesize_threads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) free_dirent:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) for (i = 0; i < n; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) zfree(&dirent[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) free(dirent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) int __weak perf_event__synthesize_extra_kmaps(struct perf_tool *tool __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) perf_event__handler_t process __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) struct machine *machine __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) static int __perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct map *map = machine__kernel_map(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct kmap *kmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) union perf_event *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (map == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) kmap = map__kmap(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (!kmap->ref_reloc_sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * We should get this from /sys/kernel/sections/.text, but till that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * available use this, and after it is use this as a fallback for older
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) event = zalloc((sizeof(event->mmap) + machine->id_hdr_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (event == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) pr_debug("Not enough memory synthesizing mmap event "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) "for kernel modules\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (machine__is_host(machine)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * kernel uses PERF_RECORD_MISC_USER for user space maps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * see kernel/perf_event.c __perf_event_mmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) event->header.misc = PERF_RECORD_MISC_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) "%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) size = PERF_ALIGN(size, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) event->mmap.header.type = PERF_RECORD_MMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) event->mmap.header.size = (sizeof(event->mmap) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) event->mmap.pgoff = kmap->ref_reloc_sym->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) event->mmap.start = map->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) event->mmap.len = map->end - event->mmap.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) event->mmap.pid = machine->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) err = perf_tool__process_synth_event(tool, event, machine, process);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) free(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) err = __perf_event__synthesize_kernel_mmap(tool, process, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return perf_event__synthesize_extra_kmaps(tool, process, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) int perf_event__synthesize_thread_map2(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) struct perf_thread_map *threads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) union perf_event *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) int i, err, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) size = sizeof(event->thread_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) size += threads->nr * sizeof(event->thread_map.entries[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) event = zalloc(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (!event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) event->header.type = PERF_RECORD_THREAD_MAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) event->header.size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) event->thread_map.nr = threads->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) for (i = 0; i < threads->nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) struct perf_record_thread_map_entry *entry = &event->thread_map.entries[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) char *comm = perf_thread_map__comm(threads, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (!comm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) comm = (char *) "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) entry->pid = perf_thread_map__pid(threads, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) strncpy((char *) &entry->comm, comm, sizeof(entry->comm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) err = process(tool, event, NULL, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) free(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) static void synthesize_cpus(struct cpu_map_entries *cpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) struct perf_cpu_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) cpus->nr = map->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) for (i = 0; i < map->nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) cpus->cpu[i] = map->map[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) static void synthesize_mask(struct perf_record_record_cpu_map *mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) struct perf_cpu_map *map, int max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) mask->nr = BITS_TO_LONGS(max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) mask->long_size = sizeof(long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) for (i = 0; i < map->nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) set_bit(map->map[i], mask->mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) static size_t cpus_size(struct perf_cpu_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return sizeof(struct cpu_map_entries) + map->nr * sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) static size_t mask_size(struct perf_cpu_map *map, int *max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) *max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) for (i = 0; i < map->nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) /* bit possition of the cpu is + 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) int bit = map->map[i] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (bit > *max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) *max = bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return sizeof(struct perf_record_record_cpu_map) + BITS_TO_LONGS(*max) * sizeof(long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) size_t size_cpus, size_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) bool is_dummy = perf_cpu_map__empty(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) * Both array and mask data have variable size based
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) * on the number of cpus and their actual values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * The size of the 'struct perf_record_cpu_map_data' is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) * array = size of 'struct cpu_map_entries' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) * number of cpus * sizeof(u64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) * mask = size of 'struct perf_record_record_cpu_map' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * maximum cpu bit converted to size of longs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * and finaly + the size of 'struct perf_record_cpu_map_data'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) size_cpus = cpus_size(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) size_mask = mask_size(map, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (is_dummy || (size_cpus < size_mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) *size += size_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) *type = PERF_CPU_MAP__CPUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) *size += size_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) *type = PERF_CPU_MAP__MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) *size += sizeof(struct perf_record_cpu_map_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) *size = PERF_ALIGN(*size, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return zalloc(*size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf_cpu_map *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) u16 type, int max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) data->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) case PERF_CPU_MAP__CPUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) synthesize_cpus((struct cpu_map_entries *) data->data, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) case PERF_CPU_MAP__MASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) synthesize_mask((struct perf_record_record_cpu_map *)data->data, map, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) static struct perf_record_cpu_map *cpu_map_event__new(struct perf_cpu_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) size_t size = sizeof(struct perf_record_cpu_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) struct perf_record_cpu_map *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) int max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) u16 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) event = cpu_map_data__alloc(map, &size, &type, &max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (!event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) event->header.type = PERF_RECORD_CPU_MAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) event->header.size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) event->data.type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) cpu_map_data__synthesize(&event->data, map, type, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) int perf_event__synthesize_cpu_map(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) struct perf_cpu_map *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) struct perf_record_cpu_map *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) event = cpu_map_event__new(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (!event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) err = process(tool, (union perf_event *) event, NULL, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) free(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) int perf_event__synthesize_stat_config(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) struct perf_record_stat_config *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) int size, i = 0, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) size = sizeof(*event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) size += (PERF_STAT_CONFIG_TERM__MAX * sizeof(event->data[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) event = zalloc(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (!event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) event->header.type = PERF_RECORD_STAT_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) event->header.size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) event->nr = PERF_STAT_CONFIG_TERM__MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) #define ADD(__term, __val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) event->data[i].tag = PERF_STAT_CONFIG_TERM__##__term; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) event->data[i].val = __val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) ADD(AGGR_MODE, config->aggr_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) ADD(INTERVAL, config->interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) ADD(SCALE, config->scale)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) WARN_ONCE(i != PERF_STAT_CONFIG_TERM__MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) "stat config terms unbalanced\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) #undef ADD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) err = process(tool, (union perf_event *) event, NULL, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) free(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) int perf_event__synthesize_stat(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) u32 cpu, u32 thread, u64 id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) struct perf_counts_values *count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) struct perf_record_stat event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) event.header.type = PERF_RECORD_STAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) event.header.size = sizeof(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) event.header.misc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) event.id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) event.cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) event.thread = thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) event.val = count->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) event.ena = count->ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) event.run = count->run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) return process(tool, (union perf_event *) &event, NULL, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) int perf_event__synthesize_stat_round(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) u64 evtime, u64 type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) struct perf_record_stat_round event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) event.header.type = PERF_RECORD_STAT_ROUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) event.header.size = sizeof(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) event.header.misc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) event.time = evtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) event.type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) return process(tool, (union perf_event *) &event, NULL, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, u64 read_format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) size_t sz, result = sizeof(struct perf_record_sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (type & PERF_SAMPLE_IDENTIFIER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (type & PERF_SAMPLE_IP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (type & PERF_SAMPLE_TID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (type & PERF_SAMPLE_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (type & PERF_SAMPLE_ADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (type & PERF_SAMPLE_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (type & PERF_SAMPLE_STREAM_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (type & PERF_SAMPLE_CPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (type & PERF_SAMPLE_PERIOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (type & PERF_SAMPLE_READ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (read_format & PERF_FORMAT_GROUP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) sz = sample->read.group.nr *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) sizeof(struct sample_read_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) result += sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (type & PERF_SAMPLE_CALLCHAIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) sz = (sample->callchain->nr + 1) * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) result += sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (type & PERF_SAMPLE_RAW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) result += sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) result += sample->raw_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (type & PERF_SAMPLE_BRANCH_STACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) sz = sample->branch_stack->nr * sizeof(struct branch_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) /* nr, hw_idx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) sz += 2 * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) result += sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (type & PERF_SAMPLE_REGS_USER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) if (sample->user_regs.abi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) sz = hweight64(sample->user_regs.mask) * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) result += sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (type & PERF_SAMPLE_STACK_USER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) sz = sample->user_stack.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) if (sz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) result += sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (type & PERF_SAMPLE_WEIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (type & PERF_SAMPLE_DATA_SRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if (type & PERF_SAMPLE_TRANSACTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (type & PERF_SAMPLE_REGS_INTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (sample->intr_regs.abi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) sz = hweight64(sample->intr_regs.mask) * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) result += sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) if (type & PERF_SAMPLE_PHYS_ADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (type & PERF_SAMPLE_CGROUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) if (type & PERF_SAMPLE_AUX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) result += sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) result += sample->aux_sample.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) const struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) __u64 *array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) size_t sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * used for cross-endian analysis. See git commit 65014ab3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) * for why this goofiness is needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) union u64_swap u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) array = event->sample.array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) if (type & PERF_SAMPLE_IDENTIFIER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) *array = sample->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (type & PERF_SAMPLE_IP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) *array = sample->ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (type & PERF_SAMPLE_TID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) u.val32[0] = sample->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) u.val32[1] = sample->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) *array = u.val64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (type & PERF_SAMPLE_TIME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) *array = sample->time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) if (type & PERF_SAMPLE_ADDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) *array = sample->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if (type & PERF_SAMPLE_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) *array = sample->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (type & PERF_SAMPLE_STREAM_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) *array = sample->stream_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (type & PERF_SAMPLE_CPU) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) u.val32[0] = sample->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) u.val32[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) *array = u.val64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if (type & PERF_SAMPLE_PERIOD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) *array = sample->period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (type & PERF_SAMPLE_READ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) if (read_format & PERF_FORMAT_GROUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) *array = sample->read.group.nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) *array = sample->read.one.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) *array = sample->read.time_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) *array = sample->read.time_running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) if (read_format & PERF_FORMAT_GROUP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) sz = sample->read.group.nr *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) sizeof(struct sample_read_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) memcpy(array, sample->read.group.values, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) array = (void *)array + sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) *array = sample->read.one.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) if (type & PERF_SAMPLE_CALLCHAIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) sz = (sample->callchain->nr + 1) * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) memcpy(array, sample->callchain, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) array = (void *)array + sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (type & PERF_SAMPLE_RAW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) u.val32[0] = sample->raw_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) *array = u.val64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) array = (void *)array + sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) memcpy(array, sample->raw_data, sample->raw_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) array = (void *)array + sample->raw_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) if (type & PERF_SAMPLE_BRANCH_STACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) sz = sample->branch_stack->nr * sizeof(struct branch_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) /* nr, hw_idx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) sz += 2 * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) memcpy(array, sample->branch_stack, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) array = (void *)array + sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (type & PERF_SAMPLE_REGS_USER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) if (sample->user_regs.abi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) *array++ = sample->user_regs.abi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) sz = hweight64(sample->user_regs.mask) * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) memcpy(array, sample->user_regs.regs, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) array = (void *)array + sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) *array++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) if (type & PERF_SAMPLE_STACK_USER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) sz = sample->user_stack.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) *array++ = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) if (sz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) memcpy(array, sample->user_stack.data, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) array = (void *)array + sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) *array++ = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) if (type & PERF_SAMPLE_WEIGHT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) *array = sample->weight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) if (type & PERF_SAMPLE_DATA_SRC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) *array = sample->data_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (type & PERF_SAMPLE_TRANSACTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) *array = sample->transaction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) if (type & PERF_SAMPLE_REGS_INTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (sample->intr_regs.abi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) *array++ = sample->intr_regs.abi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) sz = hweight64(sample->intr_regs.mask) * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) memcpy(array, sample->intr_regs.regs, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) array = (void *)array + sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) *array++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) if (type & PERF_SAMPLE_PHYS_ADDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) *array = sample->phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) if (type & PERF_SAMPLE_CGROUP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) *array = sample->cgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) array++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) if (type & PERF_SAMPLE_AUX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) sz = sample->aux_sample.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) *array++ = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) memcpy(array, sample->aux_sample.data, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) array = (void *)array + sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_t process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) struct evlist *evlist, struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) union perf_event *ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) size_t nr = 0, i = 0, sz, max_nr, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) pr_debug2("Synthesizing id index\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) max_nr = (UINT16_MAX - sizeof(struct perf_record_id_index)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) sizeof(struct id_index_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) evlist__for_each_entry(evlist, evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) nr += evsel->core.ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) n = nr > max_nr ? max_nr : nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) sz = sizeof(struct perf_record_id_index) + n * sizeof(struct id_index_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) ev = zalloc(sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) if (!ev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) ev->id_index.header.type = PERF_RECORD_ID_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) ev->id_index.header.size = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) ev->id_index.nr = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) u32 j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) for (j = 0; j < evsel->core.ids; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) struct id_index_entry *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) struct perf_sample_id *sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) if (i >= n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) err = process(tool, ev, NULL, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) nr -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) e = &ev->id_index.entries[i++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) e->id = evsel->core.id[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) sid = perf_evlist__id2sid(evlist, e->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) if (!sid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) free(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) e->idx = sid->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) e->cpu = sid->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) e->tid = sid->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) sz = sizeof(struct perf_record_id_index) + nr * sizeof(struct id_index_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) ev->id_index.header.size = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) ev->id_index.nr = nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) err = process(tool, ev, NULL, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) free(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) struct target *target, struct perf_thread_map *threads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) perf_event__handler_t process, bool data_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) unsigned int nr_threads_synthesize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) if (target__has_task(target))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) else if (target__has_cpu(target))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) return perf_event__synthesize_threads(tool, process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) machine, data_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) nr_threads_synthesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) /* command specified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) int machine__synthesize_threads(struct machine *machine, struct target *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) struct perf_thread_map *threads, bool data_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) unsigned int nr_threads_synthesize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) return __machine__synthesize_threads(machine, NULL, target, threads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) perf_event__process, data_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) nr_threads_synthesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) static struct perf_record_event_update *event_update_event__new(size_t size, u64 type, u64 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) struct perf_record_event_update *ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) size += sizeof(*ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) size = PERF_ALIGN(size, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) ev = zalloc(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) if (ev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) ev->header.type = PERF_RECORD_EVENT_UPDATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) ev->header.size = (u16)size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) ev->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) ev->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) return ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) int perf_event__synthesize_event_update_unit(struct perf_tool *tool, struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) size_t size = strlen(evsel->unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) struct perf_record_event_update *ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->core.id[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) if (ev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) strlcpy(ev->data, evsel->unit, size + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) err = process(tool, (union perf_event *)ev, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) free(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) int perf_event__synthesize_event_update_scale(struct perf_tool *tool, struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) struct perf_record_event_update *ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) struct perf_record_event_update_scale *ev_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->core.id[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) if (ev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) ev_data = (struct perf_record_event_update_scale *)ev->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) ev_data->scale = evsel->scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) err = process(tool, (union perf_event *)ev, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) free(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) int perf_event__synthesize_event_update_name(struct perf_tool *tool, struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) struct perf_record_event_update *ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) size_t len = strlen(evsel->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->core.id[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) if (ev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) strlcpy(ev->data, evsel->name, len + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) err = process(tool, (union perf_event *)ev, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) free(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) size_t size = sizeof(struct perf_record_event_update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) struct perf_record_event_update *ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) int max, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) u16 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) if (!evsel->core.own_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) ev = cpu_map_data__alloc(evsel->core.own_cpus, &size, &type, &max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) if (!ev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) ev->header.type = PERF_RECORD_EVENT_UPDATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) ev->header.size = (u16)size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) ev->type = PERF_EVENT_UPDATE__CPUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) ev->id = evsel->core.id[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) cpu_map_data__synthesize((struct perf_record_cpu_map_data *)ev->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) evsel->core.own_cpus, type, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) err = process(tool, (union perf_event *)ev, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) free(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) int perf_event__synthesize_attrs(struct perf_tool *tool, struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) err = perf_event__synthesize_attr(tool, &evsel->core.attr, evsel->core.ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) evsel->core.id, process);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) pr_debug("failed to create perf header attribute\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) static bool has_unit(struct evsel *evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) return evsel->unit && *evsel->unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) static bool has_scale(struct evsel *evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) return evsel->scale != 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) int perf_event__synthesize_extra_attr(struct perf_tool *tool, struct evlist *evsel_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) perf_event__handler_t process, bool is_pipe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) * Synthesize other events stuff not carried within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) * attr event - unit, scale, name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) evlist__for_each_entry(evsel_list, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) if (!evsel->supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) * Synthesize unit and scale only if it's defined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (has_unit(evsel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) err = perf_event__synthesize_event_update_unit(tool, evsel, process);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) pr_err("Couldn't synthesize evsel unit.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) if (has_scale(evsel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) err = perf_event__synthesize_event_update_scale(tool, evsel, process);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) pr_err("Couldn't synthesize evsel evsel.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (evsel->core.own_cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) err = perf_event__synthesize_event_update_cpus(tool, evsel, process);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) pr_err("Couldn't synthesize evsel cpus.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) * Name is needed only for pipe output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) * perf.data carries event names.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) if (is_pipe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) err = perf_event__synthesize_event_update_name(tool, evsel, process);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) pr_err("Couldn't synthesize evsel name.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) int perf_event__synthesize_attr(struct perf_tool *tool, struct perf_event_attr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) u32 ids, u64 *id, perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) union perf_event *ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) size = sizeof(struct perf_event_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) size = PERF_ALIGN(size, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) size += sizeof(struct perf_event_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) size += ids * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) ev = zalloc(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) if (ev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) ev->attr.attr = *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) memcpy(ev->attr.id, id, ids * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) ev->attr.header.size = (u16)size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) if (ev->attr.header.size == size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) err = process(tool, ev, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) err = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) free(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) union perf_event ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) struct tracing_data *tdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) ssize_t size = 0, aligned_size = 0, padding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) struct feat_fd ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) * We are going to store the size of the data followed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) * by the data contents. Since the fd descriptor is a pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) * we cannot seek back to store the size of the data once
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) * we know it. Instead we:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) * - write the tracing data to the temp file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) * - get/write the data size to pipe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) * - write the tracing data from the temp file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) * to the pipe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) tdata = tracing_data_get(&evlist->core.entries, fd, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) if (!tdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) memset(&ev, 0, sizeof(ev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) size = tdata->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) aligned_size = PERF_ALIGN(size, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) padding = aligned_size - size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) ev.tracing_data.header.size = sizeof(ev.tracing_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) ev.tracing_data.size = aligned_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) process(tool, &ev, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) * The put function will copy all the tracing data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) * stored in temp file to the pipe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) tracing_data_put(tdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) ff = (struct feat_fd){ .fd = fd };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) if (write_padded(&ff, NULL, 0, padding))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) return aligned_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) int perf_event__synthesize_build_id(struct perf_tool *tool, struct dso *pos, u16 misc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) perf_event__handler_t process, struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) union perf_event ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) if (!pos->hit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) memset(&ev, 0, sizeof(ev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) len = pos->long_name_len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) len = PERF_ALIGN(len, NAME_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) memcpy(&ev.build_id.build_id, pos->bid.data, sizeof(pos->bid.data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) ev.build_id.header.misc = misc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) ev.build_id.pid = machine->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) ev.build_id.header.size = sizeof(ev.build_id) + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) return process(tool, &ev, NULL, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) int perf_event__synthesize_stat_events(struct perf_stat_config *config, struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) struct evlist *evlist, perf_event__handler_t process, bool attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) if (attrs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) err = perf_event__synthesize_attrs(tool, evlist, process);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) pr_err("Couldn't synthesize attrs.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) err = perf_event__synthesize_extra_attr(tool, evlist, process, attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) err = perf_event__synthesize_thread_map2(tool, evlist->core.threads, process, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) pr_err("Couldn't synthesize thread map.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) err = perf_event__synthesize_cpu_map(tool, evlist->core.cpus, process, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) pr_err("Couldn't synthesize thread map.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) err = perf_event__synthesize_stat_config(tool, config, process, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) pr_err("Couldn't synthesize config.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) extern const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) int perf_event__synthesize_features(struct perf_tool *tool, struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) struct evlist *evlist, perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) struct perf_header *header = &session->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) struct perf_record_header_feature *fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) struct feat_fd ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) size_t sz, sz_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) int feat, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) sz_hdr = sizeof(fe->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) sz = sizeof(union perf_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) /* get a nice alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) sz = PERF_ALIGN(sz, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) memset(&ff, 0, sizeof(ff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) ff.buf = malloc(sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) if (!ff.buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) ff.size = sz - sz_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) ff.ph = &session->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) if (!feat_ops[feat].synthesize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) pr_debug("No record header feature for header :%d\n", feat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) ff.offset = sizeof(*fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) ret = feat_ops[feat].write(&ff, evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) if (ret || ff.offset <= (ssize_t)sizeof(*fe)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) pr_debug("Error writing feature\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) /* ff.buf may have changed due to realloc in do_write() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) fe = ff.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) memset(fe, 0, sizeof(*fe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) fe->feat_id = feat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) fe->header.type = PERF_RECORD_HEADER_FEATURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) fe->header.size = ff.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) ret = process(tool, ff.buf, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) free(ff.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) /* Send HEADER_LAST_FEATURE mark. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) fe = ff.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) fe->feat_id = HEADER_LAST_FEATURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) fe->header.type = PERF_RECORD_HEADER_FEATURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) fe->header.size = sizeof(*fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) ret = process(tool, ff.buf, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) free(ff.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) }