Merge branch 'bpftool: Add LLVM as default library for disassembling JIT-ed programs'

Quentin Monnet says:

====================

To disassemble instructions for JIT-ed programs, bpftool has relied on the
libbfd library. This has been problematic in the past: libbfd's interface
is not meant to be stable and has changed several times, hence the
detection of the two related features from the Makefile
(disassembler-four-args and disassembler-init-styled). When it comes to
shipping bpftool, this has also caused issues with several distribution
maintainers unwilling to support the feature (for example, Debian's page
for binutils-dev, libbfd's package, says: "Note that building Debian
packages which depend on the shared libbfd is Not Allowed.").

This patchset adds support for LLVM as the primary library for
disassembling instructions for JIT-ed programs.

We keep libbfd as a fallback. One reason for this is that currently it
works well, we have all we need in terms of features detection in the
Makefile, so it provides a fallback for disassembling JIT-ed programs if
libbfd is installed but LLVM is not. The other reason is that libbfd
supports nfp instruction for Netronome's SmartNICs and can be used to
disassemble offloaded programs, something that LLVM cannot do (Niklas
confirmed that the feature is still in use). However, if libbfd's interface
breaks again in the future, we might reconsider keeping support for it.

v4:
  - Rebase to address a conflict with commit 2c76238ead ("bpftool: Add
    "bootstrap" feature to version output").

v3:
  - Extend commit description (patch 6) with notes on llvm-dev and LLVM's
    disassembler stability.

v2:
  - Pass callback when creating the LLVM disassembler, so that the
    branch targets are printed as addresses (instead of byte offsets).
  - Add last commit to "support" other arch with LLVM, although we don't
    know any supported triple yet.
  - Use $(LLVM_CONFIG) instead of llvm-config in Makefile.
  - Pass components to llvm-config --libs to limit the number of
    libraries to pass on the command line, in Makefile.
  - Rebase split of FEATURE_TESTS and FEATURE_DISPLAY in Makefile.
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Alexei Starovoitov 2022-10-25 10:11:57 -07:00
commit 152e60e3fa
12 changed files with 319 additions and 105 deletions

View file

@ -7,10 +7,10 @@
Print bpftool's version number (similar to **bpftool version**), the Print bpftool's version number (similar to **bpftool version**), the
number of the libbpf version in use, and optional features that were number of the libbpf version in use, and optional features that were
included when bpftool was compiled. Optional features include linking included when bpftool was compiled. Optional features include linking
against libbfd to provide the disassembler for JIT-ted programs against LLVM or libbfd to provide the disassembler for JIT-ted
(**bpftool prog dump jited**) and usage of BPF skeletons (some programs (**bpftool prog dump jited**) and usage of BPF skeletons
features like **bpftool prog profile** or showing pids associated to (some features like **bpftool prog profile** or showing pids
BPF objects may rely on it). associated to BPF objects may rely on it).
-j, --json -j, --json
Generate JSON output. For commands that cannot produce JSON, this Generate JSON output. For commands that cannot produce JSON, this

View file

@ -93,11 +93,22 @@ INSTALL ?= install
RM ?= rm -f RM ?= rm -f
FEATURE_USER = .bpftool FEATURE_USER = .bpftool
FEATURE_TESTS = libbfd libbfd-liberty libbfd-liberty-z \
disassembler-four-args disassembler-init-styled libcap \ FEATURE_TESTS := clang-bpf-co-re
clang-bpf-co-re FEATURE_TESTS += llvm
FEATURE_DISPLAY = libbfd libbfd-liberty libbfd-liberty-z \ FEATURE_TESTS += libcap
libcap clang-bpf-co-re FEATURE_TESTS += libbfd
FEATURE_TESTS += libbfd-liberty
FEATURE_TESTS += libbfd-liberty-z
FEATURE_TESTS += disassembler-four-args
FEATURE_TESTS += disassembler-init-styled
FEATURE_DISPLAY := clang-bpf-co-re
FEATURE_DISPLAY += llvm
FEATURE_DISPLAY += libcap
FEATURE_DISPLAY += libbfd
FEATURE_DISPLAY += libbfd-liberty
FEATURE_DISPLAY += libbfd-liberty-z
check_feat := 1 check_feat := 1
NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall
@ -115,13 +126,6 @@ include $(FEATURES_DUMP)
endif endif
endif endif
ifeq ($(feature-disassembler-four-args), 1)
CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
endif
ifeq ($(feature-disassembler-init-styled), 1)
CFLAGS += -DDISASM_INIT_STYLED
endif
LIBS = $(LIBBPF) -lelf -lz LIBS = $(LIBBPF) -lelf -lz
LIBS_BOOTSTRAP = $(LIBBPF_BOOTSTRAP) -lelf -lz LIBS_BOOTSTRAP = $(LIBBPF_BOOTSTRAP) -lelf -lz
ifeq ($(feature-libcap), 1) ifeq ($(feature-libcap), 1)
@ -133,21 +137,41 @@ include $(wildcard $(OUTPUT)*.d)
all: $(OUTPUT)bpftool all: $(OUTPUT)bpftool
BFD_SRCS = jit_disasm.c SRCS := $(wildcard *.c)
SRCS = $(filter-out $(BFD_SRCS),$(wildcard *.c)) ifeq ($(feature-llvm),1)
# If LLVM is available, use it for JIT disassembly
CFLAGS += -DHAVE_LLVM_SUPPORT
LLVM_CONFIG_LIB_COMPONENTS := mcdisassembler all-targets
CFLAGS += $(shell $(LLVM_CONFIG) --cflags --libs $(LLVM_CONFIG_LIB_COMPONENTS))
LIBS += $(shell $(LLVM_CONFIG) --libs $(LLVM_CONFIG_LIB_COMPONENTS))
LDFLAGS += $(shell $(LLVM_CONFIG) --ldflags)
else
# Fall back on libbfd
ifeq ($(feature-libbfd),1)
LIBS += -lbfd -ldl -lopcodes
else ifeq ($(feature-libbfd-liberty),1)
LIBS += -lbfd -ldl -lopcodes -liberty
else ifeq ($(feature-libbfd-liberty-z),1)
LIBS += -lbfd -ldl -lopcodes -liberty -lz
endif
ifeq ($(feature-libbfd),1) # If one of the above feature combinations is set, we support libbfd
LIBS += -lbfd -ldl -lopcodes ifneq ($(filter -lbfd,$(LIBS)),)
else ifeq ($(feature-libbfd-liberty),1) CFLAGS += -DHAVE_LIBBFD_SUPPORT
LIBS += -lbfd -ldl -lopcodes -liberty
else ifeq ($(feature-libbfd-liberty-z),1) # Libbfd interface changed over time, figure out what we need
LIBS += -lbfd -ldl -lopcodes -liberty -lz ifeq ($(feature-disassembler-four-args), 1)
CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
endif
ifeq ($(feature-disassembler-init-styled), 1)
CFLAGS += -DDISASM_INIT_STYLED
endif
endif
endif endif
ifeq ($(filter -DHAVE_LLVM_SUPPORT -DHAVE_LIBBFD_SUPPORT,$(CFLAGS)),)
ifneq ($(filter -lbfd,$(LIBS)),) # No support for JIT disassembly
CFLAGS += -DHAVE_LIBBFD_SUPPORT SRCS := $(filter-out jit_disasm.c,$(SRCS))
SRCS += $(BFD_SRCS)
endif endif
HOST_CFLAGS = $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),\ HOST_CFLAGS = $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),\

