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 static int 51 __resolve_symbol(struct btf *btf, int type_id) 52 { 53 const struct btf_type *type; 54 const char *str; 55 unsigned int i; 56 57 type = btf__type_by_id(btf, type_id); 58 if (!type) { 59 PRINT_FAIL("Failed to get type for ID %d\n", type_id); 60 return -1; 61 } 62 63 for (i = 0; i < ARRAY_SIZE(test_symbols); i++) { 64 if (test_symbols[i].id != -1) 65 continue; 66 67 if (BTF_INFO_KIND(type->info) != test_symbols[i].type) 68 continue; 69 70 str = btf__name_by_offset(btf, type->name_off); 71 if (!str) { 72 PRINT_FAIL("Failed to get name for BTF ID %d\n", type_id); 73 return -1; 74 } 75 76 if (!strcmp(str, test_symbols[i].name)) 77 test_symbols[i].id = type_id; 78 } 79 80 return 0; 81 } 82 83 static int resolve_symbols(void) 84 { 85 struct btf *btf; 86 int type_id; 87 __u32 nr; 88 89 btf = btf__parse_elf("btf_data.o", NULL); 90 if (CHECK(libbpf_get_error(btf), "resolve", 91 "Failed to load BTF from btf_data.o\n")) 92 return -1; 93 94 nr = btf__get_nr_types(btf); 95 96 for (type_id = 1; type_id <= nr; type_id++) { 97 if (__resolve_symbol(btf, type_id)) 98 break; 99 } 100 101 btf__free(btf); 102 return 0; 103 } 104 105 int test_resolve_btfids(void) 106 { 107 __u32 *test_list, *test_lists[] = { test_list_local, test_list_global }; 108 unsigned int i, j; 109 int ret = 0; 110 111 if (resolve_symbols()) 112 return -1; 113 114 /* Check BTF_ID_LIST(test_list_local) and 115 * BTF_ID_LIST_GLOBAL(test_list_global) IDs 116 */ 117 for (j = 0; j < ARRAY_SIZE(test_lists); j++) { 118 test_list = test_lists[j]; 119 for (i = 0; i < ARRAY_SIZE(test_symbols) && !ret; i++) { 120 ret = CHECK(test_list[i] != test_symbols[i].id, 121 "id_check", 122 "wrong ID for %s (%d != %d)\n", 123 test_symbols[i].name, 124 test_list[i], test_symbols[i].id); 125 } 126 } 127 128 return ret; 129 } 130