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 BTF_ID_LIST(test_list_local) 32 BTF_ID_UNUSED 33 BTF_ID(typedef, S) 34 BTF_ID(typedef, T) 35 BTF_ID(typedef, U) 36 BTF_ID(struct, S) 37 BTF_ID(union, U) 38 BTF_ID(func, func) 39 40 extern __u32 test_list_global[]; 41 BTF_ID_LIST_GLOBAL(test_list_global) 42 BTF_ID_UNUSED 43 BTF_ID(typedef, S) 44 BTF_ID(typedef, T) 45 BTF_ID(typedef, U) 46 BTF_ID(struct, S) 47 BTF_ID(union, U) 48 BTF_ID(func, func) 49 50 BTF_SET_START(test_set) 51 BTF_ID(typedef, S) 52 BTF_ID(typedef, T) 53 BTF_ID(typedef, U) 54 BTF_ID(struct, S) 55 BTF_ID(union, U) 56 BTF_ID(func, func) 57 BTF_SET_END(test_set) 58 59 static int 60 __resolve_symbol(struct btf *btf, int type_id) 61 { 62 const struct btf_type *type; 63 const char *str; 64 unsigned int i; 65 66 type = btf__type_by_id(btf, type_id); 67 if (!type) { 68 PRINT_FAIL("Failed to get type for ID %d\n", type_id); 69 return -1; 70 } 71 72 for (i = 0; i < ARRAY_SIZE(test_symbols); i++) { 73 if (test_symbols[i].id != -1) 74 continue; 75 76 if (BTF_INFO_KIND(type->info) != test_symbols[i].type) 77 continue; 78 79 str = btf__name_by_offset(btf, type->name_off); 80 if (!str) { 81 PRINT_FAIL("Failed to get name for BTF ID %d\n", type_id); 82 return -1; 83 } 84 85 if (!strcmp(str, test_symbols[i].name)) 86 test_symbols[i].id = type_id; 87 } 88 89 return 0; 90 } 91 92 static int resolve_symbols(void) 93 { 94 struct btf *btf; 95 int type_id; 96 __u32 nr; 97 98 btf = btf__parse_elf("btf_data.o", NULL); 99 if (CHECK(libbpf_get_error(btf), "resolve", 100 "Failed to load BTF from btf_data.o\n")) 101 return -1; 102 103 nr = btf__get_nr_types(btf); 104 105 for (type_id = 1; type_id <= nr; type_id++) { 106 if (__resolve_symbol(btf, type_id)) 107 break; 108 } 109 110 btf__free(btf); 111 return 0; 112 } 113 114 int test_resolve_btfids(void) 115 { 116 __u32 *test_list, *test_lists[] = { test_list_local, test_list_global }; 117 unsigned int i, j; 118 int ret = 0; 119 120 if (resolve_symbols()) 121 return -1; 122 123 /* Check BTF_ID_LIST(test_list_local) and 124 * BTF_ID_LIST_GLOBAL(test_list_global) IDs 125 */ 126 for (j = 0; j < ARRAY_SIZE(test_lists); j++) { 127 test_list = test_lists[j]; 128 for (i = 0; i < ARRAY_SIZE(test_symbols); i++) { 129 ret = CHECK(test_list[i] != test_symbols[i].id, 130 "id_check", 131 "wrong ID for %s (%d != %d)\n", 132 test_symbols[i].name, 133 test_list[i], test_symbols[i].id); 134 if (ret) 135 return ret; 136 } 137 } 138 139 /* Check BTF_SET_START(test_set) IDs */ 140 for (i = 0; i < test_set.cnt; i++) { 141 bool found = false; 142 143 for (j = 0; j < ARRAY_SIZE(test_symbols); j++) { 144 if (test_symbols[j].id != test_set.ids[i]) 145 continue; 146 found = true; 147 break; 148 } 149 150 ret = CHECK(!found, "id_check", 151 "ID %d not found in test_symbols\n", 152 test_set.ids[i]); 153 if (ret) 154 break; 155 156 if (i > 0) { 157 ret = CHECK(test_set.ids[i - 1] > test_set.ids[i], 158 "sort_check", 159 "test_set is not sorted\n"); 160 if (ret) 161 break; 162 } 163 } 164 165 return ret; 166 } 167