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