1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/types.h> 2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdlib.h> 3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <unistd.h> 4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h> 5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <inttypes.h> 6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <ctype.h> 7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <string.h> 8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "parse-events.h" 10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "evlist.h" 11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "evsel.h" 12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "thread_map.h" 13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "cpumap.h" 14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "machine.h" 15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "event.h" 16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "thread.h" 17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "tests.h" 19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define BUFSZ 1024 21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define READLEN 128 22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct state { 24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 done[1024]; 25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t done_cnt; 26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic unsigned int hex(char c) 29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (c >= '0' && c <= '9') 31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return c - '0'; 32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (c >= 'a' && c <= 'f') 33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return c - 'a' + 10; 34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return c - 'A' + 10; 35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void read_objdump_line(const char *line, size_t line_len, void **buf, 38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t *len) 39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *p; 41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t i; 42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Skip to a colon */ 44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng p = strchr(line, ':'); 45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!p) 46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng i = p + 1 - line; 48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Read bytes */ 50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (*len) { 51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char c1, c2; 52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Skip spaces */ 54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (; i < line_len; i++) { 55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!isspace(line[i])) 56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Get 2 hex digits */ 59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (i >= line_len || !isxdigit(line[i])) 60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng c1 = line[i++]; 62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (i >= line_len || !isxdigit(line[i])) 63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng c2 = line[i++]; 65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Followed by a space */ 66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (i < line_len && line[i] && !isspace(line[i])) 67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Store byte */ 69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *(unsigned char *)*buf = (hex(c1) << 4) | hex(c2); 70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *buf += 1; 71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *len -= 1; 72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int read_objdump_output(FILE *f, void **buf, size_t *len) 76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *line = NULL; 78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t line_len; 79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ssize_t ret; 80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int err = 0; 81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (1) { 83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = getline(&line, &line_len, f); 84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (feof(f)) 85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) { 87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("getline failed\n"); 88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = -1; 89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng read_objdump_line(line, ret, buf, len); 92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(line); 95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return err; 97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int read_via_objdump(const char *filename, u64 addr, void *buf, 100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t len) 101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char cmd[PATH_MAX * 2]; 103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *fmt; 104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng FILE *f; 105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret; 106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fmt = "%s -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s"; 108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len, 109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng filename); 110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret <= 0 || (size_t)ret >= sizeof(cmd)) 111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("Objdump command is: %s\n", cmd); 114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Ignore objdump errors */ 116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng strcat(cmd, " 2>/dev/null"); 117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng f = popen(cmd, "r"); 119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!f) { 120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("popen failed\n"); 121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = read_objdump_output(f, &buf, &len); 125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (len) { 126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("objdump read too few bytes\n"); 127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!ret) 128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = len; 129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pclose(f); 132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int read_object_code(u64 addr, size_t len, u8 cpumode, 137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *thread, struct machine *machine, 138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct state *state) 139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct addr_location al; 141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned char buf1[BUFSZ]; 142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned char buf2[BUFSZ]; 143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t ret_len; 144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 objdump_addr; 145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret; 146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr, 150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng &al); 151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!al.map || !al.map->dso) { 152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("thread__find_addr_map failed\n"); 153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("File is: %s\n", al.map->dso->long_name); 157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng !dso__is_kcore(al.map->dso)) { 160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("Unexpected kernel address - skipping\n"); 161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("On file address is: %#"PRIx64"\n", al.addr); 165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (len > BUFSZ) 167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng len = BUFSZ; 168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Do not go off the map */ 170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (addr + len > al.map->end) 171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng len = al.map->end - addr; 172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Read the object code using perf */ 174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1, 175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng len); 176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret_len != len) { 177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("dso__data_read_offset failed\n"); 178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Converting addresses for use by objdump requires more information. 183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * map__load() does that. See map__rip_2objdump() for details. 184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map__load(al.map, NULL)) 186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* objdump struggles with kcore - try each map only once */ 189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dso__is_kcore(al.map->dso)) { 190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t d; 191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (d = 0; d < state->done_cnt; d++) { 193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (state->done[d] == al.map->start) { 194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("kcore map tested already"); 195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug(" - skipping\n"); 196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (state->done_cnt >= ARRAY_SIZE(state->done)) { 200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("Too many kcore maps - skipping\n"); 201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng state->done[state->done_cnt++] = al.map->start; 204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Read the object code using objdump */ 207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng objdump_addr = map__rip_2objdump(al.map, al.addr); 208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len); 209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret > 0) { 210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * The kernel maps are inaccurate - assume objdump is right in 212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * that case. 213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (cpumode == PERF_RECORD_MISC_KERNEL || 215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cpumode == PERF_RECORD_MISC_GUEST_KERNEL) { 216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng len -= ret; 217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (len) { 218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("Reducing len to %zu\n", len); 219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else if (dso__is_kcore(al.map->dso)) { 220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * objdump cannot handle very large segments 222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * that may be found in kcore. 223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("objdump failed for kcore"); 225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug(" - skipping\n"); 226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) { 233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("read_via_objdump failed\n"); 234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* The results should be identical */ 238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (memcmp(buf1, buf2, len)) { 239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("Bytes read differ from those read by objdump\n"); 240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("Bytes read match those read by objdump\n"); 243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_sample_event(struct machine *machine, 248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evlist *evlist, 249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng union perf_event *event, struct state *state) 250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample sample; 252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *thread; 253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u8 cpumode; 254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_evlist__parse_sample(evlist, event, &sample)) { 256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("perf_evlist__parse_sample failed\n"); 257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng thread = machine__findnew_thread(machine, sample.pid, sample.pid); 261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!thread) { 262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("machine__findnew_thread failed\n"); 263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return read_object_code(sample.ip, READLEN, cpumode, thread, machine, 269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng state); 270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_event(struct machine *machine, struct perf_evlist *evlist, 273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng union perf_event *event, struct state *state) 274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (event->header.type == PERF_RECORD_SAMPLE) 276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return process_sample_event(machine, evlist, event, state); 277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (event->header.type < PERF_RECORD_MAX) 279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return machine__process_event(machine, event); 280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_events(struct machine *machine, struct perf_evlist *evlist, 285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct state *state) 286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng union perf_event *event; 288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i, ret; 289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < evlist->nr_mmaps; i++) { 291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = process_event(machine, evlist, event, state); 293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_evlist__mmap_consume(evlist, i); 294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) 295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int comp(const void *a, const void *b) 302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return *(int *)a - *(int *)b; 304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void do_sort_something(void) 307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int buf[40960], i; 309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < (int)ARRAY_SIZE(buf); i++) 311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng buf[i] = ARRAY_SIZE(buf) - i - 1; 312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng qsort(buf, ARRAY_SIZE(buf), sizeof(int), comp); 314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < (int)ARRAY_SIZE(buf); i++) { 316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (buf[i] != i) { 317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("qsort failed\n"); 318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void sort_something(void) 324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < 10; i++) 328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng do_sort_something(); 329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void syscall_something(void) 332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int pipefd[2]; 334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < 1000; i++) { 337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pipe(pipefd) < 0) { 338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("pipe failed\n"); 339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng close(pipefd[1]); 342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng close(pipefd[0]); 343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void fs_something(void) 347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *test_file_name = "temp-perf-code-reading-test-file--"; 349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng FILE *f; 350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < 1000; i++) { 353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng f = fopen(test_file_name, "w+"); 354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (f) { 355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fclose(f); 356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unlink(test_file_name); 357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void do_something(void) 362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fs_something(); 364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sort_something(); 366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng syscall_something(); 368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengenum { 371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng TEST_CODE_READING_OK, 372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng TEST_CODE_READING_NO_VMLINUX, 373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng TEST_CODE_READING_NO_KCORE, 374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng TEST_CODE_READING_NO_ACCESS, 375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng TEST_CODE_READING_NO_KERNEL_OBJ, 376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int do_test_code_reading(bool try_kcore) 379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machines machines; 381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine; 382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *thread; 383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_record_opts opts = { 384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .mmap_pages = UINT_MAX, 385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .user_freq = UINT_MAX, 386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .user_interval = ULLONG_MAX, 387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .freq = 4000, 388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .target = { 389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .uses_mmap = true, 390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }, 391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct state state = { 393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .done_cnt = 0, 394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread_map *threads = NULL; 396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct cpu_map *cpus = NULL; 397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evlist *evlist = NULL; 398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel = NULL; 399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int err = -1, ret; 400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pid_t pid; 401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *map; 402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool have_vmlinux, have_kcore, excl_kernel = false; 403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pid = getpid(); 405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng machines__init(&machines); 407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng machine = &machines.host; 408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = machine__create_kernel_maps(machine); 410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) { 411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("machine__create_kernel_maps failed\n"); 412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Force the use of kallsyms instead of vmlinux to try kcore */ 416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (try_kcore) 417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng symbol_conf.kallsyms_name = "/proc/kallsyms"; 418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Load kernel map */ 420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map = machine->vmlinux_maps[MAP__FUNCTION]; 421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = map__load(map, NULL); 422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) { 423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("map__load failed\n"); 424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng have_vmlinux = dso__is_vmlinux(map->dso); 427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng have_kcore = dso__is_kcore(map->dso); 428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 2nd time through we just try kcore */ 430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (try_kcore && !have_kcore) 431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return TEST_CODE_READING_NO_KCORE; 432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* No point getting kernel events if there is no kernel object */ 434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!have_vmlinux && !have_kcore) 435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng excl_kernel = true; 436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads = thread_map__new_by_tid(pid); 438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!threads) { 439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("thread_map__new_by_tid failed\n"); 440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = perf_event__synthesize_thread_map(NULL, threads, 444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_event__process, machine); 445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) { 446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("perf_event__synthesize_thread_map failed\n"); 447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng thread = machine__findnew_thread(machine, pid, pid); 451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!thread) { 452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("machine__findnew_thread failed\n"); 453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cpus = cpu_map__new(NULL); 457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!cpus) { 458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("cpu_map__new failed\n"); 459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (1) { 463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *str; 464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng evlist = perf_evlist__new(); 466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!evlist) { 467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("perf_evlist__new failed\n"); 468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_evlist__set_maps(evlist, cpus, threads); 472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (excl_kernel) 474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng str = "cycles:u"; 475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng str = "cycles"; 477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("Parsing event '%s'\n", str); 478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = parse_events(evlist, str); 479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) { 480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("parse_events failed\n"); 481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_evlist__config(evlist, &opts); 485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng evsel = perf_evlist__first(evlist); 487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng evsel->attr.comm = 1; 489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng evsel->attr.disabled = 1; 490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng evsel->attr.enable_on_exec = 0; 491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = perf_evlist__open(evlist); 493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) { 494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!excl_kernel) { 495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng excl_kernel = true; 496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_evlist__delete(evlist); 497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng evlist = NULL; 498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("perf_evlist__open failed\n"); 501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = perf_evlist__mmap(evlist, UINT_MAX, false); 507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) { 508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("perf_evlist__mmap failed\n"); 509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_evlist__enable(evlist); 513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng do_something(); 515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_evlist__disable(evlist); 517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = process_events(machine, evlist, &state); 519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret < 0) 520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_err; 521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!have_vmlinux && !have_kcore && !try_kcore) 523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = TEST_CODE_READING_NO_KERNEL_OBJ; 524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else if (!have_vmlinux && !try_kcore) 525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = TEST_CODE_READING_NO_VMLINUX; 526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else if (excl_kernel) 527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = TEST_CODE_READING_NO_ACCESS; 528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = TEST_CODE_READING_OK; 530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_err: 531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (evlist) { 532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_evlist__munmap(evlist); 533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_evlist__close(evlist); 534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_evlist__delete(evlist); 535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (cpus) 537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cpu_map__delete(cpus); 538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (threads) 539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng thread_map__delete(threads); 540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng machines__destroy_kernel_maps(&machines); 541e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng machine__delete_threads(machine); 542e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng machines__exit(&machines); 543e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 544e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return err; 545e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 546e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 547e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint test__code_reading(void) 548e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 549e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret; 550e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 551e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = do_test_code_reading(false); 552e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!ret) 553e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = do_test_code_reading(true); 554e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 555e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng switch (ret) { 556e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case TEST_CODE_READING_OK: 557e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 558e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case TEST_CODE_READING_NO_VMLINUX: 559e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(stderr, " (no vmlinux)"); 560e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 561e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case TEST_CODE_READING_NO_KCORE: 562e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(stderr, " (no kcore)"); 563e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 564e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case TEST_CODE_READING_NO_ACCESS: 565e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(stderr, " (no access)"); 566e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 567e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case TEST_CODE_READING_NO_KERNEL_OBJ: 568e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(stderr, " (no kernel obj)"); 569e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 570e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng default: 571e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 572e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 573e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 574