Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf dso: Move read_symbol() from llvm/capstone to dso

Move the read_symbol function to dso.h, make the return type const and
add a mutable out_buf out parameter.

In future changes this will allow a code pointer to be returned without
necessary allocating memory.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexandre Ghiti <alexghiti@rivosinc.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.ibm.com>
Cc: Bill Wendling <morbo@google.com>
Cc: Charlie Jenkins <charlie@rivosinc.com>
Cc: Collin Funk <collin.funk1@gmail.com>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Dr. David Alan Gilbert <linux@treblig.org>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: Haibo Xu <haibo1.xu@intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Justin Stitt <justinstitt@google.com>
Cc: Li Huafei <lihuafei1@huawei.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Cc: Stephen Brennan <stephen.s.brennan@oracle.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
9518e10c 0e52f3f9

+97 -128
+11 -55
tools/perf/util/capstone.c
··· 215 215 } 216 216 #endif 217 217 218 - #ifdef HAVE_LIBCAPSTONE_SUPPORT 219 - static u8 * 220 - read_symbol(const char *filename, struct map *map, struct symbol *sym, 221 - u64 *len, bool *is_64bit) 222 - { 223 - struct dso *dso = map__dso(map); 224 - struct nscookie nsc; 225 - u64 start = map__rip_2objdump(map, sym->start); 226 - u64 end = map__rip_2objdump(map, sym->end); 227 - int fd, count; 228 - u8 *buf = NULL; 229 - struct find_file_offset_data data = { 230 - .ip = start, 231 - }; 232 - 233 - *is_64bit = false; 234 - 235 - nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); 236 - fd = open(filename, O_RDONLY); 237 - nsinfo__mountns_exit(&nsc); 238 - if (fd < 0) 239 - return NULL; 240 - 241 - if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data, 242 - is_64bit) == 0) 243 - goto err; 244 - 245 - *len = end - start; 246 - buf = malloc(*len); 247 - if (buf == NULL) 248 - goto err; 249 - 250 - count = pread(fd, buf, *len, data.offset); 251 - close(fd); 252 - fd = -1; 253 - 254 - if ((u64)count != *len) 255 - goto err; 256 - 257 - return buf; 258 - 259 - err: 260 - if (fd >= 0) 261 - close(fd); 262 - free(buf); 263 - return NULL; 264 - } 265 - #endif 266 - 267 218 int symbol__disassemble_capstone(const char *filename __maybe_unused, 268 219 struct symbol *sym __maybe_unused, 269 220 struct annotate_args *args __maybe_unused) ··· 222 271 #ifdef HAVE_LIBCAPSTONE_SUPPORT 223 272 struct annotation *notes = symbol__annotation(sym); 224 273 struct map *map = args->ms.map; 274 + struct dso *dso = map__dso(map); 225 275 u64 start = map__rip_2objdump(map, sym->start); 226 - u64 len; 227 276 u64 offset; 228 277 int i, count, free_count; 229 278 bool is_64bit = false; 230 279 bool needs_cs_close = false; 231 - u8 *buf = NULL; 280 + /* Malloc-ed buffer containing instructions read from disk. */ 281 + u8 *code_buf = NULL; 282 + /* Pointer to code to be disassembled. */ 283 + const u8 *buf; 284 + u64 buf_len; 232 285 csh handle; 233 286 cs_insn *insn = NULL; 234 287 char disasm_buf[512]; ··· 242 287 if (args->options->objdump_path) 243 288 return -1; 244 289 245 - buf = read_symbol(filename, map, sym, &len, &is_64bit); 290 + buf = dso__read_symbol(dso, filename, map, sym, 291 + &code_buf, &buf_len, &is_64bit); 246 292 if (buf == NULL) 247 293 return -1; 248 294 ··· 272 316 273 317 needs_cs_close = true; 274 318 275 - free_count = count = cs_disasm(handle, buf, len, start, len, &insn); 319 + free_count = count = cs_disasm(handle, buf, buf_len, start, buf_len, &insn); 276 320 for (i = 0, offset = 0; i < count; i++) { 277 321 int printed; 278 322 ··· 296 340 } 297 341 298 342 /* It failed in the middle: probably due to unknown instructions */ 299 - if (offset != len) { 343 + if (offset != buf_len) { 300 344 struct list_head *list = &notes->src->source; 301 345 302 346 /* Discard all lines and fallback to objdump */ ··· 315 359 if (free_count > 0) 316 360 cs_free(insn, free_count); 317 361 } 318 - free(buf); 362 + free(code_buf); 319 363 return count < 0 ? count : 0; 320 364 321 365 err:
+67
tools/perf/util/dso.c
··· 1798 1798 1799 1799 return perf_pid_map_tid(dso_name, &tid); 1800 1800 } 1801 + 1802 + struct find_file_offset_data { 1803 + u64 ip; 1804 + u64 offset; 1805 + }; 1806 + 1807 + /* This will be called for each PHDR in an ELF binary */ 1808 + static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg) 1809 + { 1810 + struct find_file_offset_data *data = arg; 1811 + 1812 + if (start <= data->ip && data->ip < start + len) { 1813 + data->offset = pgoff + data->ip - start; 1814 + return 1; 1815 + } 1816 + return 0; 1817 + } 1818 + 1819 + const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename, 1820 + const struct map *map, const struct symbol *sym, 1821 + u8 **out_buf, u64 *out_buf_len, bool *is_64bit) 1822 + { 1823 + struct nscookie nsc; 1824 + u64 start = map__rip_2objdump(map, sym->start); 1825 + u64 end = map__rip_2objdump(map, sym->end); 1826 + int fd, count; 1827 + u8 *buf = NULL; 1828 + size_t len; 1829 + struct find_file_offset_data data = { 1830 + .ip = start, 1831 + }; 1832 + 1833 + *out_buf = NULL; 1834 + *out_buf_len = 0; 1835 + *is_64bit = false; 1836 + 1837 + nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); 1838 + fd = open(symfs_filename, O_RDONLY); 1839 + nsinfo__mountns_exit(&nsc); 1840 + if (fd < 0) 1841 + return NULL; 1842 + 1843 + if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data, is_64bit) == 0) 1844 + goto err; 1845 + 1846 + len = end - start; 1847 + buf = malloc(len); 1848 + if (buf == NULL) 1849 + goto err; 1850 + 1851 + count = pread(fd, buf, len, data.offset); 1852 + close(fd); 1853 + fd = -1; 1854 + 1855 + if ((u64)count != len) 1856 + goto err; 1857 + 1858 + *out_buf = buf; 1859 + *out_buf_len = len; 1860 + return buf; 1861 + 1862 + err: 1863 + if (fd >= 0) 1864 + close(fd); 1865 + free(buf); 1866 + return NULL; 1867 + }
+4
tools/perf/util/dso.h
··· 924 924 return debuginfo__new(dso__long_name(dso)); 925 925 } 926 926 927 + const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename, 928 + const struct map *map, const struct symbol *sym, 929 + u8 **out_buf, u64 *out_buf_len, bool *is_64bit); 930 + 927 931 #endif /* __PERF_DSO */
+15 -73
tools/perf/util/llvm.c
··· 87 87 } 88 88 } 89 89 90 - struct find_file_offset_data { 91 - u64 ip; 92 - u64 offset; 93 - }; 94 - 95 - /* This will be called for each PHDR in an ELF binary */ 96 - static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg) 97 - { 98 - struct find_file_offset_data *data = arg; 99 - 100 - if (start <= data->ip && data->ip < start + len) { 101 - data->offset = pgoff + data->ip - start; 102 - return 1; 103 - } 104 - return 0; 105 - } 106 - 107 - static u8 * 108 - read_symbol(const char *filename, struct map *map, struct symbol *sym, 109 - u64 *len, bool *is_64bit) 110 - { 111 - struct dso *dso = map__dso(map); 112 - struct nscookie nsc; 113 - u64 start = map__rip_2objdump(map, sym->start); 114 - u64 end = map__rip_2objdump(map, sym->end); 115 - int fd, count; 116 - u8 *buf = NULL; 117 - struct find_file_offset_data data = { 118 - .ip = start, 119 - }; 120 - 121 - *is_64bit = false; 122 - 123 - nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); 124 - fd = open(filename, O_RDONLY); 125 - nsinfo__mountns_exit(&nsc); 126 - if (fd < 0) 127 - return NULL; 128 - 129 - if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data, 130 - is_64bit) == 0) 131 - goto err; 132 - 133 - *len = end - start; 134 - buf = malloc(*len); 135 - if (buf == NULL) 136 - goto err; 137 - 138 - count = pread(fd, buf, *len, data.offset); 139 - close(fd); 140 - fd = -1; 141 - 142 - if ((u64)count != *len) 143 - goto err; 144 - 145 - return buf; 146 - 147 - err: 148 - if (fd >= 0) 149 - close(fd); 150 - free(buf); 151 - return NULL; 152 - } 153 - #endif 154 - 155 90 /* 156 91 * Whenever LLVM wants to resolve an address into a symbol, it calls this 157 92 * callback. We don't ever actually _return_ anything (in particular, because ··· 95 160 * should add some textual annotation for after the instruction. The caller 96 161 * will use this information to add the actual annotation. 97 162 */ 98 - #ifdef HAVE_LIBLLVM_SUPPORT 99 163 struct symbol_lookup_storage { 100 164 u64 branch_addr; 101 165 u64 pcrel_load_addr; ··· 125 191 struct map *map = args->ms.map; 126 192 struct dso *dso = map__dso(map); 127 193 u64 start = map__rip_2objdump(map, sym->start); 128 - u8 *buf; 129 - u64 len; 194 + /* Malloc-ed buffer containing instructions read from disk. */ 195 + u8 *code_buf = NULL; 196 + /* Pointer to code to be disassembled. */ 197 + const u8 *buf; 198 + u64 buf_len; 130 199 u64 pc; 131 200 bool is_64bit; 132 201 char disasm_buf[2048]; ··· 144 207 if (args->options->objdump_path) 145 208 return -1; 146 209 147 - buf = read_symbol(filename, map, sym, &len, &is_64bit); 210 + buf = dso__read_symbol(dso, filename, map, sym, 211 + &code_buf, &buf_len, &is_64bit); 148 212 if (buf == NULL) 149 213 return -1; 150 214 ··· 197 259 annotation_line__add(&dl->al, &notes->src->source); 198 260 199 261 pc = start; 200 - for (u64 offset = 0; offset < len; ) { 262 + for (u64 offset = 0; offset < buf_len; ) { 201 263 unsigned int ins_len; 202 264 203 265 storage.branch_addr = 0; 204 266 storage.pcrel_load_addr = 0; 205 267 206 - ins_len = LLVMDisasmInstruction(disasm, buf + offset, 207 - len - offset, pc, 268 + /* 269 + * LLVM's API has the code be disassembled as non-const, cast 270 + * here as we may be disassembling from mapped read-only memory. 271 + */ 272 + ins_len = LLVMDisasmInstruction(disasm, (u8 *)(buf + offset), 273 + buf_len - offset, pc, 208 274 disasm_buf, sizeof(disasm_buf)); 209 275 if (ins_len == 0) 210 276 goto err; ··· 266 324 267 325 err: 268 326 LLVMDisasmDispose(disasm); 269 - free(buf); 327 + free(code_buf); 270 328 free(line_storage); 271 329 return ret; 272 330 #else // HAVE_LIBLLVM_SUPPORT