^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <sys/param.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <perf/cpumap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <perf/evlist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <perf/mmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "dso.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "env.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "parse-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "trace-event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "evlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "evsel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "thread_map.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "machine.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "map.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "record.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "util/mmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "util/synthetic-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "thread.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "tests.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define BUFSZ 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define READLEN 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u64 done[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) size_t done_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static unsigned int hex(char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (c >= '0' && c <= '9')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return c - '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (c >= 'a' && c <= 'f')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return c - 'a' + 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return c - 'A' + 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static size_t read_objdump_chunk(const char **line, unsigned char **buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) size_t *buf_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) size_t bytes_read = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned char *chunk_start = *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Read bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) while (*buf_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) char c1, c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Get 2 hex digits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) c1 = *(*line)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!isxdigit(c1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) c2 = *(*line)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (!isxdigit(c2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Store byte and advance buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) **buf = (hex(c1) << 4) | hex(c2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) (*buf)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) (*buf_len)--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) bytes_read++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* End of chunk? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (isspace(**line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * objdump will display raw insn as LE if code endian
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * is LE and bytes_per_chunk > 1. In that case reverse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * the chunk we just read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * see disassemble_bytes() at binutils/objdump.c for details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * how objdump chooses display endian)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (bytes_read > 1 && !bigendian()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned char *chunk_end = chunk_start + bytes_read - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned char tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) while (chunk_start < chunk_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) tmp = *chunk_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *chunk_start = *chunk_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *chunk_end = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) chunk_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) chunk_end--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return bytes_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static size_t read_objdump_line(const char *line, unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) size_t buf_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) const char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) size_t ret, bytes_read = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Skip to a colon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) p = strchr(line, ':');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* Skip initial spaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (!isspace(*p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ret = read_objdump_chunk(&p, &buf, &buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) bytes_read += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) } while (ret > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* return number of successfully read bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return bytes_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) char *line = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) size_t line_len, off_last = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u64 addr, last_addr = start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) while (off_last < *len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) size_t off, read_bytes, written_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned char tmp[BUFSZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ret = getline(&line, &line_len, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (feof(f))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) pr_debug("getline failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* read objdump data into temporary buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) read_bytes = read_objdump_line(line, tmp, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (!read_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (sscanf(line, "%"PRIx64, &addr) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (addr < last_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) pr_debug("addr going backwards, read beyond section?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) last_addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* copy it from temporary buffer to 'buf' according
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * to address on current objdump line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) off = addr - start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (off >= *len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) written_bytes = MIN(read_bytes, *len - off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) memcpy(buf + off, tmp, written_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) off_last = off + written_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* len returns number of bytes that could not be read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *len -= off_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) free(line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int read_via_objdump(const char *filename, u64 addr, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) char cmd[PATH_MAX * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) const char *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) FILE *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) fmt = "%s -z -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (ret <= 0 || (size_t)ret >= sizeof(cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) pr_debug("Objdump command is: %s\n", cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* Ignore objdump errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) strcat(cmd, " 2>/dev/null");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) f = popen(cmd, "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) pr_debug("popen failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = read_objdump_output(f, buf, &len, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) pr_debug("objdump read too few bytes: %zd\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ret = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) pclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static void dump_buf(unsigned char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) pr_debug("0x%02x ", buf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (i % 16 == 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) pr_debug("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) pr_debug("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int read_object_code(u64 addr, size_t len, u8 cpumode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct thread *thread, struct state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct addr_location al;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) unsigned char buf1[BUFSZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) unsigned char buf2[BUFSZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) size_t ret_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) u64 objdump_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) const char *objdump_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) char decomp_name[KMOD_DECOMP_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) bool decomp = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!thread__find_map(thread, cpumode, addr, &al) || !al.map->dso) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) pr_debug("Hypervisor address can not be resolved - skipping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) pr_debug("thread__find_map failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) pr_debug("File is: %s\n", al.map->dso->long_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) !dso__is_kcore(al.map->dso)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) pr_debug("Unexpected kernel address - skipping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) pr_debug("On file address is: %#"PRIx64"\n", al.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (len > BUFSZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) len = BUFSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* Do not go off the map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (addr + len > al.map->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) len = al.map->end - addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* Read the object code using perf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ret_len = dso__data_read_offset(al.map->dso, thread->maps->machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) al.addr, buf1, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (ret_len != len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) pr_debug("dso__data_read_offset failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * Converting addresses for use by objdump requires more information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * map__load() does that. See map__rip_2objdump() for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (map__load(al.map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* objdump struggles with kcore - try each map only once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (dso__is_kcore(al.map->dso)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) size_t d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) for (d = 0; d < state->done_cnt; d++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (state->done[d] == al.map->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) pr_debug("kcore map tested already");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) pr_debug(" - skipping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (state->done_cnt >= ARRAY_SIZE(state->done)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) pr_debug("Too many kcore maps - skipping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) state->done[state->done_cnt++] = al.map->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) objdump_name = al.map->dso->long_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (dso__needs_decompress(al.map->dso)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (dso__decompress_kmodule_path(al.map->dso, objdump_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) decomp_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) sizeof(decomp_name)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) pr_debug("decompression failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) decomp = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) objdump_name = decomp_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* Read the object code using objdump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) objdump_addr = map__rip_2objdump(al.map, al.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (decomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) unlink(objdump_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * The kernel maps are inaccurate - assume objdump is right in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * that case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (cpumode == PERF_RECORD_MISC_KERNEL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) cpumode == PERF_RECORD_MISC_GUEST_KERNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) len -= ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) pr_debug("Reducing len to %zu\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) } else if (dso__is_kcore(al.map->dso)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * objdump cannot handle very large segments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * that may be found in kcore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) pr_debug("objdump failed for kcore");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) pr_debug(" - skipping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) pr_debug("read_via_objdump failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* The results should be identical */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (memcmp(buf1, buf2, len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) pr_debug("Bytes read differ from those read by objdump\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) pr_debug("buf1 (dso):\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) dump_buf(buf1, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) pr_debug("buf2 (objdump):\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) dump_buf(buf2, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) pr_debug("Bytes read match those read by objdump\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static int process_sample_event(struct machine *machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) union perf_event *event, struct state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct perf_sample sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct thread *thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (perf_evlist__parse_sample(evlist, event, &sample)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) pr_debug("perf_evlist__parse_sample failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) thread = machine__findnew_thread(machine, sample.pid, sample.tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!thread) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) pr_debug("machine__findnew_thread failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ret = read_object_code(sample.ip, READLEN, sample.cpumode, thread, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) thread__put(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int process_event(struct machine *machine, struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) union perf_event *event, struct state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (event->header.type == PERF_RECORD_SAMPLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return process_sample_event(machine, evlist, event, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (event->header.type == PERF_RECORD_THROTTLE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) event->header.type == PERF_RECORD_UNTHROTTLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (event->header.type < PERF_RECORD_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) ret = machine__process_event(machine, event, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) pr_debug("machine__process_event failed, event type %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) event->header.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static int process_events(struct machine *machine, struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) struct state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) union perf_event *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct mmap *md;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) for (i = 0; i < evlist->core.nr_mmaps; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) md = &evlist->mmap[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (perf_mmap__read_init(&md->core) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) while ((event = perf_mmap__read_event(&md->core)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) ret = process_event(machine, evlist, event, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) perf_mmap__consume(&md->core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) perf_mmap__read_done(&md->core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static int comp(const void *a, const void *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return *(int *)a - *(int *)b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static void do_sort_something(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) int buf[40960], i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) for (i = 0; i < (int)ARRAY_SIZE(buf); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) buf[i] = ARRAY_SIZE(buf) - i - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) qsort(buf, ARRAY_SIZE(buf), sizeof(int), comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) for (i = 0; i < (int)ARRAY_SIZE(buf); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (buf[i] != i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pr_debug("qsort failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static void sort_something(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) for (i = 0; i < 10; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) do_sort_something();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static void syscall_something(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int pipefd[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) for (i = 0; i < 1000; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (pipe(pipefd) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) pr_debug("pipe failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) close(pipefd[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) close(pipefd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static void fs_something(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) const char *test_file_name = "temp-perf-code-reading-test-file--";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) FILE *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) for (i = 0; i < 1000; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) f = fopen(test_file_name, "w+");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) fclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) unlink(test_file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) #ifdef __s390x__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) #include "header.h" // for get_cpuid()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static const char *do_determine_event(bool excl_kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) const char *event = excl_kernel ? "cycles:u" : "cycles";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) #ifdef __s390x__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) char cpuid[128], model[16], model_c[16], cpum_cf_v[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) unsigned int family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int ret, cpum_cf_a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (get_cpuid(cpuid, sizeof(cpuid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) goto out_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%x", &family, model_c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) model, cpum_cf_v, &cpum_cf_a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (ret != 5) /* Not available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) goto out_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (excl_kernel && (cpum_cf_a & 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (!excl_kernel && (cpum_cf_a & 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* Fall through: missing authorization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) out_clocks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) event = excl_kernel ? "cpu-clock:u" : "cpu-clock";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static void do_something(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) fs_something();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) sort_something();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) syscall_something();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) TEST_CODE_READING_OK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) TEST_CODE_READING_NO_VMLINUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) TEST_CODE_READING_NO_KCORE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) TEST_CODE_READING_NO_ACCESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) TEST_CODE_READING_NO_KERNEL_OBJ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static int do_test_code_reading(bool try_kcore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct machine *machine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct thread *thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct record_opts opts = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) .mmap_pages = UINT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) .user_freq = UINT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) .user_interval = ULLONG_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) .freq = 500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) .target = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) .uses_mmap = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) struct state state = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) .done_cnt = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct perf_thread_map *threads = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct perf_cpu_map *cpus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct evlist *evlist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) struct evsel *evsel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) int err = -1, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) pid_t pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) struct map *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) bool have_vmlinux, have_kcore, excl_kernel = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) pid = getpid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) machine = machine__new_host();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) machine->env = &perf_env;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) ret = machine__create_kernel_maps(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) pr_debug("machine__create_kernel_maps failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* Force the use of kallsyms instead of vmlinux to try kcore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (try_kcore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) symbol_conf.kallsyms_name = "/proc/kallsyms";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) /* Load kernel map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) map = machine__kernel_map(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ret = map__load(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) pr_debug("map__load failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) have_vmlinux = dso__is_vmlinux(map->dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) have_kcore = dso__is_kcore(map->dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* 2nd time through we just try kcore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (try_kcore && !have_kcore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return TEST_CODE_READING_NO_KCORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* No point getting kernel events if there is no kernel object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (!have_vmlinux && !have_kcore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) excl_kernel = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) threads = thread_map__new_by_tid(pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (!threads) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) pr_debug("thread_map__new_by_tid failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ret = perf_event__synthesize_thread_map(NULL, threads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) perf_event__process, machine, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) pr_debug("perf_event__synthesize_thread_map failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) thread = machine__findnew_thread(machine, pid, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (!thread) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) pr_debug("machine__findnew_thread failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) cpus = perf_cpu_map__new(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (!cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) pr_debug("perf_cpu_map__new failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) const char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) evlist = evlist__new();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (!evlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) pr_debug("perf_evlist__new failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) perf_evlist__set_maps(&evlist->core, cpus, threads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) str = do_determine_event(excl_kernel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) pr_debug("Parsing event '%s'\n", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) ret = parse_events(evlist, str, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) pr_debug("parse_events failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) perf_evlist__config(evlist, &opts, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) evsel = evlist__first(evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) evsel->core.attr.comm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) evsel->core.attr.disabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) evsel->core.attr.enable_on_exec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ret = evlist__open(evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (!excl_kernel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) excl_kernel = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * Both cpus and threads are now owned by evlist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * and will be freed by following perf_evlist__set_maps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * call. Getting refference to keep them alive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) perf_cpu_map__get(cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) perf_thread_map__get(threads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) perf_evlist__set_maps(&evlist->core, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) evlist__delete(evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) evlist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (verbose > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) char errbuf[512];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) pr_debug("perf_evlist__open() failed!\n%s\n", errbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ret = evlist__mmap(evlist, UINT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) pr_debug("evlist__mmap failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) goto out_put;
^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) evlist__enable(evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) do_something();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) evlist__disable(evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) ret = process_events(machine, evlist, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (!have_vmlinux && !have_kcore && !try_kcore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) err = TEST_CODE_READING_NO_KERNEL_OBJ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) else if (!have_vmlinux && !try_kcore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) err = TEST_CODE_READING_NO_VMLINUX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) else if (excl_kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) err = TEST_CODE_READING_NO_ACCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) err = TEST_CODE_READING_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) out_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) thread__put(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (evlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) evlist__delete(evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) perf_cpu_map__put(cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) perf_thread_map__put(threads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) machine__delete_threads(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) machine__delete(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) int test__code_reading(struct test *test __maybe_unused, int subtest __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ret = do_test_code_reading(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ret = do_test_code_reading(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) case TEST_CODE_READING_OK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) case TEST_CODE_READING_NO_VMLINUX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) pr_debug("no vmlinux\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) case TEST_CODE_READING_NO_KCORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) pr_debug("no kcore\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) case TEST_CODE_READING_NO_ACCESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) pr_debug("no access\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) case TEST_CODE_READING_NO_KERNEL_OBJ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) pr_debug("no kernel obj\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }