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