Skip to content

Commit

Permalink
selftests/bpf: Add test for resolve_btfids
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Jiri Olsa authored and Alexei Starovoitov committed Jul 13, 2020
1 parent e5a0516 commit cc15a20
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 1 deletion.
15 changes: 14 additions & 1 deletion tools/testing/selftests/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 $@

Expand All @@ -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.
Expand Down Expand Up @@ -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

Expand Down
111 changes: 111 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
Original file line number Diff line number Diff line change
@@ -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 changes: 50 additions & 0 deletions tools/testing/selftests/bpf/progs/btf_data.c
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit cc15a20

Please sign in to comment.