Skip to content

Commit aa04707

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

4 files changed

Lines changed: 80 additions & 42 deletions

File tree

tools/perf/util/disasm.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,12 @@ static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
15211521
struct child_process objdump_process;
15221522
int err;
15231523

1524+
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO)
1525+
return symbol__disassemble_bpf_libbfd(sym, args);
1526+
1527+
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE)
1528+
return symbol__disassemble_bpf_image(sym, args);
1529+
15241530
err = asprintf(&command,
15251531
"%s %s%s --start-address=0x%016" PRIx64
15261532
" --stop-address=0x%016" PRIx64
@@ -1655,11 +1661,7 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
16551661

16561662
pr_debug("annotating [%p] %30s : [%p] %30s\n", dso, dso__long_name(dso), sym, sym->name);
16571663

1658-
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {
1659-
return symbol__disassemble_bpf(sym, args);
1660-
} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) {
1661-
return symbol__disassemble_bpf_image(sym, args);
1662-
} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) {
1664+
if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) {
16631665
return SYMBOL_ANNOTATE_ERRNO__COULDNT_DETERMINE_FILE_TYPE;
16641666
} else if (dso__is_kcore(dso)) {
16651667
kce.addr = map__rip_2objdump(map, sym->start);

tools/perf/util/dso.c

Lines changed: 68 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1816,52 +1816,88 @@ static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg)
18161816
return 0;
18171817
}
18181818

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)
1819+
static const u8 *__dso__read_symbol(struct dso *dso, const char *symfs_filename,
1820+
u64 start, size_t len,
1821+
u8 **out_buf, u64 *out_buf_len, bool *is_64bit)
18221822
{
18231823
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;
1824+
int fd;
1825+
ssize_t count;
18291826
struct find_file_offset_data data = {
18301827
.ip = start,
18311828
};
1832-
1833-
*out_buf = NULL;
1834-
*out_buf_len = 0;
1835-
*is_64bit = false;
1829+
u8 *code_buf = NULL;
18361830

18371831
nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
18381832
fd = open(symfs_filename, O_RDONLY);
18391833
nsinfo__mountns_exit(&nsc);
18401834
if (fd < 0)
18411835
return NULL;
18421836

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);
1837+
if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data, is_64bit) == 0) {
1838+
close(fd);
1839+
return NULL;
1840+
}
1841+
code_buf = malloc(len);
1842+
if (code_buf == NULL) {
1843+
close(fd);
1844+
return NULL;
1845+
}
1846+
count = pread(fd, code_buf, len, data.offset);
18521847
close(fd);
1853-
fd = -1;
1848+
if ((u64)count != len) {
1849+
free(code_buf);
1850+
return NULL;
1851+
}
1852+
*out_buf = code_buf;
1853+
*out_buf_len = len;
1854+
return code_buf;
1855+
}
18541856

1855-
if ((u64)count != len)
1856-
goto err;
1857+
/*
1858+
* Read a symbol into memory for disassembly by a library like capstone of
1859+
* libLLVM. If memory is allocated out_buf holds it.
1860+
*/
1861+
const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename,
1862+
const struct map *map, const struct symbol *sym,
1863+
u8 **out_buf, u64 *out_buf_len, bool *is_64bit)
1864+
{
1865+
u64 start = map__rip_2objdump(map, sym->start);
1866+
u64 end = map__rip_2objdump(map, sym->end);
1867+
size_t len = end - start;
18571868

1858-
*out_buf = buf;
1859-
*out_buf_len = len;
1860-
return buf;
1869+
*out_buf = NULL;
1870+
*out_buf_len = 0;
1871+
*is_64bit = false;
18611872

1862-
err:
1863-
if (fd >= 0)
1864-
close(fd);
1865-
free(buf);
1866-
return NULL;
1873+
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) {
1874+
/*
1875+
* Note, there is fallback BPF image disassembly in the objdump
1876+
* version but it currently does nothing.
1877+
*/
1878+
return NULL;
1879+
}
1880+
if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {
1881+
#ifdef HAVE_LIBBPF_SUPPORT
1882+
struct bpf_prog_info_node *info_node;
1883+
struct perf_bpil *info_linear;
1884+
1885+
*is_64bit = sizeof(void *) == sizeof(u64);
1886+
info_node = perf_env__find_bpf_prog_info(dso__bpf_prog(dso)->env,
1887+
dso__bpf_prog(dso)->id);
1888+
if (!info_node) {
1889+
errno = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
1890+
return NULL;
1891+
}
1892+
info_linear = info_node->info_linear;
1893+
assert(len <= info_linear->info.jited_prog_len);
1894+
*out_buf_len = len;
1895+
return (const u8 *)(uintptr_t)(info_linear->info.jited_prog_insns);
1896+
#else
1897+
pr_debug("No BPF program disassembly support\n");
1898+
return NULL;
1899+
#endif
1900+
}
1901+
return __dso__read_symbol(dso, symfs_filename, start, len,
1902+
out_buf, out_buf_len, is_64bit);
18671903
}

tools/perf/util/libbfd.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,8 @@ int libbfd_filename__read_debuglink(const char *filename, char *debuglink,
448448
return err;
449449
}
450450

451-
int symbol__disassemble_bpf(struct symbol *sym __maybe_unused,
452-
struct annotate_args *args __maybe_unused)
451+
int symbol__disassemble_bpf_libbfd(struct symbol *sym __maybe_unused,
452+
struct annotate_args *args __maybe_unused)
453453
{
454454
#ifdef HAVE_LIBBPF_SUPPORT
455455
struct annotation *notes = symbol__annotation(sym);

tools/perf/util/libbfd.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ int libbfd__read_build_id(const char *filename, struct build_id *bid, bool block
2929

3030
int libbfd_filename__read_debuglink(const char *filename, char *debuglink, size_t size);
3131

32-
int symbol__disassemble_bpf(struct symbol *sym, struct annotate_args *args);
32+
int symbol__disassemble_bpf_libbfd(struct symbol *sym, struct annotate_args *args);
3333

3434
#else // !defined(HAVE_LIBBFD_SUPPORT)
3535
#include "annotate.h"
@@ -72,8 +72,8 @@ static inline int libbfd_filename__read_debuglink(const char *filename __always_
7272
return -1;
7373
}
7474

75-
static inline int symbol__disassemble_bpf(struct symbol *sym __always_unused,
76-
struct annotate_args *args __always_unused)
75+
static inline int symbol__disassemble_bpf_libbfd(struct symbol *sym __always_unused,
76+
struct annotate_args *args __always_unused)
7777
{
7878
return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF;
7979
}

0 commit comments

Comments
 (0)