mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 14:14:24 +08:00
perf bpf: Move BPF disassembly routines to separate file to avoid clash with capstone bpf headers
There is a clash of the libbpf and capstone libraries, that ends up
with:
In file included from /usr/include/capstone/capstone.h:325,
from util/disasm.c:1513:
/usr/include/capstone/bpf.h:94:14: error: ‘bpf_insn’ defined as wrong kind of tag
94 | typedef enum bpf_insn {
So far we're just trying to avoid this by not having both headers
included in the same .c or .h file, do it one more time by moving the
BPF diassembly routines from util/disasm.c to util/disasm_bpf.c.
This is only being hit when building with BUILD_NONDISTRO=1, i.e.
building with binutils-devel, that isn't the in the default build due to
a licencing clash. We need to reimplement what is now isolated in
util/disasm_bpf.c using some other library to have BPF annotation
feature that now only is available with BUILD_NONDISTRO=1.
Fixes: 6d17edc113
("perf annotate: Use libcapstone to disassemble")
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/lkml/ZqpUSKPxMwaQKORr@x1
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
9cb3549b73
commit
ea59b70a84
@ -13,6 +13,7 @@ perf-util-y += copyfile.o
|
||||
perf-util-y += ctype.o
|
||||
perf-util-y += db-export.o
|
||||
perf-util-y += disasm.o
|
||||
perf-util-y += disasm_bpf.o
|
||||
perf-util-y += env.o
|
||||
perf-util-y += event.o
|
||||
perf-util-y += evlist.o
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "build-id.h"
|
||||
#include "debug.h"
|
||||
#include "disasm.h"
|
||||
#include "disasm_bpf.h"
|
||||
#include "dso.h"
|
||||
#include "env.h"
|
||||
#include "evsel.h"
|
||||
@ -1323,192 +1324,6 @@ fallback:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
|
||||
#define PACKAGE "perf"
|
||||
#include <bfd.h>
|
||||
#include <dis-asm.h>
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/btf.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <linux/btf.h>
|
||||
#include <tools/dis-asm-compat.h>
|
||||
|
||||
#include "bpf-event.h"
|
||||
#include "bpf-utils.h"
|
||||
|
||||
static int symbol__disassemble_bpf(struct symbol *sym,
|
||||
struct annotate_args *args)
|
||||
{
|
||||
struct annotation *notes = symbol__annotation(sym);
|
||||
struct bpf_prog_linfo *prog_linfo = NULL;
|
||||
struct bpf_prog_info_node *info_node;
|
||||
int len = sym->end - sym->start;
|
||||
disassembler_ftype disassemble;
|
||||
struct map *map = args->ms.map;
|
||||
struct perf_bpil *info_linear;
|
||||
struct disassemble_info info;
|
||||
struct dso *dso = map__dso(map);
|
||||
int pc = 0, count, sub_id;
|
||||
struct btf *btf = NULL;
|
||||
char tpath[PATH_MAX];
|
||||
size_t buf_size;
|
||||
int nr_skip = 0;
|
||||
char *buf;
|
||||
bfd *bfdf;
|
||||
int ret;
|
||||
FILE *s;
|
||||
|
||||
if (dso__binary_type(dso) != DSO_BINARY_TYPE__BPF_PROG_INFO)
|
||||
return SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE;
|
||||
|
||||
pr_debug("%s: handling sym %s addr %" PRIx64 " len %" PRIx64 "\n", __func__,
|
||||
sym->name, sym->start, sym->end - sym->start);
|
||||
|
||||
memset(tpath, 0, sizeof(tpath));
|
||||
perf_exe(tpath, sizeof(tpath));
|
||||
|
||||
bfdf = bfd_openr(tpath, NULL);
|
||||
if (bfdf == NULL)
|
||||
abort();
|
||||
|
||||
if (!bfd_check_format(bfdf, bfd_object))
|
||||
abort();
|
||||
|
||||
s = open_memstream(&buf, &buf_size);
|
||||
if (!s) {
|
||||
ret = errno;
|
||||
goto out;
|
||||
}
|
||||
init_disassemble_info_compat(&info, s,
|
||||
(fprintf_ftype) fprintf,
|
||||
fprintf_styled);
|
||||
info.arch = bfd_get_arch(bfdf);
|
||||
info.mach = bfd_get_mach(bfdf);
|
||||
|
||||
info_node = perf_env__find_bpf_prog_info(dso__bpf_prog(dso)->env,
|
||||
dso__bpf_prog(dso)->id);
|
||||
if (!info_node) {
|
||||
ret = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
|
||||
goto out;
|
||||
}
|
||||
info_linear = info_node->info_linear;
|
||||
sub_id = dso__bpf_prog(dso)->sub_id;
|
||||
|
||||
info.buffer = (void *)(uintptr_t)(info_linear->info.jited_prog_insns);
|
||||
info.buffer_length = info_linear->info.jited_prog_len;
|
||||
|
||||
if (info_linear->info.nr_line_info)
|
||||
prog_linfo = bpf_prog_linfo__new(&info_linear->info);
|
||||
|
||||
if (info_linear->info.btf_id) {
|
||||
struct btf_node *node;
|
||||
|
||||
node = perf_env__find_btf(dso__bpf_prog(dso)->env,
|
||||
info_linear->info.btf_id);
|
||||
if (node)
|
||||
btf = btf__new((__u8 *)(node->data),
|
||||
node->data_size);
|
||||
}
|
||||
|
||||
disassemble_init_for_target(&info);
|
||||
|
||||
#ifdef DISASM_FOUR_ARGS_SIGNATURE
|
||||
disassemble = disassembler(info.arch,
|
||||
bfd_big_endian(bfdf),
|
||||
info.mach,
|
||||
bfdf);
|
||||
#else
|
||||
disassemble = disassembler(bfdf);
|
||||
#endif
|
||||
if (disassemble == NULL)
|
||||
abort();
|
||||
|
||||
fflush(s);
|
||||
do {
|
||||
const struct bpf_line_info *linfo = NULL;
|
||||
struct disasm_line *dl;
|
||||
size_t prev_buf_size;
|
||||
const char *srcline;
|
||||
u64 addr;
|
||||
|
||||
addr = pc + ((u64 *)(uintptr_t)(info_linear->info.jited_ksyms))[sub_id];
|
||||
count = disassemble(pc, &info);
|
||||
|
||||
if (prog_linfo)
|
||||
linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
|
||||
addr, sub_id,
|
||||
nr_skip);
|
||||
|
||||
if (linfo && btf) {
|
||||
srcline = btf__name_by_offset(btf, linfo->line_off);
|
||||
nr_skip++;
|
||||
} else
|
||||
srcline = NULL;
|
||||
|
||||
fprintf(s, "\n");
|
||||
prev_buf_size = buf_size;
|
||||
fflush(s);
|
||||
|
||||
if (!annotate_opts.hide_src_code && srcline) {
|
||||
args->offset = -1;
|
||||
args->line = strdup(srcline);
|
||||
args->line_nr = 0;
|
||||
args->fileloc = NULL;
|
||||
args->ms.sym = sym;
|
||||
dl = disasm_line__new(args);
|
||||
if (dl) {
|
||||
annotation_line__add(&dl->al,
|
||||
¬es->src->source);
|
||||
}
|
||||
}
|
||||
|
||||
args->offset = pc;
|
||||
args->line = buf + prev_buf_size;
|
||||
args->line_nr = 0;
|
||||
args->fileloc = NULL;
|
||||
args->ms.sym = sym;
|
||||
dl = disasm_line__new(args);
|
||||
if (dl)
|
||||
annotation_line__add(&dl->al, ¬es->src->source);
|
||||
|
||||
pc += count;
|
||||
} while (count > 0 && pc < len);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
free(prog_linfo);
|
||||
btf__free(btf);
|
||||
fclose(s);
|
||||
bfd_close(bfdf);
|
||||
return ret;
|
||||
}
|
||||
#else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
|
||||
static int symbol__disassemble_bpf(struct symbol *sym __maybe_unused,
|
||||
struct annotate_args *args __maybe_unused)
|
||||
{
|
||||
return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF;
|
||||
}
|
||||
#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
|
||||
|
||||
static int
|
||||
symbol__disassemble_bpf_image(struct symbol *sym,
|
||||
struct annotate_args *args)
|
||||
{
|
||||
struct annotation *notes = symbol__annotation(sym);
|
||||
struct disasm_line *dl;
|
||||
|
||||
args->offset = -1;
|
||||
args->line = strdup("to be implemented");
|
||||
args->line_nr = 0;
|
||||
args->fileloc = NULL;
|
||||
dl = disasm_line__new(args);
|
||||
if (dl)
|
||||
annotation_line__add(&dl->al, ¬es->src->source);
|
||||
|
||||
zfree(&args->line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBCAPSTONE_SUPPORT
|
||||
#include <capstone/capstone.h>
|
||||
|
||||
|
195
tools/perf/util/disasm_bpf.c
Normal file
195
tools/perf/util/disasm_bpf.c
Normal file
@ -0,0 +1,195 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include "util/annotate.h"
|
||||
#include "util/disasm_bpf.h"
|
||||
#include "util/symbol.h"
|
||||
#include <linux/zalloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
|
||||
#define PACKAGE "perf"
|
||||
#include <bfd.h>
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/btf.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <dis-asm.h>
|
||||
#include <errno.h>
|
||||
#include <linux/btf.h>
|
||||
#include <tools/dis-asm-compat.h>
|
||||
|
||||
#include "util/bpf-event.h"
|
||||
#include "util/bpf-utils.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/map.h"
|
||||
#include "util/env.h"
|
||||
#include "util/util.h"
|
||||
|
||||
int symbol__disassemble_bpf(struct symbol *sym, struct annotate_args *args)
|
||||
{
|
||||
struct annotation *notes = symbol__annotation(sym);
|
||||
struct bpf_prog_linfo *prog_linfo = NULL;
|
||||
struct bpf_prog_info_node *info_node;
|
||||
int len = sym->end - sym->start;
|
||||
disassembler_ftype disassemble;
|
||||
struct map *map = args->ms.map;
|
||||
struct perf_bpil *info_linear;
|
||||
struct disassemble_info info;
|
||||
struct dso *dso = map__dso(map);
|
||||
int pc = 0, count, sub_id;
|
||||
struct btf *btf = NULL;
|
||||
char tpath[PATH_MAX];
|
||||
size_t buf_size;
|
||||
int nr_skip = 0;
|
||||
char *buf;
|
||||
bfd *bfdf;
|
||||
int ret;
|
||||
FILE *s;
|
||||
|
||||
if (dso__binary_type(dso) != DSO_BINARY_TYPE__BPF_PROG_INFO)
|
||||
return SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE;
|
||||
|
||||
pr_debug("%s: handling sym %s addr %" PRIx64 " len %" PRIx64 "\n", __func__,
|
||||
sym->name, sym->start, sym->end - sym->start);
|
||||
|
||||
memset(tpath, 0, sizeof(tpath));
|
||||
perf_exe(tpath, sizeof(tpath));
|
||||
|
||||
bfdf = bfd_openr(tpath, NULL);
|
||||
if (bfdf == NULL)
|
||||
abort();
|
||||
|
||||
if (!bfd_check_format(bfdf, bfd_object))
|
||||
abort();
|
||||
|
||||
s = open_memstream(&buf, &buf_size);
|
||||
if (!s) {
|
||||
ret = errno;
|
||||
goto out;
|
||||
}
|
||||
init_disassemble_info_compat(&info, s,
|
||||
(fprintf_ftype) fprintf,
|
||||
fprintf_styled);
|
||||
info.arch = bfd_get_arch(bfdf);
|
||||
info.mach = bfd_get_mach(bfdf);
|
||||
|
||||
info_node = perf_env__find_bpf_prog_info(dso__bpf_prog(dso)->env,
|
||||
dso__bpf_prog(dso)->id);
|
||||
if (!info_node) {
|
||||
ret = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
|
||||
goto out;
|
||||
}
|
||||
info_linear = info_node->info_linear;
|
||||
sub_id = dso__bpf_prog(dso)->sub_id;
|
||||
|
||||
info.buffer = (void *)(uintptr_t)(info_linear->info.jited_prog_insns);
|
||||
info.buffer_length = info_linear->info.jited_prog_len;
|
||||
|
||||
if (info_linear->info.nr_line_info)
|
||||
prog_linfo = bpf_prog_linfo__new(&info_linear->info);
|
||||
|
||||
if (info_linear->info.btf_id) {
|
||||
struct btf_node *node;
|
||||
|
||||
node = perf_env__find_btf(dso__bpf_prog(dso)->env,
|
||||
info_linear->info.btf_id);
|
||||
if (node)
|
||||
btf = btf__new((__u8 *)(node->data),
|
||||
node->data_size);
|
||||
}
|
||||
|
||||
disassemble_init_for_target(&info);
|
||||
|
||||
#ifdef DISASM_FOUR_ARGS_SIGNATURE
|
||||
disassemble = disassembler(info.arch,
|
||||
bfd_big_endian(bfdf),
|
||||
info.mach,
|
||||
bfdf);
|
||||
#else
|
||||
disassemble = disassembler(bfdf);
|
||||
#endif
|
||||
if (disassemble == NULL)
|
||||
abort();
|
||||
|
||||
fflush(s);
|
||||
do {
|
||||
const struct bpf_line_info *linfo = NULL;
|
||||
struct disasm_line *dl;
|
||||
size_t prev_buf_size;
|
||||
const char *srcline;
|
||||
u64 addr;
|
||||
|
||||
addr = pc + ((u64 *)(uintptr_t)(info_linear->info.jited_ksyms))[sub_id];
|
||||
count = disassemble(pc, &info);
|
||||
|
||||
if (prog_linfo)
|
||||
linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
|
||||
addr, sub_id,
|
||||
nr_skip);
|
||||
|
||||
if (linfo && btf) {
|
||||
srcline = btf__name_by_offset(btf, linfo->line_off);
|
||||
nr_skip++;
|
||||
} else
|
||||
srcline = NULL;
|
||||
|
||||
fprintf(s, "\n");
|
||||
prev_buf_size = buf_size;
|
||||
fflush(s);
|
||||
|
||||
if (!annotate_opts.hide_src_code && srcline) {
|
||||
args->offset = -1;
|
||||
args->line = strdup(srcline);
|
||||
args->line_nr = 0;
|
||||
args->fileloc = NULL;
|
||||
args->ms.sym = sym;
|
||||
dl = disasm_line__new(args);
|
||||
if (dl) {
|
||||
annotation_line__add(&dl->al,
|
||||
¬es->src->source);
|
||||
}
|
||||
}
|
||||
|
||||
args->offset = pc;
|
||||
args->line = buf + prev_buf_size;
|
||||
args->line_nr = 0;
|
||||
args->fileloc = NULL;
|
||||
args->ms.sym = sym;
|
||||
dl = disasm_line__new(args);
|
||||
if (dl)
|
||||
annotation_line__add(&dl->al, ¬es->src->source);
|
||||
|
||||
pc += count;
|
||||
} while (count > 0 && pc < len);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
free(prog_linfo);
|
||||
btf__free(btf);
|
||||
fclose(s);
|
||||
bfd_close(bfdf);
|
||||
return ret;
|
||||
}
|
||||
#else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
|
||||
int symbol__disassemble_bpf(struct symbol *sym __maybe_unused, struct annotate_args *args __maybe_unused)
|
||||
{
|
||||
return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF;
|
||||
}
|
||||
#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
|
||||
|
||||
int symbol__disassemble_bpf_image(struct symbol *sym, struct annotate_args *args)
|
||||
{
|
||||
struct annotation *notes = symbol__annotation(sym);
|
||||
struct disasm_line *dl;
|
||||
|
||||
args->offset = -1;
|
||||
args->line = strdup("to be implemented");
|
||||
args->line_nr = 0;
|
||||
args->fileloc = NULL;
|
||||
dl = disasm_line__new(args);
|
||||
if (dl)
|
||||
annotation_line__add(&dl->al, ¬es->src->source);
|
||||
|
||||
zfree(&args->line);
|
||||
return 0;
|
||||
}
|
12
tools/perf/util/disasm_bpf.h
Normal file
12
tools/perf/util/disasm_bpf.h
Normal file
@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#ifndef __PERF_DISASM_BPF_H
|
||||
#define __PERF_DISASM_BPF_H
|
||||
|
||||
struct symbol;
|
||||
struct annotate_args;
|
||||
|
||||
int symbol__disassemble_bpf(struct symbol *sym, struct annotate_args *args);
|
||||
int symbol__disassemble_bpf_image(struct symbol *sym, struct annotate_args *args);
|
||||
|
||||
#endif /* __PERF_DISASM_BPF_H */
|
Loading…
Reference in New Issue
Block a user