168 lines · c
1// SPDX-License-Identifier: GPL-2.02 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_BTF10#include <linux/btf_ids.h>11#include "test_progs.h"12 13static int duration;14 15struct symbol {16 const char *name;17 int type;18 int id;19};20 21struct 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 */32asm (33".pushsection " BTF_IDS_SECTION " ,\"a\"; \n"34".balign 4, 0; \n"35".popsection; \n");36 37BTF_ID_LIST(test_list_local)38BTF_ID_UNUSED39BTF_ID(typedef, S)40BTF_ID(typedef, T)41BTF_ID(typedef, U)42BTF_ID(struct, S)43BTF_ID(union, U)44BTF_ID(func, func)45 46extern __u32 test_list_global[];47BTF_ID_LIST_GLOBAL(test_list_global, 1)48BTF_ID_UNUSED49BTF_ID(typedef, S)50BTF_ID(typedef, T)51BTF_ID(typedef, U)52BTF_ID(struct, S)53BTF_ID(union, U)54BTF_ID(func, func)55 56BTF_SET_START(test_set)57BTF_ID(typedef, S)58BTF_ID(typedef, T)59BTF_ID(typedef, U)60BTF_ID(struct, S)61BTF_ID(union, U)62BTF_ID(func, func)63BTF_SET_END(test_set)64 65static int66__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 98static int resolve_symbols(void)99{100 struct btf *btf;101 int type_id;102 __u32 nr;103 104 btf = btf__parse_elf("btf_data.bpf.o", NULL);105 if (CHECK(libbpf_get_error(btf), "resolve",106 "Failed to load BTF from btf_data.bpf.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 120void 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) and130 * BTF_ID_LIST_GLOBAL(test_list_global) IDs131 */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