-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Jiri Olsa
authored and
Alexei Starovoitov
committed
Jul 13, 2020
1 parent
e5a0516
commit cc15a20
Showing
3 changed files
with
175 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |