mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-09 23:34:42 +08:00
selftests/bpf: Add test for resolve_btfids
Adding resolve_btfids test under test_progs suite. It's possible to use btf_ids.h header and its logic in user space application, so we can add easy test for it. The test defines BTF_ID_LIST and checks it gets properly resolved. For this reason the test_progs binary (and other binaries that use TRUNNER* macros) is processed with resolve_btfids tool, which resolves BTF IDs in .BTF_ids section. The BTF data are taken from btf_data.o object rceated from progs/btf_data.c. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Andrii Nakryiko <andriin@fb.com> Acked-by: Andrii Nakryiko <andriin@fb.com> Link: https://lore.kernel.org/bpf/20200711215329.41165-10-jolsa@kernel.org
This commit is contained in:
parent
e5a0516ec9
commit
cc15a20d5f
@ -111,6 +111,7 @@ SCRATCH_DIR := $(OUTPUT)/tools
|
||||
BUILD_DIR := $(SCRATCH_DIR)/build
|
||||
INCLUDE_DIR := $(SCRATCH_DIR)/include
|
||||
BPFOBJ := $(BUILD_DIR)/libbpf/libbpf.a
|
||||
RESOLVE_BTFIDS := $(BUILD_DIR)/resolve_btfids/resolve_btfids
|
||||
|
||||
# Define simple and short `make test_progs`, `make test_sysctl`, etc targets
|
||||
# to build individual tests.
|
||||
@ -177,7 +178,7 @@ $(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \
|
||||
$(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) OUTPUT=$(BUILD_DIR)/libbpf/ \
|
||||
DESTDIR=$(SCRATCH_DIR) prefix= all install_headers
|
||||
|
||||
$(BUILD_DIR)/libbpf $(BUILD_DIR)/bpftool $(INCLUDE_DIR):
|
||||
$(BUILD_DIR)/libbpf $(BUILD_DIR)/bpftool $(BUILD_DIR)/resolve_btfids $(INCLUDE_DIR):
|
||||
$(call msg,MKDIR,,$@)
|
||||
mkdir -p $@
|
||||
|
||||
@ -190,6 +191,16 @@ else
|
||||
cp "$(VMLINUX_H)" $@
|
||||
endif
|
||||
|
||||
$(RESOLVE_BTFIDS): $(BPFOBJ) | $(BUILD_DIR)/resolve_btfids \
|
||||
$(TOOLSDIR)/bpf/resolve_btfids/main.c \
|
||||
$(TOOLSDIR)/lib/rbtree.c \
|
||||
$(TOOLSDIR)/lib/zalloc.c \
|
||||
$(TOOLSDIR)/lib/string.c \
|
||||
$(TOOLSDIR)/lib/ctype.c \
|
||||
$(TOOLSDIR)/lib/str_error_r.c
|
||||
$(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/resolve_btfids \
|
||||
OUTPUT=$(BUILD_DIR)/resolve_btfids/ BPFOBJ=$(BPFOBJ)
|
||||
|
||||
# Get Clang's default includes on this system, as opposed to those seen by
|
||||
# '-target bpf'. This fixes "missing" files on some architectures/distros,
|
||||
# such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc.
|
||||
@ -352,9 +363,11 @@ endif
|
||||
|
||||
$(OUTPUT)/$(TRUNNER_BINARY): $(TRUNNER_TEST_OBJS) \
|
||||
$(TRUNNER_EXTRA_OBJS) $$(BPFOBJ) \
|
||||
$(RESOLVE_BTFIDS) \
|
||||
| $(TRUNNER_BINARY)-extras
|
||||
$$(call msg,BINARY,,$$@)
|
||||
$$(CC) $$(CFLAGS) $$(filter %.a %.o,$$^) $$(LDLIBS) -o $$@
|
||||
$(RESOLVE_BTFIDS) --no-fail --btf btf_data.o $$@
|
||||
|
||||
endef
|
||||
|
||||
|
111
tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
Normal file
111
tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
Normal file
@ -0,0 +1,111 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <string.h>
|
||||
#include <bpf/btf.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <linux/btf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/btf_ids.h>
|
||||
#include "test_progs.h"
|
||||
|
||||
static int duration;
|
||||
|
||||
struct symbol {
|
||||
const char *name;
|
||||
int type;
|
||||
int id;
|
||||
};
|
||||
|
||||
struct symbol test_symbols[] = {
|
||||
{ "unused", BTF_KIND_UNKN, 0 },
|
||||
{ "S", BTF_KIND_TYPEDEF, -1 },
|
||||
{ "T", BTF_KIND_TYPEDEF, -1 },
|
||||
{ "U", BTF_KIND_TYPEDEF, -1 },
|
||||
{ "S", BTF_KIND_STRUCT, -1 },
|
||||
{ "U", BTF_KIND_UNION, -1 },
|
||||
{ "func", BTF_KIND_FUNC, -1 },
|
||||
};
|
||||
|
||||
BTF_ID_LIST(test_list)
|
||||
BTF_ID_UNUSED
|
||||
BTF_ID(typedef, S)
|
||||
BTF_ID(typedef, T)
|
||||
BTF_ID(typedef, U)
|
||||
BTF_ID(struct, S)
|
||||
BTF_ID(union, U)
|
||||
BTF_ID(func, func)
|
||||
|
||||
static int
|
||||
__resolve_symbol(struct btf *btf, int type_id)
|
||||
{
|
||||
const struct btf_type *type;
|
||||
const char *str;
|
||||
unsigned int i;
|
||||
|
||||
type = btf__type_by_id(btf, type_id);
|
||||
if (!type) {
|
||||
PRINT_FAIL("Failed to get type for ID %d\n", type_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_symbols); i++) {
|
||||
if (test_symbols[i].id != -1)
|
||||
continue;
|
||||
|
||||
if (BTF_INFO_KIND(type->info) != test_symbols[i].type)
|
||||
continue;
|
||||
|
||||
str = btf__name_by_offset(btf, type->name_off);
|
||||
if (!str) {
|
||||
PRINT_FAIL("Failed to get name for BTF ID %d\n", type_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp(str, test_symbols[i].name))
|
||||
test_symbols[i].id = type_id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resolve_symbols(void)
|
||||
{
|
||||
struct btf *btf;
|
||||
int type_id;
|
||||
__u32 nr;
|
||||
|
||||
btf = btf__parse_elf("btf_data.o", NULL);
|
||||
if (CHECK(libbpf_get_error(btf), "resolve",
|
||||
"Failed to load BTF from btf_data.o\n"))
|
||||
return -1;
|
||||
|
||||
nr = btf__get_nr_types(btf);
|
||||
|
||||
for (type_id = 1; type_id <= nr; type_id++) {
|
||||
if (__resolve_symbol(btf, type_id))
|
||||
break;
|
||||
}
|
||||
|
||||
btf__free(btf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_resolve_btfids(void)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
|
||||
if (resolve_symbols())
|
||||
return -1;
|
||||
|
||||
/* Check BTF_ID_LIST(test_list) IDs */
|
||||
for (i = 0; i < ARRAY_SIZE(test_symbols) && !ret; i++) {
|
||||
ret = CHECK(test_list[i] != test_symbols[i].id,
|
||||
"id_check",
|
||||
"wrong ID for %s (%d != %d)\n", test_symbols[i].name,
|
||||
test_list[i], test_symbols[i].id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
50
tools/testing/selftests/bpf/progs/btf_data.c
Normal file
50
tools/testing/selftests/bpf/progs/btf_data.c
Normal file
@ -0,0 +1,50 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
struct S {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
union U {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
struct S1 {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
union U1 {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
typedef int T;
|
||||
typedef int S;
|
||||
typedef int U;
|
||||
typedef int T1;
|
||||
typedef int S1;
|
||||
typedef int U1;
|
||||
|
||||
struct root_struct {
|
||||
S m_1;
|
||||
T m_2;
|
||||
U m_3;
|
||||
S1 m_4;
|
||||
T1 m_5;
|
||||
U1 m_6;
|
||||
struct S m_7;
|
||||
struct S1 m_8;
|
||||
union U m_9;
|
||||
union U1 m_10;
|
||||
};
|
||||
|
||||
int func(struct root_struct *root)
|
||||
{
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user