1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/err.h> 4 #include <string.h> 5 #include <bpf/btf.h> 6 #include <bpf/libbpf.h> 7 #include <linux/btf.h> 8 #include <linux/kernel.h> 9 #define CONFIG_DEBUG_INFO_BTF 10 #include <linux/btf_ids.h> 11 #include "test_progs.h" 12 13 static int duration; 14 15 struct symbol { 16 const char *name; 17 int type; 18 int id; 19 }; 20 21 struct symbol test_symbols[] = { 22 { "unused", BTF_KIND_UNKN, 0 }, 23 { "S", BTF_KIND_TYPEDEF, -1 }, 24 { "T", BTF_KIND_TYPEDEF, -1 }, 25 { "U", BTF_KIND_TYPEDEF, -1 }, 26 { "S", BTF_KIND_STRUCT, -1 }, 27 { "U", BTF_KIND_UNION, -1 }, 28 { "func", BTF_KIND_FUNC, -1 }, 29 }; 30 31 /* Align the .BTF_ids section to 4 bytes */ 32 asm ( 33 ".pushsection " BTF_IDS_SECTION " ,\"a\"; \n" 34 ".balign 4, 0; \n" 35 ".popsection; \n"); 36 37 BTF_ID_LIST(test_list_local) 38 BTF_ID_UNUSED 39 BTF_ID(typedef, S) 40 BTF_ID(typedef, T) 41 BTF_ID(typedef, U) 42 BTF_ID(struct, S) 43 BTF_ID(union, U) 44 BTF_ID(func, func) 45 46 extern __u32 test_list_global[]; 47 BTF_ID_LIST_GLOBAL(test_list_global, 1) 48 BTF_ID_UNUSED 49 BTF_ID(typedef, S) 50 BTF_ID(typedef, T) 51 BTF_ID(typedef, U) 52 BTF_ID(struct, S) 53 BTF_ID(union, U) 54 BTF_ID(func, func) 55 56 BTF_SET_START(test_set) 57 BTF_ID(typedef, S) 58 BTF_ID(typedef, T) 59 BTF_ID(typedef, U) 60 BTF_ID(struct, S) 61 BTF_ID(union, U) 62 BTF_ID(func, func) 63 BTF_SET_END(test_set) 64 65 static int 66 __resolve_symbol(struct btf *btf, int type_id) 67 { 68 const struct btf_type *type; 69 const char *str; 70 unsigned int i; 71 72 type = btf__type_by_id(btf, type_id); 73 if (!type) { 74 PRINT_FAIL("Failed to get type for ID %d\n", type_id); 75 return -1; 76 } 77 78 for (i = 0; i < ARRAY_SIZE(test_symbols); i++) { 79 if (test_symbols[i].id >= 0) 80 continue; 81 82 if (BTF_INFO_KIND(type->info) != test_symbols[i].type) 83 continue; 84 85 str = btf__name_by_offset(btf, type->name_off); 86 if (!str) { 87 PRINT_FAIL("Failed to get name for BTF ID %d\n", type_id); 88 return -1; 89 } 90 91 if (!strcmp(str, test_symbols[i].name)) 92 test_symbols[i].id = type_id; 93 } 94 95 return 0; 96 } 97 98 static int resolve_symbols(void) 99 { 100 struct btf *btf; 101 int type_id; 102 __u32 nr; 103 104 btf = btf__parse_elf("btf_data.o", NULL); 105 if (CHECK(libbpf_get_error(btf), "resolve", 106 "Failed to load BTF from btf_data.o\n")) 107 return -1; 108 109 nr = btf__type_cnt(btf); 110 111 for (type_id = 1; type_id < nr; type_id++) { 112 if (__resolve_symbol(btf, type_id)) 113 break; 114 } 115 116 btf__free(btf); 117 return 0; 118 } 119 120 void test_resolve_btfids(void) 121 { 122 __u32 *test_list, *test_lists[] = { test_list_local, test_list_global }; 123 unsigned int i, j; 124 int ret = 0; 125 126 if (resolve_symbols()) 127 return; 128 129 /* Check BTF_ID_LIST(test_list_local) and 130 * BTF_ID_LIST_GLOBAL(test_list_global) IDs 131 */ 132 for (j = 0; j < ARRAY_SIZE(test_lists); j++) { 133 test_list = test_lists[j]; 134 for (i = 0; i < ARRAY_SIZE(test_symbols); i++) { 135 ret = CHECK(test_list[i] != test_symbols[i].id, 136 "id_check", 137 "wrong ID for %s (%d != %d)\n", 138 test_symbols[i].name, 139 test_list[i], test_symbols[i].id); 140 if (ret) 141 return; 142 } 143 } 144 145 /* Check BTF_SET_START(test_set) IDs */ 146 for (i = 0; i < test_set.cnt; i++) { 147 bool found = false; 148 149 for (j = 0; j < ARRAY_SIZE(test_symbols); j++) { 150 if (test_symbols[j].id != test_set.ids[i]) 151 continue; 152 found = true; 153 break; 154 } 155 156 ret = CHECK(!found, "id_check", 157 "ID %d not found in test_symbols\n", 158 test_set.ids[i]); 159 if (ret) 160 break; 161 162 if (i > 0) { 163 if (!ASSERT_LE(test_set.ids[i - 1], test_set.ids[i], "sort_check")) 164 return; 165 } 166 } 167 } 168