xref: /linux/tools/testing/selftests/bpf/prog_tests/btf_endian.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1ed9cf248SAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
2ed9cf248SAndrii Nakryiko /* Copyright (c) 2020 Facebook */
3ed9cf248SAndrii Nakryiko #define _GNU_SOURCE
4ed9cf248SAndrii Nakryiko #include <string.h>
5ed9cf248SAndrii Nakryiko #include <byteswap.h>
6ed9cf248SAndrii Nakryiko #include <test_progs.h>
7ed9cf248SAndrii Nakryiko #include <bpf/btf.h>
8ed9cf248SAndrii Nakryiko 
test_btf_endian()9ed9cf248SAndrii Nakryiko void test_btf_endian() {
1006fca841SIlya Leoshkevich #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
11ed9cf248SAndrii Nakryiko 	enum btf_endianness endian = BTF_LITTLE_ENDIAN;
1206fca841SIlya Leoshkevich #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
13ed9cf248SAndrii Nakryiko 	enum btf_endianness endian = BTF_BIG_ENDIAN;
14ed9cf248SAndrii Nakryiko #else
1506fca841SIlya Leoshkevich #error "Unrecognized __BYTE_ORDER__"
16ed9cf248SAndrii Nakryiko #endif
17ed9cf248SAndrii Nakryiko 	enum btf_endianness swap_endian = 1 - endian;
18ed9cf248SAndrii Nakryiko 	struct btf *btf = NULL, *swap_btf = NULL;
19ed9cf248SAndrii Nakryiko 	const void *raw_data, *swap_raw_data;
20ed9cf248SAndrii Nakryiko 	const struct btf_type *t;
21ed9cf248SAndrii Nakryiko 	const struct btf_header *hdr;
22ed9cf248SAndrii Nakryiko 	__u32 raw_sz, swap_raw_sz;
23ed9cf248SAndrii Nakryiko 	int var_id;
24ed9cf248SAndrii Nakryiko 
25ed9cf248SAndrii Nakryiko 	/* Load BTF in native endianness */
26*afef88e6SDaniel Müller 	btf = btf__parse_elf("btf_dump_test_case_syntax.bpf.o", NULL);
27ed9cf248SAndrii Nakryiko 	if (!ASSERT_OK_PTR(btf, "parse_native_btf"))
28ed9cf248SAndrii Nakryiko 		goto err_out;
29ed9cf248SAndrii Nakryiko 
30ed9cf248SAndrii Nakryiko 	ASSERT_EQ(btf__endianness(btf), endian, "endian");
31ed9cf248SAndrii Nakryiko 	btf__set_endianness(btf, swap_endian);
32ed9cf248SAndrii Nakryiko 	ASSERT_EQ(btf__endianness(btf), swap_endian, "endian");
33ed9cf248SAndrii Nakryiko 
34ed9cf248SAndrii Nakryiko 	/* Get raw BTF data in non-native endianness... */
35487ef148SHengqi Chen 	raw_data = btf__raw_data(btf, &raw_sz);
36ed9cf248SAndrii Nakryiko 	if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted"))
37ed9cf248SAndrii Nakryiko 		goto err_out;
38ed9cf248SAndrii Nakryiko 
39ed9cf248SAndrii Nakryiko 	/* ...and open it as a new BTF instance */
40ed9cf248SAndrii Nakryiko 	swap_btf = btf__new(raw_data, raw_sz);
41ed9cf248SAndrii Nakryiko 	if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf"))
42ed9cf248SAndrii Nakryiko 		goto err_out;
43ed9cf248SAndrii Nakryiko 
44ed9cf248SAndrii Nakryiko 	ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian");
45487ef148SHengqi Chen 	ASSERT_EQ(btf__type_cnt(swap_btf), btf__type_cnt(btf), "nr_types");
46ed9cf248SAndrii Nakryiko 
47487ef148SHengqi Chen 	swap_raw_data = btf__raw_data(swap_btf, &swap_raw_sz);
48ed9cf248SAndrii Nakryiko 	if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data"))
49ed9cf248SAndrii Nakryiko 		goto err_out;
50ed9cf248SAndrii Nakryiko 
51ed9cf248SAndrii Nakryiko 	/* both raw data should be identical (with non-native endianness) */
52ed9cf248SAndrii Nakryiko 	ASSERT_OK(memcmp(raw_data, swap_raw_data, raw_sz), "mem_identical");
53ed9cf248SAndrii Nakryiko 
54ed9cf248SAndrii Nakryiko 	/* make sure that at least BTF header data is really swapped */
55ed9cf248SAndrii Nakryiko 	hdr = swap_raw_data;
56ed9cf248SAndrii Nakryiko 	ASSERT_EQ(bswap_16(hdr->magic), BTF_MAGIC, "btf_magic_swapped");
57ed9cf248SAndrii Nakryiko 	ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes");
58ed9cf248SAndrii Nakryiko 
59ed9cf248SAndrii Nakryiko 	/* swap it back to native endianness */
60ed9cf248SAndrii Nakryiko 	btf__set_endianness(swap_btf, endian);
61487ef148SHengqi Chen 	swap_raw_data = btf__raw_data(swap_btf, &swap_raw_sz);
62ed9cf248SAndrii Nakryiko 	if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data"))
63ed9cf248SAndrii Nakryiko 		goto err_out;
64ed9cf248SAndrii Nakryiko 
65ed9cf248SAndrii Nakryiko 	/* now header should have native BTF_MAGIC */
66ed9cf248SAndrii Nakryiko 	hdr = swap_raw_data;
67ed9cf248SAndrii Nakryiko 	ASSERT_EQ(hdr->magic, BTF_MAGIC, "btf_magic_native");
68ed9cf248SAndrii Nakryiko 	ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes");
69ed9cf248SAndrii Nakryiko 
70ed9cf248SAndrii Nakryiko 	/* now modify original BTF */
71ed9cf248SAndrii Nakryiko 	var_id = btf__add_var(btf, "some_var", BTF_VAR_GLOBAL_ALLOCATED, 1);
727a2fa70aSAndrii Nakryiko 	ASSERT_GT(var_id, 0, "var_id");
73ed9cf248SAndrii Nakryiko 
74ed9cf248SAndrii Nakryiko 	btf__free(swap_btf);
75ed9cf248SAndrii Nakryiko 	swap_btf = NULL;
76ed9cf248SAndrii Nakryiko 
77ed9cf248SAndrii Nakryiko 	btf__set_endianness(btf, swap_endian);
78487ef148SHengqi Chen 	raw_data = btf__raw_data(btf, &raw_sz);
79ed9cf248SAndrii Nakryiko 	if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted"))
80ed9cf248SAndrii Nakryiko 		goto err_out;
81ed9cf248SAndrii Nakryiko 
82ed9cf248SAndrii Nakryiko 	/* and re-open swapped raw data again */
83ed9cf248SAndrii Nakryiko 	swap_btf = btf__new(raw_data, raw_sz);
84ed9cf248SAndrii Nakryiko 	if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf"))
85ed9cf248SAndrii Nakryiko 		goto err_out;
86ed9cf248SAndrii Nakryiko 
87ed9cf248SAndrii Nakryiko 	ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian");
88487ef148SHengqi Chen 	ASSERT_EQ(btf__type_cnt(swap_btf), btf__type_cnt(btf), "nr_types");
89ed9cf248SAndrii Nakryiko 
90ed9cf248SAndrii Nakryiko 	/* the type should appear as if it was stored in native endianness */
91ed9cf248SAndrii Nakryiko 	t = btf__type_by_id(swap_btf, var_id);
92ed9cf248SAndrii Nakryiko 	ASSERT_STREQ(btf__str_by_offset(swap_btf, t->name_off), "some_var", "var_name");
93ed9cf248SAndrii Nakryiko 	ASSERT_EQ(btf_var(t)->linkage, BTF_VAR_GLOBAL_ALLOCATED, "var_linkage");
94ed9cf248SAndrii Nakryiko 	ASSERT_EQ(t->type, 1, "var_type");
95ed9cf248SAndrii Nakryiko 
96ed9cf248SAndrii Nakryiko err_out:
97ed9cf248SAndrii Nakryiko 	btf__free(btf);
98ed9cf248SAndrii Nakryiko 	btf__free(swap_btf);
99ed9cf248SAndrii Nakryiko }
100