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