View file

@ -1,7 +1,9 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2017-2018 Netronome Systems, Inc. */ /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@ -625,12 +627,11 @@ static int read_sysfs_netdev_hex_int(char *devname, const char *entry_name)
} }
const char * const char *
ifindex_to_bfd_params(__u32 ifindex, __u64 ns_dev, __u64 ns_ino, ifindex_to_arch(__u32 ifindex, __u64 ns_dev, __u64 ns_ino, const char **opt)
const char **opt)
{ {
__maybe_unused int device_id;
char devname[IF_NAMESIZE]; char devname[IF_NAMESIZE];
int vendor_id; int vendor_id;
int device_id;
if (!ifindex_to_name_ns(ifindex, ns_dev, ns_ino, devname)) { if (!ifindex_to_name_ns(ifindex, ns_dev, ns_ino, devname)) {
p_err("Can't get net device name for ifindex %d: %s", ifindex, p_err("Can't get net device name for ifindex %d: %s", ifindex,
@ -645,6 +646,7 @@ ifindex_to_bfd_params(__u32 ifindex, __u64 ns_dev, __u64 ns_ino,
} }
switch (vendor_id) { switch (vendor_id) {
#ifdef HAVE_LIBBFD_SUPPORT
case 0x19ee: case 0x19ee:
device_id = read_sysfs_netdev_hex_int(devname, "device"); device_id = read_sysfs_netdev_hex_int(devname, "device");
if (device_id != 0x4000 && if (device_id != 0x4000 &&
@ -653,8 +655,10 @@ ifindex_to_bfd_params(__u32 ifindex, __u64 ns_dev, __u64 ns_ino,
p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch"); p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch");
*opt = "ctx4"; *opt = "ctx4";
return "NFP-6xxx"; return "NFP-6xxx";
#endif /* HAVE_LIBBFD_SUPPORT */
/* No NFP support in LLVM, we have no valid triple to return. */
default: default:
p_err("Can't get bfd arch name for device vendor id 0x%04x", p_err("Can't get arch name for device vendor id 0x%04x",
vendor_id); vendor_id);
return NULL; return NULL;
} }

View file

@ -1,7 +1,9 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
// Copyright (C) 2020 Facebook // Copyright (C) 2020 Facebook
#ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif
#include <unistd.h> #include <unistd.h>
#include <linux/err.h> #include <linux/err.h>
#include <bpf/libbpf.h> #include <bpf/libbpf.h>

View file

@ -11,35 +11,151 @@
* Licensed under the GNU General Public License, version 2.0 (GPLv2) * Licensed under the GNU General Public License, version 2.0 (GPLv2)
*/ */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <bfd.h>
#include <dis-asm.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <limits.h> #include <limits.h>
#include <bpf/libbpf.h> #include <bpf/libbpf.h>
#ifdef HAVE_LLVM_SUPPORT
#include <llvm-c/Core.h>
#include <llvm-c/Disassembler.h>
#include <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>
#endif
#ifdef HAVE_LIBBFD_SUPPORT
#include <bfd.h>
#include <dis-asm.h>
#include <tools/dis-asm-compat.h> #include <tools/dis-asm-compat.h>
#endif
#include "json_writer.h" #include "json_writer.h"
#include "main.h" #include "main.h"
static void get_exec_path(char *tpath, size_t size) static int oper_count;
#ifdef HAVE_LLVM_SUPPORT
#define DISASM_SPACER
typedef LLVMDisasmContextRef disasm_ctx_t;
static int printf_json(char *s)
{
s = strtok(s, " \t");
jsonw_string_field(json_wtr, "operation", s);
jsonw_name(json_wtr, "operands");
jsonw_start_array(json_wtr);
oper_count = 1;
while ((s = strtok(NULL, " \t,()")) != 0) {
jsonw_string(json_wtr, s);
oper_count++;
}
return 0;
}
/* This callback to set the ref_type is necessary to have the LLVM disassembler
* print PC-relative addresses instead of byte offsets for branch instruction
* targets.
*/
static const char *
symbol_lookup_callback(__maybe_unused void *disasm_info,
__maybe_unused uint64_t ref_value,
uint64_t *ref_type, __maybe_unused uint64_t ref_PC,
__maybe_unused const char **ref_name)
{
*ref_type = LLVMDisassembler_ReferenceType_InOut_None;
return NULL;
}
static int
init_context(disasm_ctx_t *ctx, const char *arch,
__maybe_unused const char *disassembler_options,
__maybe_unused unsigned char *image, __maybe_unused ssize_t len)
{
char *triple;
if (arch)
triple = LLVMNormalizeTargetTriple(arch);
else
triple = LLVMGetDefaultTargetTriple();
if (!triple) {
p_err("Failed to retrieve triple");
return -1;
}
*ctx = LLVMCreateDisasm(triple, NULL, 0, NULL, symbol_lookup_callback);
LLVMDisposeMessage(triple);
if (!*ctx) {
p_err("Failed to create disassembler");
return -1;
}
return 0;
}
static void destroy_context(disasm_ctx_t *ctx)
{
LLVMDisposeMessage(*ctx);
}
static int
disassemble_insn(disasm_ctx_t *ctx, unsigned char *image, ssize_t len, int pc)
{
char buf[256];
int count;
count = LLVMDisasmInstruction(*ctx, image + pc, len - pc, pc,
buf, sizeof(buf));
if (json_output)
printf_json(buf);
else
printf("%s", buf);
return count;
}
int disasm_init(void)
{
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();
return 0;
}
#endif /* HAVE_LLVM_SUPPORT */
#ifdef HAVE_LIBBFD_SUPPORT
#define DISASM_SPACER "\t"
typedef struct {
struct disassemble_info *info;
disassembler_ftype disassemble;
bfd *bfdf;
} disasm_ctx_t;
static int get_exec_path(char *tpath, size_t size)
{ {
const char *path = "/proc/self/exe"; const char *path = "/proc/self/exe";
ssize_t len; ssize_t len;
len = readlink(path, tpath, size - 1); len = readlink(path, tpath, size - 1);
assert(len > 0); if (len <= 0)
return -1;
tpath[len] = 0; tpath[len] = 0;
return 0;
} }
static int oper_count;
static int printf_json(void *out, const char *fmt, va_list ap) static int printf_json(void *out, const char *fmt, va_list ap)
{ {
char *s; char *s;
@ -97,37 +213,44 @@ static int fprintf_json_styled(void *out,
return r; return r;
} }
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, static int init_context(disasm_ctx_t *ctx, const char *arch,
const char *arch, const char *disassembler_options, const char *disassembler_options,
const struct btf *btf, unsigned char *image, ssize_t len)
const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx,
bool linum)
{ {
const struct bpf_line_info *linfo = NULL; struct disassemble_info *info;
disassembler_ftype disassemble;
struct disassemble_info info;
unsigned int nr_skip = 0;
int count, i, pc = 0;
char tpath[PATH_MAX]; char tpath[PATH_MAX];
bfd *bfdf; bfd *bfdf;
if (!len)
return;
memset(tpath, 0, sizeof(tpath)); memset(tpath, 0, sizeof(tpath));
get_exec_path(tpath, sizeof(tpath)); if (get_exec_path(tpath, sizeof(tpath))) {
p_err("failed to create disasembler (get_exec_path)");
return -1;
}
bfdf = bfd_openr(tpath, NULL); ctx->bfdf = bfd_openr(tpath, NULL);
assert(bfdf); if (!ctx->bfdf) {
assert(bfd_check_format(bfdf, bfd_object)); p_err("failed to create disassembler (bfd_openr)");
return -1;
}
if (!bfd_check_format(ctx->bfdf, bfd_object)) {
p_err("failed to create disassembler (bfd_check_format)");
goto err_close;
}
bfdf = ctx->bfdf;
ctx->info = malloc(sizeof(struct disassemble_info));
if (!ctx->info) {
p_err("mem alloc failed");
goto err_close;
}
info = ctx->info;
if (json_output) if (json_output)
init_disassemble_info_compat(&info, stdout, init_disassemble_info_compat(info, stdout,
(fprintf_ftype) fprintf_json, (fprintf_ftype) fprintf_json,
fprintf_json_styled); fprintf_json_styled);
else else
init_disassemble_info_compat(&info, stdout, init_disassemble_info_compat(info, stdout,
(fprintf_ftype) fprintf, (fprintf_ftype) fprintf,
fprintf_styled); fprintf_styled);
@ -139,28 +262,77 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
bfdf->arch_info = inf; bfdf->arch_info = inf;
} else { } else {
p_err("No libbfd support for %s", arch); p_err("No libbfd support for %s", arch);
return; goto err_free;
} }
} }
info.arch = bfd_get_arch(bfdf); info->arch = bfd_get_arch(bfdf);
info.mach = bfd_get_mach(bfdf); info->mach = bfd_get_mach(bfdf);
if (disassembler_options) if (disassembler_options)
info.disassembler_options = disassembler_options; info->disassembler_options = disassembler_options;
info.buffer = image; info->buffer = image;
info.buffer_length = len; info->buffer_length = len;
disassemble_init_for_target(&info); disassemble_init_for_target(info);
#ifdef DISASM_FOUR_ARGS_SIGNATURE #ifdef DISASM_FOUR_ARGS_SIGNATURE
disassemble = disassembler(info.arch, ctx->disassemble = disassembler(info->arch,
bfd_big_endian(bfdf), bfd_big_endian(bfdf),
info.mach, info->mach,
bfdf); bfdf);
#else #else
disassemble = disassembler(bfdf); ctx->disassemble = disassembler(bfdf);
#endif #endif
assert(disassemble); if (!ctx->disassemble) {
p_err("failed to create disassembler");
goto err_free;
}
return 0;
err_free:
free(info);
err_close:
bfd_close(ctx->bfdf);
return -1;
}
static void destroy_context(disasm_ctx_t *ctx)
{
free(ctx->info);
bfd_close(ctx->bfdf);
}
static int
disassemble_insn(disasm_ctx_t *ctx, __maybe_unused unsigned char *image,
__maybe_unused ssize_t len, int pc)
{
return ctx->disassemble(pc, ctx->info);
}
int disasm_init(void)
{
bfd_init();
return 0;
}
#endif /* HAVE_LIBBPFD_SUPPORT */
int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch, const char *disassembler_options,
const struct btf *btf,
const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx,
bool linum)
{
const struct bpf_line_info *linfo = NULL;
unsigned int nr_skip = 0;
int count, i, pc = 0;
disasm_ctx_t ctx;
if (!len)
return -1;
if (init_context(&ctx, arch, disassembler_options, image, len))
return -1;
if (json_output) if (json_output)
jsonw_start_array(json_wtr); jsonw_start_array(json_wtr);
@ -185,10 +357,11 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
if (linfo) if (linfo)
btf_dump_linfo_plain(btf, linfo, "; ", btf_dump_linfo_plain(btf, linfo, "; ",
linum); linum);
printf("%4x:\t", pc); printf("%4x:" DISASM_SPACER, pc);
} }
count = disassemble(pc, &info); count = disassemble_insn(&ctx, image, len, pc);
if (json_output) { if (json_output) {
/* Operand array, was started in fprintf_json. Before /* Operand array, was started in fprintf_json. Before
* that, make sure we have a _null_ value if no operand * that, make sure we have a _null_ value if no operand
@ -224,11 +397,7 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
if (json_output) if (json_output)
jsonw_end_array(json_wtr); jsonw_end_array(json_wtr);
bfd_close(bfdf); destroy_context(&ctx);
}
int disasm_init(void)
{
bfd_init();
return 0; return 0;
} }

View file

@ -119,6 +119,11 @@ static int do_version(int argc, char **argv)
#else #else
const bool has_libbfd = false; const bool has_libbfd = false;
#endif #endif
#ifdef HAVE_LLVM_SUPPORT
const bool has_llvm = true;
#else
const bool has_llvm = false;
#endif
#ifdef BPFTOOL_WITHOUT_SKELETONS #ifdef BPFTOOL_WITHOUT_SKELETONS
const bool has_skeletons = false; const bool has_skeletons = false;
#else #else
@ -154,6 +159,7 @@ static int do_version(int argc, char **argv)
jsonw_name(json_wtr, "features"); jsonw_name(json_wtr, "features");
jsonw_start_object(json_wtr); /* features */ jsonw_start_object(json_wtr); /* features */
jsonw_bool_field(json_wtr, "libbfd", has_libbfd); jsonw_bool_field(json_wtr, "libbfd", has_libbfd);
jsonw_bool_field(json_wtr, "llvm", has_llvm);
jsonw_bool_field(json_wtr, "libbpf_strict", !legacy_libbpf); jsonw_bool_field(json_wtr, "libbpf_strict", !legacy_libbpf);
jsonw_bool_field(json_wtr, "skeletons", has_skeletons); jsonw_bool_field(json_wtr, "skeletons", has_skeletons);
jsonw_bool_field(json_wtr, "bootstrap", bootstrap); jsonw_bool_field(json_wtr, "bootstrap", bootstrap);
@ -172,6 +178,7 @@ static int do_version(int argc, char **argv)
printf("using libbpf %s\n", libbpf_version_string()); printf("using libbpf %s\n", libbpf_version_string());
printf("features:"); printf("features:");
print_feature("libbfd", has_libbfd, &nb_features); print_feature("libbfd", has_libbfd, &nb_features);
print_feature("llvm", has_llvm, &nb_features);
print_feature("libbpf_strict", !legacy_libbpf, &nb_features); print_feature("libbpf_strict", !legacy_libbpf, &nb_features);
print_feature("skeletons", has_skeletons, &nb_features); print_feature("skeletons", has_skeletons, &nb_features);
print_feature("bootstrap", bootstrap, &nb_features); print_feature("bootstrap", bootstrap, &nb_features);

View file

@ -172,27 +172,28 @@ int map_parse_fds(int *argc, char ***argv, int **fds);
int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len); int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len);
struct bpf_prog_linfo; struct bpf_prog_linfo;
#ifdef HAVE_LIBBFD_SUPPORT #if defined(HAVE_LLVM_SUPPORT) || defined(HAVE_LIBBFD_SUPPORT)
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch, const char *disassembler_options, const char *arch, const char *disassembler_options,
const struct btf *btf, const struct btf *btf,
const struct bpf_prog_linfo *prog_linfo, const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx, __u64 func_ksym, unsigned int func_idx,
bool linum); bool linum);
int disasm_init(void); int disasm_init(void);
#else #else
static inline static inline
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch, const char *disassembler_options, const char *arch, const char *disassembler_options,
const struct btf *btf, const struct btf *btf,
const struct bpf_prog_linfo *prog_linfo, const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx, __u64 func_ksym, unsigned int func_idx,
bool linum) bool linum)
{ {
return 0;
} }
static inline int disasm_init(void) static inline int disasm_init(void)
{ {
p_err("No libbfd support"); p_err("No JIT disassembly support");
return -1; return -1;
} }
#endif #endif
@ -202,8 +203,7 @@ void print_hex_data_json(uint8_t *data, size_t len);
unsigned int get_page_size(void); unsigned int get_page_size(void);
unsigned int get_possible_cpus(void); unsigned int get_possible_cpus(void);
const char * const char *
ifindex_to_bfd_params(__u32 ifindex, __u64 ns_dev, __u64 ns_ino, ifindex_to_arch(__u32 ifindex, __u64 ns_dev, __u64 ns_ino, const char **opt);
const char **opt);
struct btf_dumper { struct btf_dumper {
const struct btf *btf; const struct btf *btf;

View file

@ -1,7 +1,6 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2017-2018 Netronome Systems, Inc. */ /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/err.h> #include <linux/err.h>

View file

@ -1,7 +1,9 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
// Copyright (C) 2018 Facebook // Copyright (C) 2018 Facebook
#ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>

View file

@ -2,7 +2,9 @@
// Copyright (C) 2018 Facebook // Copyright (C) 2018 Facebook
// Author: Yonghong Song <yhs@fb.com> // Author: Yonghong Song <yhs@fb.com>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>

View file

@ -1,7 +1,9 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2017-2018 Netronome Systems, Inc. */ /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <signal.h> #include <signal.h>
@ -762,10 +764,8 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
const char *name = NULL; const char *name = NULL;
if (info->ifindex) { if (info->ifindex) {
name = ifindex_to_bfd_params(info->ifindex, name = ifindex_to_arch(info->ifindex, info->netns_dev,
info->netns_dev, info->netns_ino, &disasm_opt);
info->netns_ino,
&disasm_opt);
if (!name) if (!name)
goto exit_free; goto exit_free;
} }
@ -820,10 +820,11 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
printf("%s:\n", sym_name); printf("%s:\n", sym_name);
} }
disasm_print_insn(img, lens[i], opcodes, if (disasm_print_insn(img, lens[i], opcodes,
name, disasm_opt, btf, name, disasm_opt, btf,
prog_linfo, ksyms[i], i, prog_linfo, ksyms[i], i,
linum); linum))
goto exit_free;
img += lens[i]; img += lens[i];
@ -836,8 +837,10 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
if (json_output) if (json_output)
jsonw_end_array(json_wtr); jsonw_end_array(json_wtr);
} else { } else {
disasm_print_insn(buf, member_len, opcodes, name, if (disasm_print_insn(buf, member_len, opcodes, name,
disasm_opt, btf, NULL, 0, 0, false); disasm_opt, btf, NULL, 0, 0,
false))
goto exit_free;
} }
} else if (visual) { } else if (visual) {
if (json_output) if (json_output)

View file

@ -1,7 +1,9 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2018 Netronome Systems, Inc. */ /* Copyright (C) 2018 Netronome Systems, Inc. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>