xref: /linux/tools/bpf/bpftool/btf.c (revision 3fd6c59042dbba50391e30862beac979491145fe)
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2019 Facebook */
3 
4 #ifndef _GNU_SOURCE
5 #define _GNU_SOURCE
6 #endif
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <linux/err.h>
10 #include <stdbool.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <linux/btf.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 
19 #include <bpf/bpf.h>
20 #include <bpf/btf.h>
21 #include <bpf/hashmap.h>
22 #include <bpf/libbpf.h>
23 
24 #include "json_writer.h"
25 #include "main.h"
26 
27 #define KFUNC_DECL_TAG		"bpf_kfunc"
28 #define FASTCALL_DECL_TAG	"bpf_fastcall"
29 
30 static const char * const btf_kind_str[NR_BTF_KINDS] = {
31 	[BTF_KIND_UNKN]		= "UNKNOWN",
32 	[BTF_KIND_INT]		= "INT",
33 	[BTF_KIND_PTR]		= "PTR",
34 	[BTF_KIND_ARRAY]	= "ARRAY",
35 	[BTF_KIND_STRUCT]	= "STRUCT",
36 	[BTF_KIND_UNION]	= "UNION",
37 	[BTF_KIND_ENUM]		= "ENUM",
38 	[BTF_KIND_FWD]		= "FWD",
39 	[BTF_KIND_TYPEDEF]	= "TYPEDEF",
40 	[BTF_KIND_VOLATILE]	= "VOLATILE",
41 	[BTF_KIND_CONST]	= "CONST",
42 	[BTF_KIND_RESTRICT]	= "RESTRICT",
43 	[BTF_KIND_FUNC]		= "FUNC",
44 	[BTF_KIND_FUNC_PROTO]	= "FUNC_PROTO",
45 	[BTF_KIND_VAR]		= "VAR",
46 	[BTF_KIND_DATASEC]	= "DATASEC",
47 	[BTF_KIND_FLOAT]	= "FLOAT",
48 	[BTF_KIND_DECL_TAG]	= "DECL_TAG",
49 	[BTF_KIND_TYPE_TAG]	= "TYPE_TAG",
50 	[BTF_KIND_ENUM64]	= "ENUM64",
51 };
52 
53 struct sort_datum {
54 	int index;
55 	int type_rank;
56 	const char *sort_name;
57 	const char *own_name;
58 	__u64 disambig_hash;
59 };
60 
btf_int_enc_str(__u8 encoding)61 static const char *btf_int_enc_str(__u8 encoding)
62 {
63 	switch (encoding) {
64 	case 0:
65 		return "(none)";
66 	case BTF_INT_SIGNED:
67 		return "SIGNED";
68 	case BTF_INT_CHAR:
69 		return "CHAR";
70 	case BTF_INT_BOOL:
71 		return "BOOL";
72 	default:
73 		return "UNKN";
74 	}
75 }
76 
btf_var_linkage_str(__u32 linkage)77 static const char *btf_var_linkage_str(__u32 linkage)
78 {
79 	switch (linkage) {
80 	case BTF_VAR_STATIC:
81 		return "static";
82 	case BTF_VAR_GLOBAL_ALLOCATED:
83 		return "global";
84 	case BTF_VAR_GLOBAL_EXTERN:
85 		return "extern";
86 	default:
87 		return "(unknown)";
88 	}
89 }
90 
btf_func_linkage_str(const struct btf_type * t)91 static const char *btf_func_linkage_str(const struct btf_type *t)
92 {
93 	switch (btf_vlen(t)) {
94 	case BTF_FUNC_STATIC:
95 		return "static";
96 	case BTF_FUNC_GLOBAL:
97 		return "global";
98 	case BTF_FUNC_EXTERN:
99 		return "extern";
100 	default:
101 		return "(unknown)";
102 	}
103 }
104 
btf_str(const struct btf * btf,__u32 off)105 static const char *btf_str(const struct btf *btf, __u32 off)
106 {
107 	if (!off)
108 		return "(anon)";
109 	return btf__name_by_offset(btf, off) ? : "(invalid)";
110 }
111 
btf_kind_safe(int kind)112 static int btf_kind_safe(int kind)
113 {
114 	return kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN;
115 }
116 
dump_btf_type(const struct btf * btf,__u32 id,const struct btf_type * t)117 static int dump_btf_type(const struct btf *btf, __u32 id,
118 			 const struct btf_type *t)
119 {
120 	json_writer_t *w = json_wtr;
121 	int kind = btf_kind(t);
122 
123 	if (json_output) {
124 		jsonw_start_object(w);
125 		jsonw_uint_field(w, "id", id);
126 		jsonw_string_field(w, "kind", btf_kind_str[btf_kind_safe(kind)]);
127 		jsonw_string_field(w, "name", btf_str(btf, t->name_off));
128 	} else {
129 		printf("[%u] %s '%s'", id, btf_kind_str[btf_kind_safe(kind)],
130 		       btf_str(btf, t->name_off));
131 	}
132 
133 	switch (kind) {
134 	case BTF_KIND_INT: {
135 		__u32 v = *(__u32 *)(t + 1);
136 		const char *enc;
137 
138 		enc = btf_int_enc_str(BTF_INT_ENCODING(v));
139 
140 		if (json_output) {
141 			jsonw_uint_field(w, "size", t->size);
142 			jsonw_uint_field(w, "bits_offset", BTF_INT_OFFSET(v));
143 			jsonw_uint_field(w, "nr_bits", BTF_INT_BITS(v));
144 			jsonw_string_field(w, "encoding", enc);
145 		} else {
146 			printf(" size=%u bits_offset=%u nr_bits=%u encoding=%s",
147 			       t->size, BTF_INT_OFFSET(v), BTF_INT_BITS(v),
148 			       enc);
149 		}
150 		break;
151 	}
152 	case BTF_KIND_PTR:
153 	case BTF_KIND_CONST:
154 	case BTF_KIND_VOLATILE:
155 	case BTF_KIND_RESTRICT:
156 	case BTF_KIND_TYPEDEF:
157 	case BTF_KIND_TYPE_TAG:
158 		if (json_output)
159 			jsonw_uint_field(w, "type_id", t->type);
160 		else
161 			printf(" type_id=%u", t->type);
162 		break;
163 	case BTF_KIND_ARRAY: {
164 		const struct btf_array *arr = (const void *)(t + 1);
165 
166 		if (json_output) {
167 			jsonw_uint_field(w, "type_id", arr->type);
168 			jsonw_uint_field(w, "index_type_id", arr->index_type);
169 			jsonw_uint_field(w, "nr_elems", arr->nelems);
170 		} else {
171 			printf(" type_id=%u index_type_id=%u nr_elems=%u",
172 			       arr->type, arr->index_type, arr->nelems);
173 		}
174 		break;
175 	}
176 	case BTF_KIND_STRUCT:
177 	case BTF_KIND_UNION: {
178 		const struct btf_member *m = (const void *)(t + 1);
179 		__u16 vlen = BTF_INFO_VLEN(t->info);
180 		int i;
181 
182 		if (json_output) {
183 			jsonw_uint_field(w, "size", t->size);
184 			jsonw_uint_field(w, "vlen", vlen);
185 			jsonw_name(w, "members");
186 			jsonw_start_array(w);
187 		} else {
188 			printf(" size=%u vlen=%u", t->size, vlen);
189 		}
190 		for (i = 0; i < vlen; i++, m++) {
191 			const char *name = btf_str(btf, m->name_off);
192 			__u32 bit_off, bit_sz;
193 
194 			if (BTF_INFO_KFLAG(t->info)) {
195 				bit_off = BTF_MEMBER_BIT_OFFSET(m->offset);
196 				bit_sz = BTF_MEMBER_BITFIELD_SIZE(m->offset);
197 			} else {
198 				bit_off = m->offset;
199 				bit_sz = 0;
200 			}
201 
202 			if (json_output) {
203 				jsonw_start_object(w);
204 				jsonw_string_field(w, "name", name);
205 				jsonw_uint_field(w, "type_id", m->type);
206 				jsonw_uint_field(w, "bits_offset", bit_off);
207 				if (bit_sz) {
208 					jsonw_uint_field(w, "bitfield_size",
209 							 bit_sz);
210 				}
211 				jsonw_end_object(w);
212 			} else {
213 				printf("\n\t'%s' type_id=%u bits_offset=%u",
214 				       name, m->type, bit_off);
215 				if (bit_sz)
216 					printf(" bitfield_size=%u", bit_sz);
217 			}
218 		}
219 		if (json_output)
220 			jsonw_end_array(w);
221 		break;
222 	}
223 	case BTF_KIND_ENUM: {
224 		const struct btf_enum *v = (const void *)(t + 1);
225 		__u16 vlen = BTF_INFO_VLEN(t->info);
226 		const char *encoding;
227 		int i;
228 
229 		encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
230 		if (json_output) {
231 			jsonw_string_field(w, "encoding", encoding);
232 			jsonw_uint_field(w, "size", t->size);
233 			jsonw_uint_field(w, "vlen", vlen);
234 			jsonw_name(w, "values");
235 			jsonw_start_array(w);
236 		} else {
237 			printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
238 		}
239 		for (i = 0; i < vlen; i++, v++) {
240 			const char *name = btf_str(btf, v->name_off);
241 
242 			if (json_output) {
243 				jsonw_start_object(w);
244 				jsonw_string_field(w, "name", name);
245 				if (btf_kflag(t))
246 					jsonw_int_field(w, "val", v->val);
247 				else
248 					jsonw_uint_field(w, "val", v->val);
249 				jsonw_end_object(w);
250 			} else {
251 				if (btf_kflag(t))
252 					printf("\n\t'%s' val=%d", name, v->val);
253 				else
254 					printf("\n\t'%s' val=%u", name, v->val);
255 			}
256 		}
257 		if (json_output)
258 			jsonw_end_array(w);
259 		break;
260 	}
261 	case BTF_KIND_ENUM64: {
262 		const struct btf_enum64 *v = btf_enum64(t);
263 		__u16 vlen = btf_vlen(t);
264 		const char *encoding;
265 		int i;
266 
267 		encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
268 		if (json_output) {
269 			jsonw_string_field(w, "encoding", encoding);
270 			jsonw_uint_field(w, "size", t->size);
271 			jsonw_uint_field(w, "vlen", vlen);
272 			jsonw_name(w, "values");
273 			jsonw_start_array(w);
274 		} else {
275 			printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
276 		}
277 		for (i = 0; i < vlen; i++, v++) {
278 			const char *name = btf_str(btf, v->name_off);
279 			__u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32;
280 
281 			if (json_output) {
282 				jsonw_start_object(w);
283 				jsonw_string_field(w, "name", name);
284 				if (btf_kflag(t))
285 					jsonw_int_field(w, "val", val);
286 				else
287 					jsonw_uint_field(w, "val", val);
288 				jsonw_end_object(w);
289 			} else {
290 				if (btf_kflag(t))
291 					printf("\n\t'%s' val=%lldLL", name,
292 					       (long long)val);
293 				else
294 					printf("\n\t'%s' val=%lluULL", name,
295 					       (unsigned long long)val);
296 			}
297 		}
298 		if (json_output)
299 			jsonw_end_array(w);
300 		break;
301 	}
302 	case BTF_KIND_FWD: {
303 		const char *fwd_kind = BTF_INFO_KFLAG(t->info) ? "union"
304 							       : "struct";
305 
306 		if (json_output)
307 			jsonw_string_field(w, "fwd_kind", fwd_kind);
308 		else
309 			printf(" fwd_kind=%s", fwd_kind);
310 		break;
311 	}
312 	case BTF_KIND_FUNC: {
313 		const char *linkage = btf_func_linkage_str(t);
314 
315 		if (json_output) {
316 			jsonw_uint_field(w, "type_id", t->type);
317 			jsonw_string_field(w, "linkage", linkage);
318 		} else {
319 			printf(" type_id=%u linkage=%s", t->type, linkage);
320 		}
321 		break;
322 	}
323 	case BTF_KIND_FUNC_PROTO: {
324 		const struct btf_param *p = (const void *)(t + 1);
325 		__u16 vlen = BTF_INFO_VLEN(t->info);
326 		int i;
327 
328 		if (json_output) {
329 			jsonw_uint_field(w, "ret_type_id", t->type);
330 			jsonw_uint_field(w, "vlen", vlen);
331 			jsonw_name(w, "params");
332 			jsonw_start_array(w);
333 		} else {
334 			printf(" ret_type_id=%u vlen=%u", t->type, vlen);
335 		}
336 		for (i = 0; i < vlen; i++, p++) {
337 			const char *name = btf_str(btf, p->name_off);
338 
339 			if (json_output) {
340 				jsonw_start_object(w);
341 				jsonw_string_field(w, "name", name);
342 				jsonw_uint_field(w, "type_id", p->type);
343 				jsonw_end_object(w);
344 			} else {
345 				printf("\n\t'%s' type_id=%u", name, p->type);
346 			}
347 		}
348 		if (json_output)
349 			jsonw_end_array(w);
350 		break;
351 	}
352 	case BTF_KIND_VAR: {
353 		const struct btf_var *v = (const void *)(t + 1);
354 		const char *linkage;
355 
356 		linkage = btf_var_linkage_str(v->linkage);
357 
358 		if (json_output) {
359 			jsonw_uint_field(w, "type_id", t->type);
360 			jsonw_string_field(w, "linkage", linkage);
361 		} else {
362 			printf(" type_id=%u, linkage=%s", t->type, linkage);
363 		}
364 		break;
365 	}
366 	case BTF_KIND_DATASEC: {
367 		const struct btf_var_secinfo *v = (const void *)(t + 1);
368 		const struct btf_type *vt;
369 		__u16 vlen = BTF_INFO_VLEN(t->info);
370 		int i;
371 
372 		if (json_output) {
373 			jsonw_uint_field(w, "size", t->size);
374 			jsonw_uint_field(w, "vlen", vlen);
375 			jsonw_name(w, "vars");
376 			jsonw_start_array(w);
377 		} else {
378 			printf(" size=%u vlen=%u", t->size, vlen);
379 		}
380 		for (i = 0; i < vlen; i++, v++) {
381 			if (json_output) {
382 				jsonw_start_object(w);
383 				jsonw_uint_field(w, "type_id", v->type);
384 				jsonw_uint_field(w, "offset", v->offset);
385 				jsonw_uint_field(w, "size", v->size);
386 				jsonw_end_object(w);
387 			} else {
388 				printf("\n\ttype_id=%u offset=%u size=%u",
389 				       v->type, v->offset, v->size);
390 
391 				if (v->type < btf__type_cnt(btf)) {
392 					vt = btf__type_by_id(btf, v->type);
393 					printf(" (%s '%s')",
394 					       btf_kind_str[btf_kind_safe(btf_kind(vt))],
395 					       btf_str(btf, vt->name_off));
396 				}
397 			}
398 		}
399 		if (json_output)
400 			jsonw_end_array(w);
401 		break;
402 	}
403 	case BTF_KIND_FLOAT: {
404 		if (json_output)
405 			jsonw_uint_field(w, "size", t->size);
406 		else
407 			printf(" size=%u", t->size);
408 		break;
409 	}
410 	case BTF_KIND_DECL_TAG: {
411 		const struct btf_decl_tag *tag = (const void *)(t + 1);
412 
413 		if (json_output) {
414 			jsonw_uint_field(w, "type_id", t->type);
415 			jsonw_int_field(w, "component_idx", tag->component_idx);
416 		} else {
417 			printf(" type_id=%u component_idx=%d", t->type, tag->component_idx);
418 		}
419 		break;
420 	}
421 	default:
422 		break;
423 	}
424 
425 	if (json_output)
426 		jsonw_end_object(json_wtr);
427 	else
428 		printf("\n");
429 
430 	return 0;
431 }
432 
dump_btf_raw(const struct btf * btf,__u32 * root_type_ids,int root_type_cnt)433 static int dump_btf_raw(const struct btf *btf,
434 			__u32 *root_type_ids, int root_type_cnt)
435 {
436 	const struct btf_type *t;
437 	int i;
438 
439 	if (json_output) {
440 		jsonw_start_object(json_wtr);
441 		jsonw_name(json_wtr, "types");
442 		jsonw_start_array(json_wtr);
443 	}
444 
445 	if (root_type_cnt) {
446 		for (i = 0; i < root_type_cnt; i++) {
447 			t = btf__type_by_id(btf, root_type_ids[i]);
448 			dump_btf_type(btf, root_type_ids[i], t);
449 		}
450 	} else {
451 		const struct btf *base;
452 		int cnt = btf__type_cnt(btf);
453 		int start_id = 1;
454 
455 		base = btf__base_btf(btf);
456 		if (base)
457 			start_id = btf__type_cnt(base);
458 
459 		for (i = start_id; i < cnt; i++) {
460 			t = btf__type_by_id(btf, i);
461 			dump_btf_type(btf, i, t);
462 		}
463 	}
464 
465 	if (json_output) {
466 		jsonw_end_array(json_wtr);
467 		jsonw_end_object(json_wtr);
468 	}
469 	return 0;
470 }
471 
472 struct ptr_array {
473 	__u32 cnt;
474 	__u32 cap;
475 	const void **elems;
476 };
477 
ptr_array_push(const void * ptr,struct ptr_array * arr)478 static int ptr_array_push(const void *ptr, struct ptr_array *arr)
479 {
480 	__u32 new_cap;
481 	void *tmp;
482 
483 	if (arr->cnt == arr->cap) {
484 		new_cap = (arr->cap ?: 16) * 2;
485 		tmp = realloc(arr->elems, sizeof(*arr->elems) * new_cap);
486 		if (!tmp)
487 			return -ENOMEM;
488 		arr->elems = tmp;
489 		arr->cap = new_cap;
490 	}
491 	arr->elems[arr->cnt++] = ptr;
492 	return 0;
493 }
494 
ptr_array_free(struct ptr_array * arr)495 static void ptr_array_free(struct ptr_array *arr)
496 {
497 	free(arr->elems);
498 }
499 
cmp_kfuncs(const void * pa,const void * pb,void * ctx)500 static int cmp_kfuncs(const void *pa, const void *pb, void *ctx)
501 {
502 	struct btf *btf = ctx;
503 	const struct btf_type *a = *(void **)pa;
504 	const struct btf_type *b = *(void **)pb;
505 
506 	return strcmp(btf__str_by_offset(btf, a->name_off),
507 		      btf__str_by_offset(btf, b->name_off));
508 }
509 
dump_btf_kfuncs(struct btf_dump * d,const struct btf * btf)510 static int dump_btf_kfuncs(struct btf_dump *d, const struct btf *btf)
511 {
512 	LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts);
513 	__u32 cnt = btf__type_cnt(btf), i, j;
514 	struct ptr_array fastcalls = {};
515 	struct ptr_array kfuncs = {};
516 	int err = 0;
517 
518 	printf("\n/* BPF kfuncs */\n");
519 	printf("#ifndef BPF_NO_KFUNC_PROTOTYPES\n");
520 
521 	for (i = 1; i < cnt; i++) {
522 		const struct btf_type *t = btf__type_by_id(btf, i);
523 		const struct btf_type *ft;
524 		const char *name;
525 
526 		if (!btf_is_decl_tag(t))
527 			continue;
528 
529 		if (btf_decl_tag(t)->component_idx != -1)
530 			continue;
531 
532 		ft = btf__type_by_id(btf, t->type);
533 		if (!btf_is_func(ft))
534 			continue;
535 
536 		name = btf__name_by_offset(btf, t->name_off);
537 		if (strncmp(name, KFUNC_DECL_TAG, sizeof(KFUNC_DECL_TAG)) == 0) {
538 			err = ptr_array_push(ft, &kfuncs);
539 			if (err)
540 				goto out;
541 		}
542 
543 		if (strncmp(name, FASTCALL_DECL_TAG, sizeof(FASTCALL_DECL_TAG)) == 0) {
544 			err = ptr_array_push(ft, &fastcalls);
545 			if (err)
546 				goto out;
547 		}
548 	}
549 
550 	/* Sort kfuncs by name for improved vmlinux.h stability  */
551 	qsort_r(kfuncs.elems, kfuncs.cnt, sizeof(*kfuncs.elems), cmp_kfuncs, (void *)btf);
552 	for (i = 0; i < kfuncs.cnt; i++) {
553 		const struct btf_type *t = kfuncs.elems[i];
554 
555 		printf("extern ");
556 
557 		/* Assume small amount of fastcall kfuncs */
558 		for (j = 0; j < fastcalls.cnt; j++) {
559 			if (fastcalls.elems[j] == t) {
560 				printf("__bpf_fastcall ");
561 				break;
562 			}
563 		}
564 
565 		opts.field_name = btf__name_by_offset(btf, t->name_off);
566 		err = btf_dump__emit_type_decl(d, t->type, &opts);
567 		if (err)
568 			goto out;
569 
570 		printf(" __weak __ksym;\n");
571 	}
572 
573 	printf("#endif\n\n");
574 
575 out:
576 	ptr_array_free(&fastcalls);
577 	ptr_array_free(&kfuncs);
578 	return err;
579 }
580 
btf_dump_printf(void * ctx,const char * fmt,va_list args)581 static void __printf(2, 0) btf_dump_printf(void *ctx,
582 					   const char *fmt, va_list args)
583 {
584 	vfprintf(stdout, fmt, args);
585 }
586 
btf_type_rank(const struct btf * btf,__u32 index,bool has_name)587 static int btf_type_rank(const struct btf *btf, __u32 index, bool has_name)
588 {
589 	const struct btf_type *t = btf__type_by_id(btf, index);
590 	const int kind = btf_kind(t);
591 	const int max_rank = 10;
592 
593 	if (t->name_off)
594 		has_name = true;
595 
596 	switch (kind) {
597 	case BTF_KIND_ENUM:
598 	case BTF_KIND_ENUM64:
599 		return has_name ? 1 : 0;
600 	case BTF_KIND_INT:
601 	case BTF_KIND_FLOAT:
602 		return 2;
603 	case BTF_KIND_STRUCT:
604 	case BTF_KIND_UNION:
605 		return has_name ? 3 : max_rank;
606 	case BTF_KIND_FUNC_PROTO:
607 		return has_name ? 4 : max_rank;
608 	case BTF_KIND_ARRAY:
609 		if (has_name)
610 			return btf_type_rank(btf, btf_array(t)->type, has_name);
611 		return max_rank;
612 	case BTF_KIND_TYPE_TAG:
613 	case BTF_KIND_CONST:
614 	case BTF_KIND_PTR:
615 	case BTF_KIND_VOLATILE:
616 	case BTF_KIND_RESTRICT:
617 	case BTF_KIND_TYPEDEF:
618 	case BTF_KIND_DECL_TAG:
619 		if (has_name)
620 			return btf_type_rank(btf, t->type, has_name);
621 		return max_rank;
622 	default:
623 		return max_rank;
624 	}
625 }
626 
btf_type_sort_name(const struct btf * btf,__u32 index,bool from_ref)627 static const char *btf_type_sort_name(const struct btf *btf, __u32 index, bool from_ref)
628 {
629 	const struct btf_type *t = btf__type_by_id(btf, index);
630 
631 	switch (btf_kind(t)) {
632 	case BTF_KIND_ENUM:
633 	case BTF_KIND_ENUM64: {
634 		int name_off = t->name_off;
635 
636 		if (!from_ref && !name_off && btf_vlen(t))
637 			name_off = btf_kind(t) == BTF_KIND_ENUM64 ?
638 				btf_enum64(t)->name_off :
639 				btf_enum(t)->name_off;
640 
641 		return btf__name_by_offset(btf, name_off);
642 	}
643 	case BTF_KIND_ARRAY:
644 		return btf_type_sort_name(btf, btf_array(t)->type, true);
645 	case BTF_KIND_TYPE_TAG:
646 	case BTF_KIND_CONST:
647 	case BTF_KIND_PTR:
648 	case BTF_KIND_VOLATILE:
649 	case BTF_KIND_RESTRICT:
650 	case BTF_KIND_TYPEDEF:
651 	case BTF_KIND_DECL_TAG:
652 		return btf_type_sort_name(btf, t->type, true);
653 	default:
654 		return btf__name_by_offset(btf, t->name_off);
655 	}
656 	return NULL;
657 }
658 
hasher(__u64 hash,__u64 val)659 static __u64 hasher(__u64 hash, __u64 val)
660 {
661 	return hash * 31 + val;
662 }
663 
btf_name_hasher(__u64 hash,const struct btf * btf,__u32 name_off)664 static __u64 btf_name_hasher(__u64 hash, const struct btf *btf, __u32 name_off)
665 {
666 	if (!name_off)
667 		return hash;
668 
669 	return hasher(hash, str_hash(btf__name_by_offset(btf, name_off)));
670 }
671 
btf_type_disambig_hash(const struct btf * btf,__u32 id,bool include_members)672 static __u64 btf_type_disambig_hash(const struct btf *btf, __u32 id, bool include_members)
673 {
674 	const struct btf_type *t = btf__type_by_id(btf, id);
675 	int i;
676 	size_t hash = 0;
677 
678 	hash = btf_name_hasher(hash, btf, t->name_off);
679 
680 	switch (btf_kind(t)) {
681 	case BTF_KIND_ENUM:
682 	case BTF_KIND_ENUM64:
683 		for (i = 0; i < btf_vlen(t); i++) {
684 			__u32 name_off = btf_is_enum(t) ?
685 				btf_enum(t)[i].name_off :
686 				btf_enum64(t)[i].name_off;
687 
688 			hash = btf_name_hasher(hash, btf, name_off);
689 		}
690 		break;
691 	case BTF_KIND_STRUCT:
692 	case BTF_KIND_UNION:
693 		if (!include_members)
694 			break;
695 		for (i = 0; i < btf_vlen(t); i++) {
696 			const struct btf_member *m = btf_members(t) + i;
697 
698 			hash = btf_name_hasher(hash, btf, m->name_off);
699 			/* resolve field type's name and hash it as well */
700 			hash = hasher(hash, btf_type_disambig_hash(btf, m->type, false));
701 		}
702 		break;
703 	case BTF_KIND_TYPE_TAG:
704 	case BTF_KIND_CONST:
705 	case BTF_KIND_PTR:
706 	case BTF_KIND_VOLATILE:
707 	case BTF_KIND_RESTRICT:
708 	case BTF_KIND_TYPEDEF:
709 	case BTF_KIND_DECL_TAG:
710 		hash = hasher(hash, btf_type_disambig_hash(btf, t->type, include_members));
711 		break;
712 	case BTF_KIND_ARRAY: {
713 		struct btf_array *arr = btf_array(t);
714 
715 		hash = hasher(hash, arr->nelems);
716 		hash = hasher(hash, btf_type_disambig_hash(btf, arr->type, include_members));
717 		break;
718 	}
719 	default:
720 		break;
721 	}
722 	return hash;
723 }
724 
btf_type_compare(const void * left,const void * right)725 static int btf_type_compare(const void *left, const void *right)
726 {
727 	const struct sort_datum *d1 = (const struct sort_datum *)left;
728 	const struct sort_datum *d2 = (const struct sort_datum *)right;
729 	int r;
730 
731 	r = d1->type_rank - d2->type_rank;
732 	r = r ?: strcmp(d1->sort_name, d2->sort_name);
733 	r = r ?: strcmp(d1->own_name, d2->own_name);
734 	if (r)
735 		return r;
736 
737 	if (d1->disambig_hash != d2->disambig_hash)
738 		return d1->disambig_hash < d2->disambig_hash ? -1 : 1;
739 
740 	return d1->index - d2->index;
741 }
742 
sort_btf_c(const struct btf * btf)743 static struct sort_datum *sort_btf_c(const struct btf *btf)
744 {
745 	struct sort_datum *datums;
746 	int n;
747 
748 	n = btf__type_cnt(btf);
749 	datums = malloc(sizeof(struct sort_datum) * n);
750 	if (!datums)
751 		return NULL;
752 
753 	for (int i = 0; i < n; ++i) {
754 		struct sort_datum *d = datums + i;
755 		const struct btf_type *t = btf__type_by_id(btf, i);
756 
757 		d->index = i;
758 		d->type_rank = btf_type_rank(btf, i, false);
759 		d->sort_name = btf_type_sort_name(btf, i, false);
760 		d->own_name = btf__name_by_offset(btf, t->name_off);
761 		d->disambig_hash = btf_type_disambig_hash(btf, i, true);
762 	}
763 
764 	qsort(datums, n, sizeof(struct sort_datum), btf_type_compare);
765 
766 	return datums;
767 }
768 
dump_btf_c(const struct btf * btf,__u32 * root_type_ids,int root_type_cnt,bool sort_dump)769 static int dump_btf_c(const struct btf *btf,
770 		      __u32 *root_type_ids, int root_type_cnt, bool sort_dump)
771 {
772 	struct sort_datum *datums = NULL;
773 	struct btf_dump *d;
774 	int err = 0, i;
775 
776 	d = btf_dump__new(btf, btf_dump_printf, NULL, NULL);
777 	if (!d)
778 		return -errno;
779 
780 	printf("#ifndef __VMLINUX_H__\n");
781 	printf("#define __VMLINUX_H__\n");
782 	printf("\n");
783 	printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
784 	printf("#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)\n");
785 	printf("#endif\n\n");
786 	printf("#ifndef __ksym\n");
787 	printf("#define __ksym __attribute__((section(\".ksyms\")))\n");
788 	printf("#endif\n\n");
789 	printf("#ifndef __weak\n");
790 	printf("#define __weak __attribute__((weak))\n");
791 	printf("#endif\n\n");
792 	printf("#ifndef __bpf_fastcall\n");
793 	printf("#if __has_attribute(bpf_fastcall)\n");
794 	printf("#define __bpf_fastcall __attribute__((bpf_fastcall))\n");
795 	printf("#else\n");
796 	printf("#define __bpf_fastcall\n");
797 	printf("#endif\n");
798 	printf("#endif\n\n");
799 
800 	if (root_type_cnt) {
801 		for (i = 0; i < root_type_cnt; i++) {
802 			err = btf_dump__dump_type(d, root_type_ids[i]);
803 			if (err)
804 				goto done;
805 		}
806 	} else {
807 		int cnt = btf__type_cnt(btf);
808 
809 		if (sort_dump)
810 			datums = sort_btf_c(btf);
811 		for (i = 1; i < cnt; i++) {
812 			int idx = datums ? datums[i].index : i;
813 
814 			err = btf_dump__dump_type(d, idx);
815 			if (err)
816 				goto done;
817 		}
818 
819 		err = dump_btf_kfuncs(d, btf);
820 		if (err)
821 			goto done;
822 	}
823 
824 	printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
825 	printf("#pragma clang attribute pop\n");
826 	printf("#endif\n");
827 	printf("\n");
828 	printf("#endif /* __VMLINUX_H__ */\n");
829 
830 done:
831 	free(datums);
832 	btf_dump__free(d);
833 	return err;
834 }
835 
836 static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux";
837 
get_vmlinux_btf_from_sysfs(void)838 static struct btf *get_vmlinux_btf_from_sysfs(void)
839 {
840 	struct btf *base;
841 
842 	base = btf__parse(sysfs_vmlinux, NULL);
843 	if (!base)
844 		p_err("failed to parse vmlinux BTF at '%s': %d\n",
845 		      sysfs_vmlinux, -errno);
846 
847 	return base;
848 }
849 
850 #define BTF_NAME_BUFF_LEN 64
851 
btf_is_kernel_module(__u32 btf_id)852 static bool btf_is_kernel_module(__u32 btf_id)
853 {
854 	struct bpf_btf_info btf_info = {};
855 	char btf_name[BTF_NAME_BUFF_LEN];
856 	int btf_fd;
857 	__u32 len;
858 	int err;
859 
860 	btf_fd = bpf_btf_get_fd_by_id(btf_id);
861 	if (btf_fd < 0) {
862 		p_err("can't get BTF object by id (%u): %s", btf_id, strerror(errno));
863 		return false;
864 	}
865 
866 	len = sizeof(btf_info);
867 	btf_info.name = ptr_to_u64(btf_name);
868 	btf_info.name_len = sizeof(btf_name);
869 	err = bpf_btf_get_info_by_fd(btf_fd, &btf_info, &len);
870 	close(btf_fd);
871 	if (err) {
872 		p_err("can't get BTF (ID %u) object info: %s", btf_id, strerror(errno));
873 		return false;
874 	}
875 
876 	return btf_info.kernel_btf && strncmp(btf_name, "vmlinux", sizeof(btf_name)) != 0;
877 }
878 
do_dump(int argc,char ** argv)879 static int do_dump(int argc, char **argv)
880 {
881 	bool dump_c = false, sort_dump_c = true;
882 	struct btf *btf = NULL, *base = NULL;
883 	__u32 root_type_ids[2];
884 	int root_type_cnt = 0;
885 	__u32 btf_id = -1;
886 	const char *src;
887 	int fd = -1;
888 	int err = 0;
889 
890 	if (!REQ_ARGS(2)) {
891 		usage();
892 		return -1;
893 	}
894 	src = GET_ARG();
895 	if (is_prefix(src, "map")) {
896 		struct bpf_map_info info = {};
897 		__u32 len = sizeof(info);
898 
899 		if (!REQ_ARGS(2)) {
900 			usage();
901 			return -1;
902 		}
903 
904 		fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
905 		if (fd < 0)
906 			return -1;
907 
908 		btf_id = info.btf_id;
909 		if (argc && is_prefix(*argv, "key")) {
910 			root_type_ids[root_type_cnt++] = info.btf_key_type_id;
911 			NEXT_ARG();
912 		} else if (argc && is_prefix(*argv, "value")) {
913 			root_type_ids[root_type_cnt++] = info.btf_value_type_id;
914 			NEXT_ARG();
915 		} else if (argc && is_prefix(*argv, "all")) {
916 			NEXT_ARG();
917 		} else if (argc && is_prefix(*argv, "kv")) {
918 			root_type_ids[root_type_cnt++] = info.btf_key_type_id;
919 			root_type_ids[root_type_cnt++] = info.btf_value_type_id;
920 			NEXT_ARG();
921 		} else {
922 			root_type_ids[root_type_cnt++] = info.btf_key_type_id;
923 			root_type_ids[root_type_cnt++] = info.btf_value_type_id;
924 		}
925 	} else if (is_prefix(src, "prog")) {
926 		struct bpf_prog_info info = {};
927 		__u32 len = sizeof(info);
928 
929 		if (!REQ_ARGS(2)) {
930 			usage();
931 			return -1;
932 		}
933 
934 		fd = prog_parse_fd(&argc, &argv);
935 		if (fd < 0)
936 			return -1;
937 
938 		err = bpf_prog_get_info_by_fd(fd, &info, &len);
939 		if (err) {
940 			p_err("can't get prog info: %s", strerror(errno));
941 			goto done;
942 		}
943 
944 		btf_id = info.btf_id;
945 	} else if (is_prefix(src, "id")) {
946 		char *endptr;
947 
948 		btf_id = strtoul(*argv, &endptr, 0);
949 		if (*endptr) {
950 			p_err("can't parse %s as ID", *argv);
951 			return -1;
952 		}
953 		NEXT_ARG();
954 	} else if (is_prefix(src, "file")) {
955 		const char sysfs_prefix[] = "/sys/kernel/btf/";
956 
957 		if (!base_btf &&
958 		    strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 &&
959 		    strcmp(*argv, sysfs_vmlinux) != 0)
960 			base = get_vmlinux_btf_from_sysfs();
961 
962 		btf = btf__parse_split(*argv, base ?: base_btf);
963 		if (!btf) {
964 			err = -errno;
965 			p_err("failed to load BTF from %s: %s",
966 			      *argv, strerror(errno));
967 			goto done;
968 		}
969 		NEXT_ARG();
970 	} else {
971 		err = -1;
972 		p_err("unrecognized BTF source specifier: '%s'", src);
973 		goto done;
974 	}
975 
976 	while (argc) {
977 		if (is_prefix(*argv, "format")) {
978 			NEXT_ARG();
979 			if (argc < 1) {
980 				p_err("expecting value for 'format' option\n");
981 				err = -EINVAL;
982 				goto done;
983 			}
984 			if (strcmp(*argv, "c") == 0) {
985 				dump_c = true;
986 			} else if (strcmp(*argv, "raw") == 0) {
987 				dump_c = false;
988 			} else {
989 				p_err("unrecognized format specifier: '%s', possible values: raw, c",
990 				      *argv);
991 				err = -EINVAL;
992 				goto done;
993 			}
994 			NEXT_ARG();
995 		} else if (is_prefix(*argv, "unsorted")) {
996 			sort_dump_c = false;
997 			NEXT_ARG();
998 		} else {
999 			p_err("unrecognized option: '%s'", *argv);
1000 			err = -EINVAL;
1001 			goto done;
1002 		}
1003 	}
1004 
1005 	if (!btf) {
1006 		if (!base_btf && btf_is_kernel_module(btf_id)) {
1007 			p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)",
1008 			       sysfs_vmlinux);
1009 			base_btf = get_vmlinux_btf_from_sysfs();
1010 		}
1011 
1012 		btf = btf__load_from_kernel_by_id_split(btf_id, base_btf);
1013 		if (!btf) {
1014 			err = -errno;
1015 			p_err("get btf by id (%u): %s", btf_id, strerror(errno));
1016 			goto done;
1017 		}
1018 	}
1019 
1020 	if (dump_c) {
1021 		if (json_output) {
1022 			p_err("JSON output for C-syntax dump is not supported");
1023 			err = -ENOTSUP;
1024 			goto done;
1025 		}
1026 		err = dump_btf_c(btf, root_type_ids, root_type_cnt, sort_dump_c);
1027 	} else {
1028 		err = dump_btf_raw(btf, root_type_ids, root_type_cnt);
1029 	}
1030 
1031 done:
1032 	close(fd);
1033 	btf__free(btf);
1034 	btf__free(base);
1035 	return err;
1036 }
1037 
btf_parse_fd(int * argc,char *** argv)1038 static int btf_parse_fd(int *argc, char ***argv)
1039 {
1040 	unsigned int id;
1041 	char *endptr;
1042 	int fd;
1043 
1044 	if (!is_prefix(*argv[0], "id")) {
1045 		p_err("expected 'id', got: '%s'?", **argv);
1046 		return -1;
1047 	}
1048 	NEXT_ARGP();
1049 
1050 	id = strtoul(**argv, &endptr, 0);
1051 	if (*endptr) {
1052 		p_err("can't parse %s as ID", **argv);
1053 		return -1;
1054 	}
1055 	NEXT_ARGP();
1056 
1057 	fd = bpf_btf_get_fd_by_id(id);
1058 	if (fd < 0)
1059 		p_err("can't get BTF object by id (%u): %s",
1060 		      id, strerror(errno));
1061 
1062 	return fd;
1063 }
1064 
1065 static int
build_btf_type_table(struct hashmap * tab,enum bpf_obj_type type,void * info,__u32 * len)1066 build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
1067 		     void *info, __u32 *len)
1068 {
1069 	static const char * const names[] = {
1070 		[BPF_OBJ_UNKNOWN]	= "unknown",
1071 		[BPF_OBJ_PROG]		= "prog",
1072 		[BPF_OBJ_MAP]		= "map",
1073 	};
1074 	__u32 btf_id, id = 0;
1075 	int err;
1076 	int fd;
1077 
1078 	while (true) {
1079 		switch (type) {
1080 		case BPF_OBJ_PROG:
1081 			err = bpf_prog_get_next_id(id, &id);
1082 			break;
1083 		case BPF_OBJ_MAP:
1084 			err = bpf_map_get_next_id(id, &id);
1085 			break;
1086 		default:
1087 			err = -1;
1088 			p_err("unexpected object type: %d", type);
1089 			goto err_free;
1090 		}
1091 		if (err) {
1092 			if (errno == ENOENT) {
1093 				err = 0;
1094 				break;
1095 			}
1096 			p_err("can't get next %s: %s%s", names[type],
1097 			      strerror(errno),
1098 			      errno == EINVAL ? " -- kernel too old?" : "");
1099 			goto err_free;
1100 		}
1101 
1102 		switch (type) {
1103 		case BPF_OBJ_PROG:
1104 			fd = bpf_prog_get_fd_by_id(id);
1105 			break;
1106 		case BPF_OBJ_MAP:
1107 			fd = bpf_map_get_fd_by_id(id);
1108 			break;
1109 		default:
1110 			err = -1;
1111 			p_err("unexpected object type: %d", type);
1112 			goto err_free;
1113 		}
1114 		if (fd < 0) {
1115 			if (errno == ENOENT)
1116 				continue;
1117 			p_err("can't get %s by id (%u): %s", names[type], id,
1118 			      strerror(errno));
1119 			err = -1;
1120 			goto err_free;
1121 		}
1122 
1123 		memset(info, 0, *len);
1124 		if (type == BPF_OBJ_PROG)
1125 			err = bpf_prog_get_info_by_fd(fd, info, len);
1126 		else
1127 			err = bpf_map_get_info_by_fd(fd, info, len);
1128 		close(fd);
1129 		if (err) {
1130 			p_err("can't get %s info: %s", names[type],
1131 			      strerror(errno));
1132 			goto err_free;
1133 		}
1134 
1135 		switch (type) {
1136 		case BPF_OBJ_PROG:
1137 			btf_id = ((struct bpf_prog_info *)info)->btf_id;
1138 			break;
1139 		case BPF_OBJ_MAP:
1140 			btf_id = ((struct bpf_map_info *)info)->btf_id;
1141 			break;
1142 		default:
1143 			err = -1;
1144 			p_err("unexpected object type: %d", type);
1145 			goto err_free;
1146 		}
1147 		if (!btf_id)
1148 			continue;
1149 
1150 		err = hashmap__append(tab, btf_id, id);
1151 		if (err) {
1152 			p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s",
1153 			      btf_id, id, strerror(-err));
1154 			goto err_free;
1155 		}
1156 	}
1157 
1158 	return 0;
1159 
1160 err_free:
1161 	hashmap__free(tab);
1162 	return err;
1163 }
1164 
1165 static int
build_btf_tables(struct hashmap * btf_prog_table,struct hashmap * btf_map_table)1166 build_btf_tables(struct hashmap *btf_prog_table,
1167 		 struct hashmap *btf_map_table)
1168 {
1169 	struct bpf_prog_info prog_info;
1170 	__u32 prog_len = sizeof(prog_info);
1171 	struct bpf_map_info map_info;
1172 	__u32 map_len = sizeof(map_info);
1173 	int err = 0;
1174 
1175 	err = build_btf_type_table(btf_prog_table, BPF_OBJ_PROG, &prog_info,
1176 				   &prog_len);
1177 	if (err)
1178 		return err;
1179 
1180 	err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info,
1181 				   &map_len);
1182 	if (err) {
1183 		hashmap__free(btf_prog_table);
1184 		return err;
1185 	}
1186 
1187 	return 0;
1188 }
1189 
1190 static void
show_btf_plain(struct bpf_btf_info * info,int fd,struct hashmap * btf_prog_table,struct hashmap * btf_map_table)1191 show_btf_plain(struct bpf_btf_info *info, int fd,
1192 	       struct hashmap *btf_prog_table,
1193 	       struct hashmap *btf_map_table)
1194 {
1195 	struct hashmap_entry *entry;
1196 	const char *name = u64_to_ptr(info->name);
1197 	int n;
1198 
1199 	printf("%u: ", info->id);
1200 	if (info->kernel_btf)
1201 		printf("name [%s]  ", name);
1202 	else if (name && name[0])
1203 		printf("name %s  ", name);
1204 	else
1205 		printf("name <anon>  ");
1206 	printf("size %uB", info->btf_size);
1207 
1208 	n = 0;
1209 	hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
1210 		printf("%s%lu", n++ == 0 ? "  prog_ids " : ",", entry->value);
1211 	}
1212 
1213 	n = 0;
1214 	hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
1215 		printf("%s%lu", n++ == 0 ? "  map_ids " : ",", entry->value);
1216 	}
1217 
1218 	emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
1219 
1220 	printf("\n");
1221 }
1222 
1223 static void
show_btf_json(struct bpf_btf_info * info,int fd,struct hashmap * btf_prog_table,struct hashmap * btf_map_table)1224 show_btf_json(struct bpf_btf_info *info, int fd,
1225 	      struct hashmap *btf_prog_table,
1226 	      struct hashmap *btf_map_table)
1227 {
1228 	struct hashmap_entry *entry;
1229 	const char *name = u64_to_ptr(info->name);
1230 
1231 	jsonw_start_object(json_wtr);	/* btf object */
1232 	jsonw_uint_field(json_wtr, "id", info->id);
1233 	jsonw_uint_field(json_wtr, "size", info->btf_size);
1234 
1235 	jsonw_name(json_wtr, "prog_ids");
1236 	jsonw_start_array(json_wtr);	/* prog_ids */
1237 	hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
1238 		jsonw_uint(json_wtr, entry->value);
1239 	}
1240 	jsonw_end_array(json_wtr);	/* prog_ids */
1241 
1242 	jsonw_name(json_wtr, "map_ids");
1243 	jsonw_start_array(json_wtr);	/* map_ids */
1244 	hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
1245 		jsonw_uint(json_wtr, entry->value);
1246 	}
1247 	jsonw_end_array(json_wtr);	/* map_ids */
1248 
1249 	emit_obj_refs_json(refs_table, info->id, json_wtr); /* pids */
1250 
1251 	jsonw_bool_field(json_wtr, "kernel", info->kernel_btf);
1252 
1253 	if (name && name[0])
1254 		jsonw_string_field(json_wtr, "name", name);
1255 
1256 	jsonw_end_object(json_wtr);	/* btf object */
1257 }
1258 
1259 static int
show_btf(int fd,struct hashmap * btf_prog_table,struct hashmap * btf_map_table)1260 show_btf(int fd, struct hashmap *btf_prog_table,
1261 	 struct hashmap *btf_map_table)
1262 {
1263 	struct bpf_btf_info info;
1264 	__u32 len = sizeof(info);
1265 	char name[64];
1266 	int err;
1267 
1268 	memset(&info, 0, sizeof(info));
1269 	err = bpf_btf_get_info_by_fd(fd, &info, &len);
1270 	if (err) {
1271 		p_err("can't get BTF object info: %s", strerror(errno));
1272 		return -1;
1273 	}
1274 	/* if kernel support emitting BTF object name, pass name pointer */
1275 	if (info.name_len) {
1276 		memset(&info, 0, sizeof(info));
1277 		info.name_len = sizeof(name);
1278 		info.name = ptr_to_u64(name);
1279 		len = sizeof(info);
1280 
1281 		err = bpf_btf_get_info_by_fd(fd, &info, &len);
1282 		if (err) {
1283 			p_err("can't get BTF object info: %s", strerror(errno));
1284 			return -1;
1285 		}
1286 	}
1287 
1288 	if (json_output)
1289 		show_btf_json(&info, fd, btf_prog_table, btf_map_table);
1290 	else
1291 		show_btf_plain(&info, fd, btf_prog_table, btf_map_table);
1292 
1293 	return 0;
1294 }
1295 
do_show(int argc,char ** argv)1296 static int do_show(int argc, char **argv)
1297 {
1298 	struct hashmap *btf_prog_table;
1299 	struct hashmap *btf_map_table;
1300 	int err, fd = -1;
1301 	__u32 id = 0;
1302 
1303 	if (argc == 2) {
1304 		fd = btf_parse_fd(&argc, &argv);
1305 		if (fd < 0)
1306 			return -1;
1307 	}
1308 
1309 	if (argc) {
1310 		if (fd >= 0)
1311 			close(fd);
1312 		return BAD_ARG();
1313 	}
1314 
1315 	btf_prog_table = hashmap__new(hash_fn_for_key_as_id,
1316 				      equal_fn_for_key_as_id, NULL);
1317 	btf_map_table = hashmap__new(hash_fn_for_key_as_id,
1318 				     equal_fn_for_key_as_id, NULL);
1319 	if (IS_ERR(btf_prog_table) || IS_ERR(btf_map_table)) {
1320 		hashmap__free(btf_prog_table);
1321 		hashmap__free(btf_map_table);
1322 		if (fd >= 0)
1323 			close(fd);
1324 		p_err("failed to create hashmap for object references");
1325 		return -1;
1326 	}
1327 	err = build_btf_tables(btf_prog_table, btf_map_table);
1328 	if (err) {
1329 		if (fd >= 0)
1330 			close(fd);
1331 		return err;
1332 	}
1333 	build_obj_refs_table(&refs_table, BPF_OBJ_BTF);
1334 
1335 	if (fd >= 0) {
1336 		err = show_btf(fd, btf_prog_table, btf_map_table);
1337 		close(fd);
1338 		goto exit_free;
1339 	}
1340 
1341 	if (json_output)
1342 		jsonw_start_array(json_wtr);	/* root array */
1343 
1344 	while (true) {
1345 		err = bpf_btf_get_next_id(id, &id);
1346 		if (err) {
1347 			if (errno == ENOENT) {
1348 				err = 0;
1349 				break;
1350 			}
1351 			p_err("can't get next BTF object: %s%s",
1352 			      strerror(errno),
1353 			      errno == EINVAL ? " -- kernel too old?" : "");
1354 			err = -1;
1355 			break;
1356 		}
1357 
1358 		fd = bpf_btf_get_fd_by_id(id);
1359 		if (fd < 0) {
1360 			if (errno == ENOENT)
1361 				continue;
1362 			p_err("can't get BTF object by id (%u): %s",
1363 			      id, strerror(errno));
1364 			err = -1;
1365 			break;
1366 		}
1367 
1368 		err = show_btf(fd, btf_prog_table, btf_map_table);
1369 		close(fd);
1370 		if (err)
1371 			break;
1372 	}
1373 
1374 	if (json_output)
1375 		jsonw_end_array(json_wtr);	/* root array */
1376 
1377 exit_free:
1378 	hashmap__free(btf_prog_table);
1379 	hashmap__free(btf_map_table);
1380 	delete_obj_refs_table(refs_table);
1381 
1382 	return err;
1383 }
1384 
do_help(int argc,char ** argv)1385 static int do_help(int argc, char **argv)
1386 {
1387 	if (json_output) {
1388 		jsonw_null(json_wtr);
1389 		return 0;
1390 	}
1391 
1392 	fprintf(stderr,
1393 		"Usage: %1$s %2$s { show | list } [id BTF_ID]\n"
1394 		"       %1$s %2$s dump BTF_SRC [format FORMAT]\n"
1395 		"       %1$s %2$s help\n"
1396 		"\n"
1397 		"       BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n"
1398 		"       FORMAT  := { raw | c [unsorted] }\n"
1399 		"       " HELP_SPEC_MAP "\n"
1400 		"       " HELP_SPEC_PROGRAM "\n"
1401 		"       " HELP_SPEC_OPTIONS " |\n"
1402 		"                    {-B|--base-btf} }\n"
1403 		"",
1404 		bin_name, "btf");
1405 
1406 	return 0;
1407 }
1408 
1409 static const struct cmd cmds[] = {
1410 	{ "show",	do_show },
1411 	{ "list",	do_show },
1412 	{ "help",	do_help },
1413 	{ "dump",	do_dump },
1414 	{ 0 }
1415 };
1416 
do_btf(int argc,char ** argv)1417 int do_btf(int argc, char **argv)
1418 {
1419 	return cmd_select(cmds, argc, argv, do_help);
1420 }
1421