Skip to content

Commit 9518e10

Browse files
captain5050acmel
authored andcommitted
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>
1 parent 0e52f3f commit 9518e10

4 files changed

Lines changed: 97 additions & 128 deletions

File tree

tools/perf/util/capstone.c

Lines changed: 11 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -215,69 +215,24 @@ static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg)
215215
}
216216
#endif
217217

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-
267218
int symbol__disassemble_capstone(const char *filename __maybe_unused,
268219
struct symbol *sym __maybe_unused,
269220
struct annotate_args *args __maybe_unused)
270221
{
271222
#ifdef HAVE_LIBCAPSTONE_SUPPORT
272223
struct annotation *notes = symbol__annotation(sym);
273224
struct map *map = args->ms.map;
225+
struct dso *dso = map__dso(map);
274226
u64 start = map__rip_2objdump(map, sym->start);
275-
u64 len;
276227
u64 offset;
277228
int i, count, free_count;
278229
bool is_64bit = false;
279230
bool needs_cs_close = false;
280-
u8 *buf = NULL;
231+
/* Malloc-ed buffer containing instructions read from disk. */
232+
u8 *code_buf = NULL;
233+
/* Pointer to code to be disassembled. */
234+
const u8 *buf;
235+
u64 buf_len;
281236
csh handle;
282237
cs_insn *insn = NULL;
283238
char disasm_buf[512];
@@ -287,7 +242,8 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
287242
if (args->options->objdump_path)
288243
return -1;
289244

290-
buf = read_symbol(filename, map, sym, &len, &is_64bit);
245+
buf = dso__read_symbol(dso, filename, map, sym,
246+
&code_buf, &buf_len, &is_64bit);
291247
if (buf == NULL)
292248
return -1;
293249

@@ -316,7 +272,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
316272

317273
needs_cs_close = true;
318274

319-
free_count = count = cs_disasm(handle, buf, len, start, len, &insn);
275+
free_count = count = cs_disasm(handle, buf, buf_len, start, buf_len, &insn);
320276
for (i = 0, offset = 0; i < count; i++) {
321277
int printed;
322278

@@ -340,7 +296,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
340296
}
341297

342298
/* It failed in the middle: probably due to unknown instructions */
343-
if (offset != len) {
299+
if (offset != buf_len) {
344300
struct list_head *list = &notes->src->source;
345301

346302
/* Discard all lines and fallback to objdump */
@@ -359,7 +315,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
359315
if (free_count > 0)
360316
cs_free(insn, free_count);
361317
}
362-
free(buf);
318+
free(code_buf);
363319
return count < 0 ? count : 0;
364320

365321
err:

tools/perf/util/dso.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,3 +1798,70 @@ bool is_perf_pid_map_name(const char *dso_name)
17981798

17991799
return perf_pid_map_tid(dso_name, &tid);
18001800
}
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+
}

tools/perf/util/dso.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,4 +924,8 @@ static inline struct debuginfo *dso__debuginfo(struct dso *dso)
924924
return debuginfo__new(dso__long_name(dso));
925925
}
926926

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+
927931
#endif /* __PERF_DSO */

tools/perf/util/llvm.c

Lines changed: 15 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -87,71 +87,6 @@ static void init_llvm(void)
8787
}
8888
}
8989

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-
15590
/*
15691
* Whenever LLVM wants to resolve an address into a symbol, it calls this
15792
* callback. We don't ever actually _return_ anything (in particular, because
@@ -160,7 +95,6 @@ read_symbol(const char *filename, struct map *map, struct symbol *sym,
16095
* should add some textual annotation for after the instruction. The caller
16196
* will use this information to add the actual annotation.
16297
*/
163-
#ifdef HAVE_LIBLLVM_SUPPORT
16498
struct symbol_lookup_storage {
16599
u64 branch_addr;
166100
u64 pcrel_load_addr;
@@ -191,8 +125,11 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
191125
struct map *map = args->ms.map;
192126
struct dso *dso = map__dso(map);
193127
u64 start = map__rip_2objdump(map, sym->start);
194-
u8 *buf;
195-
u64 len;
128+
/* Malloc-ed buffer containing instructions read from disk. */
129+
u8 *code_buf = NULL;
130+
/* Pointer to code to be disassembled. */
131+
const u8 *buf;
132+
u64 buf_len;
196133
u64 pc;
197134
bool is_64bit;
198135
char disasm_buf[2048];
@@ -207,7 +144,8 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
207144
if (args->options->objdump_path)
208145
return -1;
209146

210-
buf = read_symbol(filename, map, sym, &len, &is_64bit);
147+
buf = dso__read_symbol(dso, filename, map, sym,
148+
&code_buf, &buf_len, &is_64bit);
211149
if (buf == NULL)
212150
return -1;
213151

@@ -259,14 +197,18 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
259197
annotation_line__add(&dl->al, &notes->src->source);
260198

261199
pc = start;
262-
for (u64 offset = 0; offset < len; ) {
200+
for (u64 offset = 0; offset < buf_len; ) {
263201
unsigned int ins_len;
264202

265203
storage.branch_addr = 0;
266204
storage.pcrel_load_addr = 0;
267205

268-
ins_len = LLVMDisasmInstruction(disasm, buf + offset,
269-
len - offset, pc,
206+
/*
207+
* LLVM's API has the code be disassembled as non-const, cast
208+
* here as we may be disassembling from mapped read-only memory.
209+
*/
210+
ins_len = LLVMDisasmInstruction(disasm, (u8 *)(buf + offset),
211+
buf_len - offset, pc,
270212
disasm_buf, sizeof(disasm_buf));
271213
if (ins_len == 0)
272214
goto err;
@@ -324,7 +266,7 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
324266

325267
err:
326268
LLVMDisasmDispose(disasm);
327-
free(buf);
269+
free(code_buf);
328270
free(line_storage);
329271
return ret;
330272
#else // HAVE_LIBLLVM_SUPPORT

0 commit comments

Comments
 (0)