18a138aedSMartin KaFai Lau /* SPDX-License-Identifier: GPL-2.0 */ 28a138aedSMartin KaFai Lau /* Copyright (c) 2018 Facebook */ 38a138aedSMartin KaFai Lau 48a138aedSMartin KaFai Lau #include <stdlib.h> 58a138aedSMartin KaFai Lau #include <stdint.h> 68a138aedSMartin KaFai Lau #include <string.h> 78a138aedSMartin KaFai Lau #include <unistd.h> 88a138aedSMartin KaFai Lau #include <errno.h> 98a138aedSMartin KaFai Lau #include <linux/err.h> 108a138aedSMartin KaFai Lau #include <linux/btf.h> 118a138aedSMartin KaFai Lau #include "btf.h" 128a138aedSMartin KaFai Lau #include "bpf.h" 138a138aedSMartin KaFai Lau 148a138aedSMartin KaFai Lau #define elog(fmt, ...) { if (err_log) err_log(fmt, ##__VA_ARGS__); } 158a138aedSMartin KaFai Lau #define max(a, b) ((a) > (b) ? (a) : (b)) 168a138aedSMartin KaFai Lau #define min(a, b) ((a) < (b) ? (a) : (b)) 178a138aedSMartin KaFai Lau 188a138aedSMartin KaFai Lau #define BTF_MAX_NR_TYPES 65535 198a138aedSMartin KaFai Lau 20*92b57121SOkash Khawaja #define IS_MODIFIER(k) (((k) == BTF_KIND_TYPEDEF) || \ 21*92b57121SOkash Khawaja ((k) == BTF_KIND_VOLATILE) || \ 22*92b57121SOkash Khawaja ((k) == BTF_KIND_CONST) || \ 23*92b57121SOkash Khawaja ((k) == BTF_KIND_RESTRICT)) 24*92b57121SOkash Khawaja 258a138aedSMartin KaFai Lau static struct btf_type btf_void; 268a138aedSMartin KaFai Lau 278a138aedSMartin KaFai Lau struct btf { 288a138aedSMartin KaFai Lau union { 298a138aedSMartin KaFai Lau struct btf_header *hdr; 308a138aedSMartin KaFai Lau void *data; 318a138aedSMartin KaFai Lau }; 328a138aedSMartin KaFai Lau struct btf_type **types; 338a138aedSMartin KaFai Lau const char *strings; 348a138aedSMartin KaFai Lau void *nohdr_data; 358a138aedSMartin KaFai Lau uint32_t nr_types; 368a138aedSMartin KaFai Lau uint32_t types_size; 378a138aedSMartin KaFai Lau uint32_t data_size; 388a138aedSMartin KaFai Lau int fd; 398a138aedSMartin KaFai Lau }; 408a138aedSMartin KaFai Lau 418a138aedSMartin KaFai Lau static int btf_add_type(struct btf *btf, struct btf_type *t) 428a138aedSMartin KaFai Lau { 438a138aedSMartin KaFai Lau if (btf->types_size - btf->nr_types < 2) { 448a138aedSMartin KaFai Lau struct btf_type **new_types; 458a138aedSMartin KaFai Lau u32 expand_by, new_size; 468a138aedSMartin KaFai Lau 478a138aedSMartin KaFai Lau if (btf->types_size == BTF_MAX_NR_TYPES) 488a138aedSMartin KaFai Lau return -E2BIG; 498a138aedSMartin KaFai Lau 508a138aedSMartin KaFai Lau expand_by = max(btf->types_size >> 2, 16); 518a138aedSMartin KaFai Lau new_size = min(BTF_MAX_NR_TYPES, btf->types_size + expand_by); 528a138aedSMartin KaFai Lau 538a138aedSMartin KaFai Lau new_types = realloc(btf->types, sizeof(*new_types) * new_size); 548a138aedSMartin KaFai Lau if (!new_types) 558a138aedSMartin KaFai Lau return -ENOMEM; 568a138aedSMartin KaFai Lau 578a138aedSMartin KaFai Lau if (btf->nr_types == 0) 588a138aedSMartin KaFai Lau new_types[0] = &btf_void; 598a138aedSMartin KaFai Lau 608a138aedSMartin KaFai Lau btf->types = new_types; 618a138aedSMartin KaFai Lau btf->types_size = new_size; 628a138aedSMartin KaFai Lau } 638a138aedSMartin KaFai Lau 648a138aedSMartin KaFai Lau btf->types[++(btf->nr_types)] = t; 658a138aedSMartin KaFai Lau 668a138aedSMartin KaFai Lau return 0; 678a138aedSMartin KaFai Lau } 688a138aedSMartin KaFai Lau 698a138aedSMartin KaFai Lau static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log) 708a138aedSMartin KaFai Lau { 718a138aedSMartin KaFai Lau const struct btf_header *hdr = btf->hdr; 728a138aedSMartin KaFai Lau u32 meta_left; 738a138aedSMartin KaFai Lau 748a138aedSMartin KaFai Lau if (btf->data_size < sizeof(struct btf_header)) { 758a138aedSMartin KaFai Lau elog("BTF header not found\n"); 768a138aedSMartin KaFai Lau return -EINVAL; 778a138aedSMartin KaFai Lau } 788a138aedSMartin KaFai Lau 798a138aedSMartin KaFai Lau if (hdr->magic != BTF_MAGIC) { 808a138aedSMartin KaFai Lau elog("Invalid BTF magic:%x\n", hdr->magic); 818a138aedSMartin KaFai Lau return -EINVAL; 828a138aedSMartin KaFai Lau } 838a138aedSMartin KaFai Lau 848a138aedSMartin KaFai Lau if (hdr->version != BTF_VERSION) { 858a138aedSMartin KaFai Lau elog("Unsupported BTF version:%u\n", hdr->version); 868a138aedSMartin KaFai Lau return -ENOTSUP; 878a138aedSMartin KaFai Lau } 888a138aedSMartin KaFai Lau 898a138aedSMartin KaFai Lau if (hdr->flags) { 908a138aedSMartin KaFai Lau elog("Unsupported BTF flags:%x\n", hdr->flags); 918a138aedSMartin KaFai Lau return -ENOTSUP; 928a138aedSMartin KaFai Lau } 938a138aedSMartin KaFai Lau 948a138aedSMartin KaFai Lau meta_left = btf->data_size - sizeof(*hdr); 958a138aedSMartin KaFai Lau if (!meta_left) { 968a138aedSMartin KaFai Lau elog("BTF has no data\n"); 978a138aedSMartin KaFai Lau return -EINVAL; 988a138aedSMartin KaFai Lau } 998a138aedSMartin KaFai Lau 1008a138aedSMartin KaFai Lau if (meta_left < hdr->type_off) { 1018a138aedSMartin KaFai Lau elog("Invalid BTF type section offset:%u\n", hdr->type_off); 1028a138aedSMartin KaFai Lau return -EINVAL; 1038a138aedSMartin KaFai Lau } 1048a138aedSMartin KaFai Lau 1058a138aedSMartin KaFai Lau if (meta_left < hdr->str_off) { 1068a138aedSMartin KaFai Lau elog("Invalid BTF string section offset:%u\n", hdr->str_off); 1078a138aedSMartin KaFai Lau return -EINVAL; 1088a138aedSMartin KaFai Lau } 1098a138aedSMartin KaFai Lau 1108a138aedSMartin KaFai Lau if (hdr->type_off >= hdr->str_off) { 1118a138aedSMartin KaFai Lau elog("BTF type section offset >= string section offset. No type?\n"); 1128a138aedSMartin KaFai Lau return -EINVAL; 1138a138aedSMartin KaFai Lau } 1148a138aedSMartin KaFai Lau 1158a138aedSMartin KaFai Lau if (hdr->type_off & 0x02) { 1168a138aedSMartin KaFai Lau elog("BTF type section is not aligned to 4 bytes\n"); 1178a138aedSMartin KaFai Lau return -EINVAL; 1188a138aedSMartin KaFai Lau } 1198a138aedSMartin KaFai Lau 1208a138aedSMartin KaFai Lau btf->nohdr_data = btf->hdr + 1; 1218a138aedSMartin KaFai Lau 1228a138aedSMartin KaFai Lau return 0; 1238a138aedSMartin KaFai Lau } 1248a138aedSMartin KaFai Lau 1258a138aedSMartin KaFai Lau static int btf_parse_str_sec(struct btf *btf, btf_print_fn_t err_log) 1268a138aedSMartin KaFai Lau { 1278a138aedSMartin KaFai Lau const struct btf_header *hdr = btf->hdr; 1288a138aedSMartin KaFai Lau const char *start = btf->nohdr_data + hdr->str_off; 1298a138aedSMartin KaFai Lau const char *end = start + btf->hdr->str_len; 1308a138aedSMartin KaFai Lau 1318a138aedSMartin KaFai Lau if (!hdr->str_len || hdr->str_len - 1 > BTF_MAX_NAME_OFFSET || 1328a138aedSMartin KaFai Lau start[0] || end[-1]) { 1338a138aedSMartin KaFai Lau elog("Invalid BTF string section\n"); 1348a138aedSMartin KaFai Lau return -EINVAL; 1358a138aedSMartin KaFai Lau } 1368a138aedSMartin KaFai Lau 1378a138aedSMartin KaFai Lau btf->strings = start; 1388a138aedSMartin KaFai Lau 1398a138aedSMartin KaFai Lau return 0; 1408a138aedSMartin KaFai Lau } 1418a138aedSMartin KaFai Lau 1428a138aedSMartin KaFai Lau static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log) 1438a138aedSMartin KaFai Lau { 1448a138aedSMartin KaFai Lau struct btf_header *hdr = btf->hdr; 1458a138aedSMartin KaFai Lau void *nohdr_data = btf->nohdr_data; 1468a138aedSMartin KaFai Lau void *next_type = nohdr_data + hdr->type_off; 1478a138aedSMartin KaFai Lau void *end_type = nohdr_data + hdr->str_off; 1488a138aedSMartin KaFai Lau 1498a138aedSMartin KaFai Lau while (next_type < end_type) { 1508a138aedSMartin KaFai Lau struct btf_type *t = next_type; 1518a138aedSMartin KaFai Lau uint16_t vlen = BTF_INFO_VLEN(t->info); 1528a138aedSMartin KaFai Lau int err; 1538a138aedSMartin KaFai Lau 1548a138aedSMartin KaFai Lau next_type += sizeof(*t); 1558a138aedSMartin KaFai Lau switch (BTF_INFO_KIND(t->info)) { 1568a138aedSMartin KaFai Lau case BTF_KIND_INT: 1578a138aedSMartin KaFai Lau next_type += sizeof(int); 1588a138aedSMartin KaFai Lau break; 1598a138aedSMartin KaFai Lau case BTF_KIND_ARRAY: 1608a138aedSMartin KaFai Lau next_type += sizeof(struct btf_array); 1618a138aedSMartin KaFai Lau break; 1628a138aedSMartin KaFai Lau case BTF_KIND_STRUCT: 1638a138aedSMartin KaFai Lau case BTF_KIND_UNION: 1648a138aedSMartin KaFai Lau next_type += vlen * sizeof(struct btf_member); 1658a138aedSMartin KaFai Lau break; 1668a138aedSMartin KaFai Lau case BTF_KIND_ENUM: 1678a138aedSMartin KaFai Lau next_type += vlen * sizeof(struct btf_enum); 1688a138aedSMartin KaFai Lau break; 1698a138aedSMartin KaFai Lau case BTF_KIND_TYPEDEF: 1708a138aedSMartin KaFai Lau case BTF_KIND_PTR: 1718a138aedSMartin KaFai Lau case BTF_KIND_FWD: 1728a138aedSMartin KaFai Lau case BTF_KIND_VOLATILE: 1738a138aedSMartin KaFai Lau case BTF_KIND_CONST: 1748a138aedSMartin KaFai Lau case BTF_KIND_RESTRICT: 1758a138aedSMartin KaFai Lau break; 1768a138aedSMartin KaFai Lau default: 1778a138aedSMartin KaFai Lau elog("Unsupported BTF_KIND:%u\n", 1788a138aedSMartin KaFai Lau BTF_INFO_KIND(t->info)); 1798a138aedSMartin KaFai Lau return -EINVAL; 1808a138aedSMartin KaFai Lau } 1818a138aedSMartin KaFai Lau 1828a138aedSMartin KaFai Lau err = btf_add_type(btf, t); 1838a138aedSMartin KaFai Lau if (err) 1848a138aedSMartin KaFai Lau return err; 1858a138aedSMartin KaFai Lau } 1868a138aedSMartin KaFai Lau 1878a138aedSMartin KaFai Lau return 0; 1888a138aedSMartin KaFai Lau } 1898a138aedSMartin KaFai Lau 1908a138aedSMartin KaFai Lau static bool btf_type_is_void(const struct btf_type *t) 1918a138aedSMartin KaFai Lau { 1928a138aedSMartin KaFai Lau return t == &btf_void || BTF_INFO_KIND(t->info) == BTF_KIND_FWD; 1938a138aedSMartin KaFai Lau } 1948a138aedSMartin KaFai Lau 1958a138aedSMartin KaFai Lau static bool btf_type_is_void_or_null(const struct btf_type *t) 1968a138aedSMartin KaFai Lau { 1978a138aedSMartin KaFai Lau return !t || btf_type_is_void(t); 1988a138aedSMartin KaFai Lau } 1998a138aedSMartin KaFai Lau 2008a138aedSMartin KaFai Lau static int64_t btf_type_size(const struct btf_type *t) 2018a138aedSMartin KaFai Lau { 2028a138aedSMartin KaFai Lau switch (BTF_INFO_KIND(t->info)) { 2038a138aedSMartin KaFai Lau case BTF_KIND_INT: 2048a138aedSMartin KaFai Lau case BTF_KIND_STRUCT: 2058a138aedSMartin KaFai Lau case BTF_KIND_UNION: 2068a138aedSMartin KaFai Lau case BTF_KIND_ENUM: 2078a138aedSMartin KaFai Lau return t->size; 2088a138aedSMartin KaFai Lau case BTF_KIND_PTR: 2098a138aedSMartin KaFai Lau return sizeof(void *); 2108a138aedSMartin KaFai Lau default: 2118a138aedSMartin KaFai Lau return -EINVAL; 2128a138aedSMartin KaFai Lau } 2138a138aedSMartin KaFai Lau } 2148a138aedSMartin KaFai Lau 2158a138aedSMartin KaFai Lau #define MAX_RESOLVE_DEPTH 32 2168a138aedSMartin KaFai Lau 2178a138aedSMartin KaFai Lau int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id) 2188a138aedSMartin KaFai Lau { 2198a138aedSMartin KaFai Lau const struct btf_array *array; 2208a138aedSMartin KaFai Lau const struct btf_type *t; 2218a138aedSMartin KaFai Lau uint32_t nelems = 1; 2228a138aedSMartin KaFai Lau int64_t size = -1; 2238a138aedSMartin KaFai Lau int i; 2248a138aedSMartin KaFai Lau 225*92b57121SOkash Khawaja t = btf__type_by_id(btf, type_id); 2268a138aedSMartin KaFai Lau for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t); 2278a138aedSMartin KaFai Lau i++) { 2288a138aedSMartin KaFai Lau size = btf_type_size(t); 2298a138aedSMartin KaFai Lau if (size >= 0) 2308a138aedSMartin KaFai Lau break; 2318a138aedSMartin KaFai Lau 2328a138aedSMartin KaFai Lau switch (BTF_INFO_KIND(t->info)) { 2338a138aedSMartin KaFai Lau case BTF_KIND_TYPEDEF: 2348a138aedSMartin KaFai Lau case BTF_KIND_VOLATILE: 2358a138aedSMartin KaFai Lau case BTF_KIND_CONST: 2368a138aedSMartin KaFai Lau case BTF_KIND_RESTRICT: 2378a138aedSMartin KaFai Lau type_id = t->type; 2388a138aedSMartin KaFai Lau break; 2398a138aedSMartin KaFai Lau case BTF_KIND_ARRAY: 2408a138aedSMartin KaFai Lau array = (const struct btf_array *)(t + 1); 2418a138aedSMartin KaFai Lau if (nelems && array->nelems > UINT32_MAX / nelems) 2428a138aedSMartin KaFai Lau return -E2BIG; 2438a138aedSMartin KaFai Lau nelems *= array->nelems; 2448a138aedSMartin KaFai Lau type_id = array->type; 2458a138aedSMartin KaFai Lau break; 2468a138aedSMartin KaFai Lau default: 2478a138aedSMartin KaFai Lau return -EINVAL; 2488a138aedSMartin KaFai Lau } 2498a138aedSMartin KaFai Lau 250*92b57121SOkash Khawaja t = btf__type_by_id(btf, type_id); 2518a138aedSMartin KaFai Lau } 2528a138aedSMartin KaFai Lau 2538a138aedSMartin KaFai Lau if (size < 0) 2548a138aedSMartin KaFai Lau return -EINVAL; 2558a138aedSMartin KaFai Lau 2568a138aedSMartin KaFai Lau if (nelems && size > UINT32_MAX / nelems) 2578a138aedSMartin KaFai Lau return -E2BIG; 2588a138aedSMartin KaFai Lau 2598a138aedSMartin KaFai Lau return nelems * size; 2608a138aedSMartin KaFai Lau } 2618a138aedSMartin KaFai Lau 262*92b57121SOkash Khawaja int btf__resolve_type(const struct btf *btf, __u32 type_id) 263*92b57121SOkash Khawaja { 264*92b57121SOkash Khawaja const struct btf_type *t; 265*92b57121SOkash Khawaja int depth = 0; 266*92b57121SOkash Khawaja 267*92b57121SOkash Khawaja t = btf__type_by_id(btf, type_id); 268*92b57121SOkash Khawaja while (depth < MAX_RESOLVE_DEPTH && 269*92b57121SOkash Khawaja !btf_type_is_void_or_null(t) && 270*92b57121SOkash Khawaja IS_MODIFIER(BTF_INFO_KIND(t->info))) { 271*92b57121SOkash Khawaja type_id = t->type; 272*92b57121SOkash Khawaja t = btf__type_by_id(btf, type_id); 273*92b57121SOkash Khawaja depth++; 274*92b57121SOkash Khawaja } 275*92b57121SOkash Khawaja 276*92b57121SOkash Khawaja if (depth == MAX_RESOLVE_DEPTH || btf_type_is_void_or_null(t)) 277*92b57121SOkash Khawaja return -EINVAL; 278*92b57121SOkash Khawaja 279*92b57121SOkash Khawaja return type_id; 280*92b57121SOkash Khawaja } 281*92b57121SOkash Khawaja 2828a138aedSMartin KaFai Lau int32_t btf__find_by_name(const struct btf *btf, const char *type_name) 2838a138aedSMartin KaFai Lau { 2848a138aedSMartin KaFai Lau uint32_t i; 2858a138aedSMartin KaFai Lau 2868a138aedSMartin KaFai Lau if (!strcmp(type_name, "void")) 2878a138aedSMartin KaFai Lau return 0; 2888a138aedSMartin KaFai Lau 2898a138aedSMartin KaFai Lau for (i = 1; i <= btf->nr_types; i++) { 2908a138aedSMartin KaFai Lau const struct btf_type *t = btf->types[i]; 291*92b57121SOkash Khawaja const char *name = btf__name_by_offset(btf, t->name_off); 2928a138aedSMartin KaFai Lau 2938a138aedSMartin KaFai Lau if (name && !strcmp(type_name, name)) 2948a138aedSMartin KaFai Lau return i; 2958a138aedSMartin KaFai Lau } 2968a138aedSMartin KaFai Lau 2978a138aedSMartin KaFai Lau return -ENOENT; 2988a138aedSMartin KaFai Lau } 2998a138aedSMartin KaFai Lau 3008a138aedSMartin KaFai Lau void btf__free(struct btf *btf) 3018a138aedSMartin KaFai Lau { 3028a138aedSMartin KaFai Lau if (!btf) 3038a138aedSMartin KaFai Lau return; 3048a138aedSMartin KaFai Lau 3058a138aedSMartin KaFai Lau if (btf->fd != -1) 3068a138aedSMartin KaFai Lau close(btf->fd); 3078a138aedSMartin KaFai Lau 3088a138aedSMartin KaFai Lau free(btf->data); 3098a138aedSMartin KaFai Lau free(btf->types); 3108a138aedSMartin KaFai Lau free(btf); 3118a138aedSMartin KaFai Lau } 3128a138aedSMartin KaFai Lau 3138a138aedSMartin KaFai Lau struct btf *btf__new(uint8_t *data, uint32_t size, 3148a138aedSMartin KaFai Lau btf_print_fn_t err_log) 3158a138aedSMartin KaFai Lau { 3168a138aedSMartin KaFai Lau uint32_t log_buf_size = 0; 3178a138aedSMartin KaFai Lau char *log_buf = NULL; 3188a138aedSMartin KaFai Lau struct btf *btf; 3198a138aedSMartin KaFai Lau int err; 3208a138aedSMartin KaFai Lau 3218a138aedSMartin KaFai Lau btf = calloc(1, sizeof(struct btf)); 3228a138aedSMartin KaFai Lau if (!btf) 3238a138aedSMartin KaFai Lau return ERR_PTR(-ENOMEM); 3248a138aedSMartin KaFai Lau 3258a138aedSMartin KaFai Lau btf->fd = -1; 3268a138aedSMartin KaFai Lau 3278a138aedSMartin KaFai Lau if (err_log) { 3288a138aedSMartin KaFai Lau log_buf = malloc(BPF_LOG_BUF_SIZE); 3298a138aedSMartin KaFai Lau if (!log_buf) { 3308a138aedSMartin KaFai Lau err = -ENOMEM; 3318a138aedSMartin KaFai Lau goto done; 3328a138aedSMartin KaFai Lau } 3338a138aedSMartin KaFai Lau *log_buf = 0; 3348a138aedSMartin KaFai Lau log_buf_size = BPF_LOG_BUF_SIZE; 3358a138aedSMartin KaFai Lau } 3368a138aedSMartin KaFai Lau 3378a138aedSMartin KaFai Lau btf->data = malloc(size); 3388a138aedSMartin KaFai Lau if (!btf->data) { 3398a138aedSMartin KaFai Lau err = -ENOMEM; 3408a138aedSMartin KaFai Lau goto done; 3418a138aedSMartin KaFai Lau } 3428a138aedSMartin KaFai Lau 3438a138aedSMartin KaFai Lau memcpy(btf->data, data, size); 3448a138aedSMartin KaFai Lau btf->data_size = size; 3458a138aedSMartin KaFai Lau 3468a138aedSMartin KaFai Lau btf->fd = bpf_load_btf(btf->data, btf->data_size, 3478a138aedSMartin KaFai Lau log_buf, log_buf_size, false); 3488a138aedSMartin KaFai Lau 3498a138aedSMartin KaFai Lau if (btf->fd == -1) { 3508a138aedSMartin KaFai Lau err = -errno; 3518a138aedSMartin KaFai Lau elog("Error loading BTF: %s(%d)\n", strerror(errno), errno); 3528a138aedSMartin KaFai Lau if (log_buf && *log_buf) 3538a138aedSMartin KaFai Lau elog("%s\n", log_buf); 3548a138aedSMartin KaFai Lau goto done; 3558a138aedSMartin KaFai Lau } 3568a138aedSMartin KaFai Lau 3578a138aedSMartin KaFai Lau err = btf_parse_hdr(btf, err_log); 3588a138aedSMartin KaFai Lau if (err) 3598a138aedSMartin KaFai Lau goto done; 3608a138aedSMartin KaFai Lau 3618a138aedSMartin KaFai Lau err = btf_parse_str_sec(btf, err_log); 3628a138aedSMartin KaFai Lau if (err) 3638a138aedSMartin KaFai Lau goto done; 3648a138aedSMartin KaFai Lau 3658a138aedSMartin KaFai Lau err = btf_parse_type_sec(btf, err_log); 3668a138aedSMartin KaFai Lau 3678a138aedSMartin KaFai Lau done: 3688a138aedSMartin KaFai Lau free(log_buf); 3698a138aedSMartin KaFai Lau 3708a138aedSMartin KaFai Lau if (err) { 3718a138aedSMartin KaFai Lau btf__free(btf); 3728a138aedSMartin KaFai Lau return ERR_PTR(err); 3738a138aedSMartin KaFai Lau } 3748a138aedSMartin KaFai Lau 3758a138aedSMartin KaFai Lau return btf; 3768a138aedSMartin KaFai Lau } 3778a138aedSMartin KaFai Lau 3788a138aedSMartin KaFai Lau int btf__fd(const struct btf *btf) 3798a138aedSMartin KaFai Lau { 3808a138aedSMartin KaFai Lau return btf->fd; 3818a138aedSMartin KaFai Lau } 382*92b57121SOkash Khawaja 383*92b57121SOkash Khawaja const char *btf__name_by_offset(const struct btf *btf, __u32 offset) 384*92b57121SOkash Khawaja { 385*92b57121SOkash Khawaja if (offset < btf->hdr->str_len) 386*92b57121SOkash Khawaja return &btf->strings[offset]; 387*92b57121SOkash Khawaja else 388*92b57121SOkash Khawaja return NULL; 389*92b57121SOkash Khawaja } 390*92b57121SOkash Khawaja 391*92b57121SOkash Khawaja const struct btf_type *btf__type_by_id(const struct btf *btf, 392*92b57121SOkash Khawaja __u32 type_id) 393*92b57121SOkash Khawaja { 394*92b57121SOkash Khawaja if (type_id > btf->nr_types) 395*92b57121SOkash Khawaja return NULL; 396*92b57121SOkash Khawaja 397*92b57121SOkash Khawaja return btf->types[type_id]; 398*92b57121SOkash Khawaja } 399