-
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: Test BTF's handling of endianness
Add selftests juggling endianness back and forth to validate BTF's handling of endianness convertions internally. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20200929043046.1324350-4-andriin@fb.com
- Loading branch information
Andrii Nakryiko
authored and
Alexei Starovoitov
committed
Sep 29, 2020
1 parent
3289959
commit ed9cf24
Showing
1 changed file
with
101 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (c) 2020 Facebook */ | ||
#define _GNU_SOURCE | ||
#include <string.h> | ||
#include <byteswap.h> | ||
#include <test_progs.h> | ||
#include <bpf/btf.h> | ||
|
||
static int duration = 0; | ||
|
||
void test_btf_endian() { | ||
#if __BYTE_ORDER == __LITTLE_ENDIAN | ||
enum btf_endianness endian = BTF_LITTLE_ENDIAN; | ||
#elif __BYTE_ORDER == __BIG_ENDIAN | ||
enum btf_endianness endian = BTF_BIG_ENDIAN; | ||
#else | ||
#error "Unrecognized __BYTE_ORDER" | ||
#endif | ||
enum btf_endianness swap_endian = 1 - endian; | ||
struct btf *btf = NULL, *swap_btf = NULL; | ||
const void *raw_data, *swap_raw_data; | ||
const struct btf_type *t; | ||
const struct btf_header *hdr; | ||
__u32 raw_sz, swap_raw_sz; | ||
int var_id; | ||
|
||
/* Load BTF in native endianness */ | ||
btf = btf__parse_elf("btf_dump_test_case_syntax.o", NULL); | ||
if (!ASSERT_OK_PTR(btf, "parse_native_btf")) | ||
goto err_out; | ||
|
||
ASSERT_EQ(btf__endianness(btf), endian, "endian"); | ||
btf__set_endianness(btf, swap_endian); | ||
ASSERT_EQ(btf__endianness(btf), swap_endian, "endian"); | ||
|
||
/* Get raw BTF data in non-native endianness... */ | ||
raw_data = btf__get_raw_data(btf, &raw_sz); | ||
if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted")) | ||
goto err_out; | ||
|
||
/* ...and open it as a new BTF instance */ | ||
swap_btf = btf__new(raw_data, raw_sz); | ||
if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf")) | ||
goto err_out; | ||
|
||
ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian"); | ||
ASSERT_EQ(btf__get_nr_types(swap_btf), btf__get_nr_types(btf), "nr_types"); | ||
|
||
swap_raw_data = btf__get_raw_data(swap_btf, &swap_raw_sz); | ||
if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data")) | ||
goto err_out; | ||
|
||
/* both raw data should be identical (with non-native endianness) */ | ||
ASSERT_OK(memcmp(raw_data, swap_raw_data, raw_sz), "mem_identical"); | ||
|
||
/* make sure that at least BTF header data is really swapped */ | ||
hdr = swap_raw_data; | ||
ASSERT_EQ(bswap_16(hdr->magic), BTF_MAGIC, "btf_magic_swapped"); | ||
ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes"); | ||
|
||
/* swap it back to native endianness */ | ||
btf__set_endianness(swap_btf, endian); | ||
swap_raw_data = btf__get_raw_data(swap_btf, &swap_raw_sz); | ||
if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data")) | ||
goto err_out; | ||
|
||
/* now header should have native BTF_MAGIC */ | ||
hdr = swap_raw_data; | ||
ASSERT_EQ(hdr->magic, BTF_MAGIC, "btf_magic_native"); | ||
ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes"); | ||
|
||
/* now modify original BTF */ | ||
var_id = btf__add_var(btf, "some_var", BTF_VAR_GLOBAL_ALLOCATED, 1); | ||
CHECK(var_id <= 0, "var_id", "failed %d\n", var_id); | ||
|
||
btf__free(swap_btf); | ||
swap_btf = NULL; | ||
|
||
btf__set_endianness(btf, swap_endian); | ||
raw_data = btf__get_raw_data(btf, &raw_sz); | ||
if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted")) | ||
goto err_out; | ||
|
||
/* and re-open swapped raw data again */ | ||
swap_btf = btf__new(raw_data, raw_sz); | ||
if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf")) | ||
goto err_out; | ||
|
||
ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian"); | ||
ASSERT_EQ(btf__get_nr_types(swap_btf), btf__get_nr_types(btf), "nr_types"); | ||
|
||
/* the type should appear as if it was stored in native endianness */ | ||
t = btf__type_by_id(swap_btf, var_id); | ||
ASSERT_STREQ(btf__str_by_offset(swap_btf, t->name_off), "some_var", "var_name"); | ||
ASSERT_EQ(btf_var(t)->linkage, BTF_VAR_GLOBAL_ALLOCATED, "var_linkage"); | ||
ASSERT_EQ(t->type, 1, "var_type"); | ||
|
||
err_out: | ||
btf__free(btf); | ||
btf__free(swap_btf); | ||
} |