100 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2020 Facebook */3#define _GNU_SOURCE4#include <string.h>5#include <byteswap.h>6#include <test_progs.h>7#include <bpf/btf.h>8 9void test_btf_endian() {10#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__11 enum btf_endianness endian = BTF_LITTLE_ENDIAN;12#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__13 enum btf_endianness endian = BTF_BIG_ENDIAN;14#else15#error "Unrecognized __BYTE_ORDER__"16#endif17 enum btf_endianness swap_endian = 1 - endian;18 struct btf *btf = NULL, *swap_btf = NULL;19 const void *raw_data, *swap_raw_data;20 const struct btf_type *t;21 const struct btf_header *hdr;22 __u32 raw_sz, swap_raw_sz;23 int var_id;24 25 /* Load BTF in native endianness */26 btf = btf__parse_elf("btf_dump_test_case_syntax.bpf.o", NULL);27 if (!ASSERT_OK_PTR(btf, "parse_native_btf"))28 goto err_out;29 30 ASSERT_EQ(btf__endianness(btf), endian, "endian");31 btf__set_endianness(btf, swap_endian);32 ASSERT_EQ(btf__endianness(btf), swap_endian, "endian");33 34 /* Get raw BTF data in non-native endianness... */35 raw_data = btf__raw_data(btf, &raw_sz);36 if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted"))37 goto err_out;38 39 /* ...and open it as a new BTF instance */40 swap_btf = btf__new(raw_data, raw_sz);41 if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf"))42 goto err_out;43 44 ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian");45 ASSERT_EQ(btf__type_cnt(swap_btf), btf__type_cnt(btf), "nr_types");46 47 swap_raw_data = btf__raw_data(swap_btf, &swap_raw_sz);48 if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data"))49 goto err_out;50 51 /* both raw data should be identical (with non-native endianness) */52 ASSERT_OK(memcmp(raw_data, swap_raw_data, raw_sz), "mem_identical");53 54 /* make sure that at least BTF header data is really swapped */55 hdr = swap_raw_data;56 ASSERT_EQ(bswap_16(hdr->magic), BTF_MAGIC, "btf_magic_swapped");57 ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes");58 59 /* swap it back to native endianness */60 btf__set_endianness(swap_btf, endian);61 swap_raw_data = btf__raw_data(swap_btf, &swap_raw_sz);62 if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data"))63 goto err_out;64 65 /* now header should have native BTF_MAGIC */66 hdr = swap_raw_data;67 ASSERT_EQ(hdr->magic, BTF_MAGIC, "btf_magic_native");68 ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes");69 70 /* now modify original BTF */71 var_id = btf__add_var(btf, "some_var", BTF_VAR_GLOBAL_ALLOCATED, 1);72 ASSERT_GT(var_id, 0, "var_id");73 74 btf__free(swap_btf);75 swap_btf = NULL;76 77 btf__set_endianness(btf, swap_endian);78 raw_data = btf__raw_data(btf, &raw_sz);79 if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted"))80 goto err_out;81 82 /* and re-open swapped raw data again */83 swap_btf = btf__new(raw_data, raw_sz);84 if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf"))85 goto err_out;86 87 ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian");88 ASSERT_EQ(btf__type_cnt(swap_btf), btf__type_cnt(btf), "nr_types");89 90 /* the type should appear as if it was stored in native endianness */91 t = btf__type_by_id(swap_btf, var_id);92 ASSERT_STREQ(btf__str_by_offset(swap_btf, t->name_off), "some_var", "var_name");93 ASSERT_EQ(btf_var(t)->linkage, BTF_VAR_GLOBAL_ALLOCATED, "var_linkage");94 ASSERT_EQ(t->type, 1, "var_type");95 96err_out:97 btf__free(btf);98 btf__free(swap_btf);99}100