Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2020 Facebook */
0003 #define _GNU_SOURCE
0004 #include <string.h>
0005 #include <byteswap.h>
0006 #include <test_progs.h>
0007 #include <bpf/btf.h>
0008 
0009 void test_btf_endian() {
0010 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
0011     enum btf_endianness endian = BTF_LITTLE_ENDIAN;
0012 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
0013     enum btf_endianness endian = BTF_BIG_ENDIAN;
0014 #else
0015 #error "Unrecognized __BYTE_ORDER__"
0016 #endif
0017     enum btf_endianness swap_endian = 1 - endian;
0018     struct btf *btf = NULL, *swap_btf = NULL;
0019     const void *raw_data, *swap_raw_data;
0020     const struct btf_type *t;
0021     const struct btf_header *hdr;
0022     __u32 raw_sz, swap_raw_sz;
0023     int var_id;
0024 
0025     /* Load BTF in native endianness */
0026     btf = btf__parse_elf("btf_dump_test_case_syntax.o", NULL);
0027     if (!ASSERT_OK_PTR(btf, "parse_native_btf"))
0028         goto err_out;
0029 
0030     ASSERT_EQ(btf__endianness(btf), endian, "endian");
0031     btf__set_endianness(btf, swap_endian);
0032     ASSERT_EQ(btf__endianness(btf), swap_endian, "endian");
0033 
0034     /* Get raw BTF data in non-native endianness... */
0035     raw_data = btf__raw_data(btf, &raw_sz);
0036     if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted"))
0037         goto err_out;
0038 
0039     /* ...and open it as a new BTF instance */
0040     swap_btf = btf__new(raw_data, raw_sz);
0041     if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf"))
0042         goto err_out;
0043 
0044     ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian");
0045     ASSERT_EQ(btf__type_cnt(swap_btf), btf__type_cnt(btf), "nr_types");
0046 
0047     swap_raw_data = btf__raw_data(swap_btf, &swap_raw_sz);
0048     if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data"))
0049         goto err_out;
0050 
0051     /* both raw data should be identical (with non-native endianness) */
0052     ASSERT_OK(memcmp(raw_data, swap_raw_data, raw_sz), "mem_identical");
0053 
0054     /* make sure that at least BTF header data is really swapped */
0055     hdr = swap_raw_data;
0056     ASSERT_EQ(bswap_16(hdr->magic), BTF_MAGIC, "btf_magic_swapped");
0057     ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes");
0058 
0059     /* swap it back to native endianness */
0060     btf__set_endianness(swap_btf, endian);
0061     swap_raw_data = btf__raw_data(swap_btf, &swap_raw_sz);
0062     if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data"))
0063         goto err_out;
0064 
0065     /* now header should have native BTF_MAGIC */
0066     hdr = swap_raw_data;
0067     ASSERT_EQ(hdr->magic, BTF_MAGIC, "btf_magic_native");
0068     ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes");
0069 
0070     /* now modify original BTF */
0071     var_id = btf__add_var(btf, "some_var", BTF_VAR_GLOBAL_ALLOCATED, 1);
0072     ASSERT_GT(var_id, 0, "var_id");
0073 
0074     btf__free(swap_btf);
0075     swap_btf = NULL;
0076 
0077     btf__set_endianness(btf, swap_endian);
0078     raw_data = btf__raw_data(btf, &raw_sz);
0079     if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted"))
0080         goto err_out;
0081 
0082     /* and re-open swapped raw data again */
0083     swap_btf = btf__new(raw_data, raw_sz);
0084     if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf"))
0085         goto err_out;
0086 
0087     ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian");
0088     ASSERT_EQ(btf__type_cnt(swap_btf), btf__type_cnt(btf), "nr_types");
0089 
0090     /* the type should appear as if it was stored in native endianness */
0091     t = btf__type_by_id(swap_btf, var_id);
0092     ASSERT_STREQ(btf__str_by_offset(swap_btf, t->name_off), "some_var", "var_name");
0093     ASSERT_EQ(btf_var(t)->linkage, BTF_VAR_GLOBAL_ALLOCATED, "var_linkage");
0094     ASSERT_EQ(t->type, 1, "var_type");
0095 
0096 err_out:
0097     btf__free(btf);
0098     btf__free(swap_btf);
0099 }