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