perf dso: Support BPF programs in dso__read_symbol()
Set the buffer to the code in the BPF linear info. This enables BPF JIT code disassembly by LLVM and capstone. Move the common but minimal disassmble_bpf_image call to disassemble_objdump so that it is only called after falling back to the objdump option. Similarly move the disassmble_bpf function to disassemble_objdump and rename to disassmble_bpf_libbfd to make it clearer that this support relies on libbfd. 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>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
9518e10c2b
commit
aa04707f50
@@ -1521,6 +1521,12 @@ static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
|
||||
struct child_process objdump_process;
|
||||
int err;
|
||||
|
||||
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO)
|
||||
return symbol__disassemble_bpf_libbfd(sym, args);
|
||||
|
||||
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE)
|
||||
return symbol__disassemble_bpf_image(sym, args);
|
||||
|
||||
err = asprintf(&command,
|
||||
"%s %s%s --start-address=0x%016" PRIx64
|
||||
" --stop-address=0x%016" PRIx64
|
||||
@@ -1655,11 +1661,7 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
|
||||
|
||||
pr_debug("annotating [%p] %30s : [%p] %30s\n", dso, dso__long_name(dso), sym, sym->name);
|
||||
|
||||
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {
|
||||
return symbol__disassemble_bpf(sym, args);
|
||||
} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) {
|
||||
return symbol__disassemble_bpf_image(sym, args);
|
||||
} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) {
|
||||
if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) {
|
||||
return SYMBOL_ANNOTATE_ERRNO__COULDNT_DETERMINE_FILE_TYPE;
|
||||
} else if (dso__is_kcore(dso)) {
|
||||
kce.addr = map__rip_2objdump(map, sym->start);
|
||||
|
||||
+71
-35
@@ -1816,23 +1816,17 @@ static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename,
|
||||
const struct map *map, const struct symbol *sym,
|
||||
u8 **out_buf, u64 *out_buf_len, bool *is_64bit)
|
||||
static const u8 *__dso__read_symbol(struct dso *dso, const char *symfs_filename,
|
||||
u64 start, size_t len,
|
||||
u8 **out_buf, u64 *out_buf_len, bool *is_64bit)
|
||||
{
|
||||
struct nscookie nsc;
|
||||
u64 start = map__rip_2objdump(map, sym->start);
|
||||
u64 end = map__rip_2objdump(map, sym->end);
|
||||
int fd, count;
|
||||
u8 *buf = NULL;
|
||||
size_t len;
|
||||
int fd;
|
||||
ssize_t count;
|
||||
struct find_file_offset_data data = {
|
||||
.ip = start,
|
||||
};
|
||||
|
||||
*out_buf = NULL;
|
||||
*out_buf_len = 0;
|
||||
*is_64bit = false;
|
||||
u8 *code_buf = NULL;
|
||||
|
||||
nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
|
||||
fd = open(symfs_filename, O_RDONLY);
|
||||
@@ -1840,28 +1834,70 @@ const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename,
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data, is_64bit) == 0)
|
||||
goto err;
|
||||
|
||||
len = end - start;
|
||||
buf = malloc(len);
|
||||
if (buf == NULL)
|
||||
goto err;
|
||||
|
||||
count = pread(fd, buf, len, data.offset);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
|
||||
if ((u64)count != len)
|
||||
goto err;
|
||||
|
||||
*out_buf = buf;
|
||||
*out_buf_len = len;
|
||||
return buf;
|
||||
|
||||
err:
|
||||
if (fd >= 0)
|
||||
if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data, is_64bit) == 0) {
|
||||
close(fd);
|
||||
free(buf);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
code_buf = malloc(len);
|
||||
if (code_buf == NULL) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
count = pread(fd, code_buf, len, data.offset);
|
||||
close(fd);
|
||||
if ((u64)count != len) {
|
||||
free(code_buf);
|
||||
return NULL;
|
||||
}
|
||||
*out_buf = code_buf;
|
||||
*out_buf_len = len;
|
||||
return code_buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a symbol into memory for disassembly by a library like capstone of
|
||||
* libLLVM. If memory is allocated out_buf holds it.
|
||||
*/
|
||||
const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename,
|
||||
const struct map *map, const struct symbol *sym,
|
||||
u8 **out_buf, u64 *out_buf_len, bool *is_64bit)
|
||||
{
|
||||
u64 start = map__rip_2objdump(map, sym->start);
|
||||
u64 end = map__rip_2objdump(map, sym->end);
|
||||
size_t len = end - start;
|
||||
|
||||
*out_buf = NULL;
|
||||
*out_buf_len = 0;
|
||||
*is_64bit = false;
|
||||
|
||||
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) {
|
||||
/*
|
||||
* Note, there is fallback BPF image disassembly in the objdump
|
||||
* version but it currently does nothing.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {
|
||||
#ifdef HAVE_LIBBPF_SUPPORT
|
||||
struct bpf_prog_info_node *info_node;
|
||||
struct perf_bpil *info_linear;
|
||||
|
||||
*is_64bit = sizeof(void *) == sizeof(u64);
|
||||
info_node = perf_env__find_bpf_prog_info(dso__bpf_prog(dso)->env,
|
||||
dso__bpf_prog(dso)->id);
|
||||
if (!info_node) {
|
||||
errno = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
|
||||
return NULL;
|
||||
}
|
||||
info_linear = info_node->info_linear;
|
||||
assert(len <= info_linear->info.jited_prog_len);
|
||||
*out_buf_len = len;
|
||||
return (const u8 *)(uintptr_t)(info_linear->info.jited_prog_insns);
|
||||
#else
|
||||
pr_debug("No BPF program disassembly support\n");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
return __dso__read_symbol(dso, symfs_filename, start, len,
|
||||
out_buf, out_buf_len, is_64bit);
|
||||
}
|
||||
|
||||
@@ -448,8 +448,8 @@ out_close:
|
||||
return err;
|
||||
}
|
||||
|
||||
int symbol__disassemble_bpf(struct symbol *sym __maybe_unused,
|
||||
struct annotate_args *args __maybe_unused)
|
||||
int symbol__disassemble_bpf_libbfd(struct symbol *sym __maybe_unused,
|
||||
struct annotate_args *args __maybe_unused)
|
||||
{
|
||||
#ifdef HAVE_LIBBPF_SUPPORT
|
||||
struct annotation *notes = symbol__annotation(sym);
|
||||
|
||||
@@ -29,7 +29,7 @@ int libbfd__read_build_id(const char *filename, struct build_id *bid, bool block
|
||||
|
||||
int libbfd_filename__read_debuglink(const char *filename, char *debuglink, size_t size);
|
||||
|
||||
int symbol__disassemble_bpf(struct symbol *sym, struct annotate_args *args);
|
||||
int symbol__disassemble_bpf_libbfd(struct symbol *sym, struct annotate_args *args);
|
||||
|
||||
#else // !defined(HAVE_LIBBFD_SUPPORT)
|
||||
#include "annotate.h"
|
||||
@@ -72,8 +72,8 @@ static inline int libbfd_filename__read_debuglink(const char *filename __always_
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int symbol__disassemble_bpf(struct symbol *sym __always_unused,
|
||||
struct annotate_args *args __always_unused)
|
||||
static inline int symbol__disassemble_bpf_libbfd(struct symbol *sym __always_unused,
|
||||
struct annotate_args *args __always_unused)
|
||||
{
|
||||
return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user