xref: /openbmc/linux/tools/lib/bpf/btf.c (revision 8a138aed4a807ceb143882fb23a423d524dcdb35)
1*8a138aedSMartin KaFai Lau /* SPDX-License-Identifier: GPL-2.0 */
2*8a138aedSMartin KaFai Lau /* Copyright (c) 2018 Facebook */
3*8a138aedSMartin KaFai Lau 
4*8a138aedSMartin KaFai Lau #include <stdlib.h>
5*8a138aedSMartin KaFai Lau #include <stdint.h>
6*8a138aedSMartin KaFai Lau #include <string.h>
7*8a138aedSMartin KaFai Lau #include <unistd.h>
8*8a138aedSMartin KaFai Lau #include <errno.h>
9*8a138aedSMartin KaFai Lau #include <linux/err.h>
10*8a138aedSMartin KaFai Lau #include <linux/btf.h>
11*8a138aedSMartin KaFai Lau #include "btf.h"
12*8a138aedSMartin KaFai Lau #include "bpf.h"
13*8a138aedSMartin KaFai Lau 
14*8a138aedSMartin KaFai Lau #define elog(fmt, ...) { if (err_log) err_log(fmt, ##__VA_ARGS__); }
15*8a138aedSMartin KaFai Lau #define max(a, b) ((a) > (b) ? (a) : (b))
16*8a138aedSMartin KaFai Lau #define min(a, b) ((a) < (b) ? (a) : (b))
17*8a138aedSMartin KaFai Lau 
18*8a138aedSMartin KaFai Lau #define BTF_MAX_NR_TYPES 65535
19*8a138aedSMartin KaFai Lau 
20*8a138aedSMartin KaFai Lau static struct btf_type btf_void;
21*8a138aedSMartin KaFai Lau 
22*8a138aedSMartin KaFai Lau struct btf {
23*8a138aedSMartin KaFai Lau 	union {
24*8a138aedSMartin KaFai Lau 		struct btf_header *hdr;
25*8a138aedSMartin KaFai Lau 		void *data;
26*8a138aedSMartin KaFai Lau 	};
27*8a138aedSMartin KaFai Lau 	struct btf_type **types;
28*8a138aedSMartin KaFai Lau 	const char *strings;
29*8a138aedSMartin KaFai Lau 	void *nohdr_data;
30*8a138aedSMartin KaFai Lau 	uint32_t nr_types;
31*8a138aedSMartin KaFai Lau 	uint32_t types_size;
32*8a138aedSMartin KaFai Lau 	uint32_t data_size;
33*8a138aedSMartin KaFai Lau 	int fd;
34*8a138aedSMartin KaFai Lau };
35*8a138aedSMartin KaFai Lau 
36*8a138aedSMartin KaFai Lau static const char *btf_name_by_offset(const struct btf *btf, uint32_t offset)
37*8a138aedSMartin KaFai Lau {
38*8a138aedSMartin KaFai Lau 	if (!BTF_STR_TBL_ELF_ID(offset) &&
39*8a138aedSMartin KaFai Lau 	    BTF_STR_OFFSET(offset) < btf->hdr->str_len)
40*8a138aedSMartin KaFai Lau 		return &btf->strings[BTF_STR_OFFSET(offset)];
41*8a138aedSMartin KaFai Lau 	else
42*8a138aedSMartin KaFai Lau 		return NULL;
43*8a138aedSMartin KaFai Lau }
44*8a138aedSMartin KaFai Lau 
45*8a138aedSMartin KaFai Lau static int btf_add_type(struct btf *btf, struct btf_type *t)
46*8a138aedSMartin KaFai Lau {
47*8a138aedSMartin KaFai Lau 	if (btf->types_size - btf->nr_types < 2) {
48*8a138aedSMartin KaFai Lau 		struct btf_type **new_types;
49*8a138aedSMartin KaFai Lau 		u32 expand_by, new_size;
50*8a138aedSMartin KaFai Lau 
51*8a138aedSMartin KaFai Lau 		if (btf->types_size == BTF_MAX_NR_TYPES)
52*8a138aedSMartin KaFai Lau 			return -E2BIG;
53*8a138aedSMartin KaFai Lau 
54*8a138aedSMartin KaFai Lau 		expand_by = max(btf->types_size >> 2, 16);
55*8a138aedSMartin KaFai Lau 		new_size = min(BTF_MAX_NR_TYPES, btf->types_size + expand_by);
56*8a138aedSMartin KaFai Lau 
57*8a138aedSMartin KaFai Lau 		new_types = realloc(btf->types, sizeof(*new_types) * new_size);
58*8a138aedSMartin KaFai Lau 		if (!new_types)
59*8a138aedSMartin KaFai Lau 			return -ENOMEM;
60*8a138aedSMartin KaFai Lau 
61*8a138aedSMartin KaFai Lau 		if (btf->nr_types == 0)
62*8a138aedSMartin KaFai Lau 			new_types[0] = &btf_void;
63*8a138aedSMartin KaFai Lau 
64*8a138aedSMartin KaFai Lau 		btf->types = new_types;
65*8a138aedSMartin KaFai Lau 		btf->types_size = new_size;
66*8a138aedSMartin KaFai Lau 	}
67*8a138aedSMartin KaFai Lau 
68*8a138aedSMartin KaFai Lau 	btf->types[++(btf->nr_types)] = t;
69*8a138aedSMartin KaFai Lau 
70*8a138aedSMartin KaFai Lau 	return 0;
71*8a138aedSMartin KaFai Lau }
72*8a138aedSMartin KaFai Lau 
73*8a138aedSMartin KaFai Lau static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log)
74*8a138aedSMartin KaFai Lau {
75*8a138aedSMartin KaFai Lau 	const struct btf_header *hdr = btf->hdr;
76*8a138aedSMartin KaFai Lau 	u32 meta_left;
77*8a138aedSMartin KaFai Lau 
78*8a138aedSMartin KaFai Lau 	if (btf->data_size < sizeof(struct btf_header)) {
79*8a138aedSMartin KaFai Lau 		elog("BTF header not found\n");
80*8a138aedSMartin KaFai Lau 		return -EINVAL;
81*8a138aedSMartin KaFai Lau 	}
82*8a138aedSMartin KaFai Lau 
83*8a138aedSMartin KaFai Lau 	if (hdr->magic != BTF_MAGIC) {
84*8a138aedSMartin KaFai Lau 		elog("Invalid BTF magic:%x\n", hdr->magic);
85*8a138aedSMartin KaFai Lau 		return -EINVAL;
86*8a138aedSMartin KaFai Lau 	}
87*8a138aedSMartin KaFai Lau 
88*8a138aedSMartin KaFai Lau 	if (hdr->version != BTF_VERSION) {
89*8a138aedSMartin KaFai Lau 		elog("Unsupported BTF version:%u\n", hdr->version);
90*8a138aedSMartin KaFai Lau 		return -ENOTSUP;
91*8a138aedSMartin KaFai Lau 	}
92*8a138aedSMartin KaFai Lau 
93*8a138aedSMartin KaFai Lau 	if (hdr->flags) {
94*8a138aedSMartin KaFai Lau 		elog("Unsupported BTF flags:%x\n", hdr->flags);
95*8a138aedSMartin KaFai Lau 		return -ENOTSUP;
96*8a138aedSMartin KaFai Lau 	}
97*8a138aedSMartin KaFai Lau 
98*8a138aedSMartin KaFai Lau 	meta_left = btf->data_size - sizeof(*hdr);
99*8a138aedSMartin KaFai Lau 	if (!meta_left) {
100*8a138aedSMartin KaFai Lau 		elog("BTF has no data\n");
101*8a138aedSMartin KaFai Lau 		return -EINVAL;
102*8a138aedSMartin KaFai Lau 	}
103*8a138aedSMartin KaFai Lau 
104*8a138aedSMartin KaFai Lau 	if (meta_left < hdr->type_off) {
105*8a138aedSMartin KaFai Lau 		elog("Invalid BTF type section offset:%u\n", hdr->type_off);
106*8a138aedSMartin KaFai Lau 		return -EINVAL;
107*8a138aedSMartin KaFai Lau 	}
108*8a138aedSMartin KaFai Lau 
109*8a138aedSMartin KaFai Lau 	if (meta_left < hdr->str_off) {
110*8a138aedSMartin KaFai Lau 		elog("Invalid BTF string section offset:%u\n", hdr->str_off);
111*8a138aedSMartin KaFai Lau 		return -EINVAL;
112*8a138aedSMartin KaFai Lau 	}
113*8a138aedSMartin KaFai Lau 
114*8a138aedSMartin KaFai Lau 	if (hdr->type_off >= hdr->str_off) {
115*8a138aedSMartin KaFai Lau 		elog("BTF type section offset >= string section offset. No type?\n");
116*8a138aedSMartin KaFai Lau 		return -EINVAL;
117*8a138aedSMartin KaFai Lau 	}
118*8a138aedSMartin KaFai Lau 
119*8a138aedSMartin KaFai Lau 	if (hdr->type_off & 0x02) {
120*8a138aedSMartin KaFai Lau 		elog("BTF type section is not aligned to 4 bytes\n");
121*8a138aedSMartin KaFai Lau 		return -EINVAL;
122*8a138aedSMartin KaFai Lau 	}
123*8a138aedSMartin KaFai Lau 
124*8a138aedSMartin KaFai Lau 	btf->nohdr_data = btf->hdr + 1;
125*8a138aedSMartin KaFai Lau 
126*8a138aedSMartin KaFai Lau 	return 0;
127*8a138aedSMartin KaFai Lau }
128*8a138aedSMartin KaFai Lau 
129*8a138aedSMartin KaFai Lau static int btf_parse_str_sec(struct btf *btf, btf_print_fn_t err_log)
130*8a138aedSMartin KaFai Lau {
131*8a138aedSMartin KaFai Lau 	const struct btf_header *hdr = btf->hdr;
132*8a138aedSMartin KaFai Lau 	const char *start = btf->nohdr_data + hdr->str_off;
133*8a138aedSMartin KaFai Lau 	const char *end = start + btf->hdr->str_len;
134*8a138aedSMartin KaFai Lau 
135*8a138aedSMartin KaFai Lau 	if (!hdr->str_len || hdr->str_len - 1 > BTF_MAX_NAME_OFFSET ||
136*8a138aedSMartin KaFai Lau 	    start[0] || end[-1]) {
137*8a138aedSMartin KaFai Lau 		elog("Invalid BTF string section\n");
138*8a138aedSMartin KaFai Lau 		return -EINVAL;
139*8a138aedSMartin KaFai Lau 	}
140*8a138aedSMartin KaFai Lau 
141*8a138aedSMartin KaFai Lau 	btf->strings = start;
142*8a138aedSMartin KaFai Lau 
143*8a138aedSMartin KaFai Lau 	return 0;
144*8a138aedSMartin KaFai Lau }
145*8a138aedSMartin KaFai Lau 
146*8a138aedSMartin KaFai Lau static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
147*8a138aedSMartin KaFai Lau {
148*8a138aedSMartin KaFai Lau 	struct btf_header *hdr = btf->hdr;
149*8a138aedSMartin KaFai Lau 	void *nohdr_data = btf->nohdr_data;
150*8a138aedSMartin KaFai Lau 	void *next_type = nohdr_data + hdr->type_off;
151*8a138aedSMartin KaFai Lau 	void *end_type = nohdr_data + hdr->str_off;
152*8a138aedSMartin KaFai Lau 
153*8a138aedSMartin KaFai Lau 	while (next_type < end_type) {
154*8a138aedSMartin KaFai Lau 		struct btf_type *t = next_type;
155*8a138aedSMartin KaFai Lau 		uint16_t vlen = BTF_INFO_VLEN(t->info);
156*8a138aedSMartin KaFai Lau 		int err;
157*8a138aedSMartin KaFai Lau 
158*8a138aedSMartin KaFai Lau 		next_type += sizeof(*t);
159*8a138aedSMartin KaFai Lau 		switch (BTF_INFO_KIND(t->info)) {
160*8a138aedSMartin KaFai Lau 		case BTF_KIND_INT:
161*8a138aedSMartin KaFai Lau 			next_type += sizeof(int);
162*8a138aedSMartin KaFai Lau 			break;
163*8a138aedSMartin KaFai Lau 		case BTF_KIND_ARRAY:
164*8a138aedSMartin KaFai Lau 			next_type += sizeof(struct btf_array);
165*8a138aedSMartin KaFai Lau 			break;
166*8a138aedSMartin KaFai Lau 		case BTF_KIND_STRUCT:
167*8a138aedSMartin KaFai Lau 		case BTF_KIND_UNION:
168*8a138aedSMartin KaFai Lau 			next_type += vlen * sizeof(struct btf_member);
169*8a138aedSMartin KaFai Lau 			break;
170*8a138aedSMartin KaFai Lau 		case BTF_KIND_ENUM:
171*8a138aedSMartin KaFai Lau 			next_type += vlen * sizeof(struct btf_enum);
172*8a138aedSMartin KaFai Lau 			break;
173*8a138aedSMartin KaFai Lau 		case BTF_KIND_TYPEDEF:
174*8a138aedSMartin KaFai Lau 		case BTF_KIND_PTR:
175*8a138aedSMartin KaFai Lau 		case BTF_KIND_FWD:
176*8a138aedSMartin KaFai Lau 		case BTF_KIND_VOLATILE:
177*8a138aedSMartin KaFai Lau 		case BTF_KIND_CONST:
178*8a138aedSMartin KaFai Lau 		case BTF_KIND_RESTRICT:
179*8a138aedSMartin KaFai Lau 			break;
180*8a138aedSMartin KaFai Lau 		default:
181*8a138aedSMartin KaFai Lau 			elog("Unsupported BTF_KIND:%u\n",
182*8a138aedSMartin KaFai Lau 			     BTF_INFO_KIND(t->info));
183*8a138aedSMartin KaFai Lau 			return -EINVAL;
184*8a138aedSMartin KaFai Lau 		}
185*8a138aedSMartin KaFai Lau 
186*8a138aedSMartin KaFai Lau 		err = btf_add_type(btf, t);
187*8a138aedSMartin KaFai Lau 		if (err)
188*8a138aedSMartin KaFai Lau 			return err;
189*8a138aedSMartin KaFai Lau 	}
190*8a138aedSMartin KaFai Lau 
191*8a138aedSMartin KaFai Lau 	return 0;
192*8a138aedSMartin KaFai Lau }
193*8a138aedSMartin KaFai Lau 
194*8a138aedSMartin KaFai Lau static const struct btf_type *btf_type_by_id(const struct btf *btf,
195*8a138aedSMartin KaFai Lau 					     uint32_t type_id)
196*8a138aedSMartin KaFai Lau {
197*8a138aedSMartin KaFai Lau 	if (type_id > btf->nr_types)
198*8a138aedSMartin KaFai Lau 		return NULL;
199*8a138aedSMartin KaFai Lau 
200*8a138aedSMartin KaFai Lau 	return btf->types[type_id];
201*8a138aedSMartin KaFai Lau }
202*8a138aedSMartin KaFai Lau 
203*8a138aedSMartin KaFai Lau static bool btf_type_is_void(const struct btf_type *t)
204*8a138aedSMartin KaFai Lau {
205*8a138aedSMartin KaFai Lau 	return t == &btf_void || BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
206*8a138aedSMartin KaFai Lau }
207*8a138aedSMartin KaFai Lau 
208*8a138aedSMartin KaFai Lau static bool btf_type_is_void_or_null(const struct btf_type *t)
209*8a138aedSMartin KaFai Lau {
210*8a138aedSMartin KaFai Lau 	return !t || btf_type_is_void(t);
211*8a138aedSMartin KaFai Lau }
212*8a138aedSMartin KaFai Lau 
213*8a138aedSMartin KaFai Lau static int64_t btf_type_size(const struct btf_type *t)
214*8a138aedSMartin KaFai Lau {
215*8a138aedSMartin KaFai Lau 	switch (BTF_INFO_KIND(t->info)) {
216*8a138aedSMartin KaFai Lau 	case BTF_KIND_INT:
217*8a138aedSMartin KaFai Lau 	case BTF_KIND_STRUCT:
218*8a138aedSMartin KaFai Lau 	case BTF_KIND_UNION:
219*8a138aedSMartin KaFai Lau 	case BTF_KIND_ENUM:
220*8a138aedSMartin KaFai Lau 		return t->size;
221*8a138aedSMartin KaFai Lau 	case BTF_KIND_PTR:
222*8a138aedSMartin KaFai Lau 		return sizeof(void *);
223*8a138aedSMartin KaFai Lau 	default:
224*8a138aedSMartin KaFai Lau 		return -EINVAL;
225*8a138aedSMartin KaFai Lau 	}
226*8a138aedSMartin KaFai Lau }
227*8a138aedSMartin KaFai Lau 
228*8a138aedSMartin KaFai Lau #define MAX_RESOLVE_DEPTH 32
229*8a138aedSMartin KaFai Lau 
230*8a138aedSMartin KaFai Lau int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
231*8a138aedSMartin KaFai Lau {
232*8a138aedSMartin KaFai Lau 	const struct btf_array *array;
233*8a138aedSMartin KaFai Lau 	const struct btf_type *t;
234*8a138aedSMartin KaFai Lau 	uint32_t nelems = 1;
235*8a138aedSMartin KaFai Lau 	int64_t size = -1;
236*8a138aedSMartin KaFai Lau 	int i;
237*8a138aedSMartin KaFai Lau 
238*8a138aedSMartin KaFai Lau 	t = btf_type_by_id(btf, type_id);
239*8a138aedSMartin KaFai Lau 	for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t);
240*8a138aedSMartin KaFai Lau 	     i++) {
241*8a138aedSMartin KaFai Lau 		size = btf_type_size(t);
242*8a138aedSMartin KaFai Lau 		if (size >= 0)
243*8a138aedSMartin KaFai Lau 			break;
244*8a138aedSMartin KaFai Lau 
245*8a138aedSMartin KaFai Lau 		switch (BTF_INFO_KIND(t->info)) {
246*8a138aedSMartin KaFai Lau 		case BTF_KIND_TYPEDEF:
247*8a138aedSMartin KaFai Lau 		case BTF_KIND_VOLATILE:
248*8a138aedSMartin KaFai Lau 		case BTF_KIND_CONST:
249*8a138aedSMartin KaFai Lau 		case BTF_KIND_RESTRICT:
250*8a138aedSMartin KaFai Lau 			type_id = t->type;
251*8a138aedSMartin KaFai Lau 			break;
252*8a138aedSMartin KaFai Lau 		case BTF_KIND_ARRAY:
253*8a138aedSMartin KaFai Lau 			array = (const struct btf_array *)(t + 1);
254*8a138aedSMartin KaFai Lau 			if (nelems && array->nelems > UINT32_MAX / nelems)
255*8a138aedSMartin KaFai Lau 				return -E2BIG;
256*8a138aedSMartin KaFai Lau 			nelems *= array->nelems;
257*8a138aedSMartin KaFai Lau 			type_id = array->type;
258*8a138aedSMartin KaFai Lau 			break;
259*8a138aedSMartin KaFai Lau 		default:
260*8a138aedSMartin KaFai Lau 			return -EINVAL;
261*8a138aedSMartin KaFai Lau 		}
262*8a138aedSMartin KaFai Lau 
263*8a138aedSMartin KaFai Lau 		t = btf_type_by_id(btf, type_id);
264*8a138aedSMartin KaFai Lau 	}
265*8a138aedSMartin KaFai Lau 
266*8a138aedSMartin KaFai Lau 	if (size < 0)
267*8a138aedSMartin KaFai Lau 		return -EINVAL;
268*8a138aedSMartin KaFai Lau 
269*8a138aedSMartin KaFai Lau 	if (nelems && size > UINT32_MAX / nelems)
270*8a138aedSMartin KaFai Lau 		return -E2BIG;
271*8a138aedSMartin KaFai Lau 
272*8a138aedSMartin KaFai Lau 	return nelems * size;
273*8a138aedSMartin KaFai Lau }
274*8a138aedSMartin KaFai Lau 
275*8a138aedSMartin KaFai Lau int32_t btf__find_by_name(const struct btf *btf, const char *type_name)
276*8a138aedSMartin KaFai Lau {
277*8a138aedSMartin KaFai Lau 	uint32_t i;
278*8a138aedSMartin KaFai Lau 
279*8a138aedSMartin KaFai Lau 	if (!strcmp(type_name, "void"))
280*8a138aedSMartin KaFai Lau 		return 0;
281*8a138aedSMartin KaFai Lau 
282*8a138aedSMartin KaFai Lau 	for (i = 1; i <= btf->nr_types; i++) {
283*8a138aedSMartin KaFai Lau 		const struct btf_type *t = btf->types[i];
284*8a138aedSMartin KaFai Lau 		const char *name = btf_name_by_offset(btf, t->name);
285*8a138aedSMartin KaFai Lau 
286*8a138aedSMartin KaFai Lau 		if (name && !strcmp(type_name, name))
287*8a138aedSMartin KaFai Lau 			return i;
288*8a138aedSMartin KaFai Lau 	}
289*8a138aedSMartin KaFai Lau 
290*8a138aedSMartin KaFai Lau 	return -ENOENT;
291*8a138aedSMartin KaFai Lau }
292*8a138aedSMartin KaFai Lau 
293*8a138aedSMartin KaFai Lau void btf__free(struct btf *btf)
294*8a138aedSMartin KaFai Lau {
295*8a138aedSMartin KaFai Lau 	if (!btf)
296*8a138aedSMartin KaFai Lau 		return;
297*8a138aedSMartin KaFai Lau 
298*8a138aedSMartin KaFai Lau 	if (btf->fd != -1)
299*8a138aedSMartin KaFai Lau 		close(btf->fd);
300*8a138aedSMartin KaFai Lau 
301*8a138aedSMartin KaFai Lau 	free(btf->data);
302*8a138aedSMartin KaFai Lau 	free(btf->types);
303*8a138aedSMartin KaFai Lau 	free(btf);
304*8a138aedSMartin KaFai Lau }
305*8a138aedSMartin KaFai Lau 
306*8a138aedSMartin KaFai Lau struct btf *btf__new(uint8_t *data, uint32_t size,
307*8a138aedSMartin KaFai Lau 		     btf_print_fn_t err_log)
308*8a138aedSMartin KaFai Lau {
309*8a138aedSMartin KaFai Lau 	uint32_t log_buf_size = 0;
310*8a138aedSMartin KaFai Lau 	char *log_buf = NULL;
311*8a138aedSMartin KaFai Lau 	struct btf *btf;
312*8a138aedSMartin KaFai Lau 	int err;
313*8a138aedSMartin KaFai Lau 
314*8a138aedSMartin KaFai Lau 	btf = calloc(1, sizeof(struct btf));
315*8a138aedSMartin KaFai Lau 	if (!btf)
316*8a138aedSMartin KaFai Lau 		return ERR_PTR(-ENOMEM);
317*8a138aedSMartin KaFai Lau 
318*8a138aedSMartin KaFai Lau 	btf->fd = -1;
319*8a138aedSMartin KaFai Lau 
320*8a138aedSMartin KaFai Lau 	if (err_log) {
321*8a138aedSMartin KaFai Lau 		log_buf = malloc(BPF_LOG_BUF_SIZE);
322*8a138aedSMartin KaFai Lau 		if (!log_buf) {
323*8a138aedSMartin KaFai Lau 			err = -ENOMEM;
324*8a138aedSMartin KaFai Lau 			goto done;
325*8a138aedSMartin KaFai Lau 		}
326*8a138aedSMartin KaFai Lau 		*log_buf = 0;
327*8a138aedSMartin KaFai Lau 		log_buf_size = BPF_LOG_BUF_SIZE;
328*8a138aedSMartin KaFai Lau 	}
329*8a138aedSMartin KaFai Lau 
330*8a138aedSMartin KaFai Lau 	btf->data = malloc(size);
331*8a138aedSMartin KaFai Lau 	if (!btf->data) {
332*8a138aedSMartin KaFai Lau 		err = -ENOMEM;
333*8a138aedSMartin KaFai Lau 		goto done;
334*8a138aedSMartin KaFai Lau 	}
335*8a138aedSMartin KaFai Lau 
336*8a138aedSMartin KaFai Lau 	memcpy(btf->data, data, size);
337*8a138aedSMartin KaFai Lau 	btf->data_size = size;
338*8a138aedSMartin KaFai Lau 
339*8a138aedSMartin KaFai Lau 	btf->fd = bpf_load_btf(btf->data, btf->data_size,
340*8a138aedSMartin KaFai Lau 			       log_buf, log_buf_size, false);
341*8a138aedSMartin KaFai Lau 
342*8a138aedSMartin KaFai Lau 	if (btf->fd == -1) {
343*8a138aedSMartin KaFai Lau 		err = -errno;
344*8a138aedSMartin KaFai Lau 		elog("Error loading BTF: %s(%d)\n", strerror(errno), errno);
345*8a138aedSMartin KaFai Lau 		if (log_buf && *log_buf)
346*8a138aedSMartin KaFai Lau 			elog("%s\n", log_buf);
347*8a138aedSMartin KaFai Lau 		goto done;
348*8a138aedSMartin KaFai Lau 	}
349*8a138aedSMartin KaFai Lau 
350*8a138aedSMartin KaFai Lau 	err = btf_parse_hdr(btf, err_log);
351*8a138aedSMartin KaFai Lau 	if (err)
352*8a138aedSMartin KaFai Lau 		goto done;
353*8a138aedSMartin KaFai Lau 
354*8a138aedSMartin KaFai Lau 	err = btf_parse_str_sec(btf, err_log);
355*8a138aedSMartin KaFai Lau 	if (err)
356*8a138aedSMartin KaFai Lau 		goto done;
357*8a138aedSMartin KaFai Lau 
358*8a138aedSMartin KaFai Lau 	err = btf_parse_type_sec(btf, err_log);
359*8a138aedSMartin KaFai Lau 
360*8a138aedSMartin KaFai Lau done:
361*8a138aedSMartin KaFai Lau 	free(log_buf);
362*8a138aedSMartin KaFai Lau 
363*8a138aedSMartin KaFai Lau 	if (err) {
364*8a138aedSMartin KaFai Lau 		btf__free(btf);
365*8a138aedSMartin KaFai Lau 		return ERR_PTR(err);
366*8a138aedSMartin KaFai Lau 	}
367*8a138aedSMartin KaFai Lau 
368*8a138aedSMartin KaFai Lau 	return btf;
369*8a138aedSMartin KaFai Lau }
370*8a138aedSMartin KaFai Lau 
371*8a138aedSMartin KaFai Lau int btf__fd(const struct btf *btf)
372*8a138aedSMartin KaFai Lau {
373*8a138aedSMartin KaFai Lau 	return btf->fd;
374*8a138aedSMartin KaFai Lau }
375