xref: /linux/tools/bpf/bpftool/btf.c (revision 527a0f2bdcfe77fce22f006b97e42e4da3137c86)
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 		/* Use name of the first element for anonymous enums if allowed */
565 		if (!from_ref && !t->name_off && btf_vlen(t))
566 			name_off = btf_enum(t)->name_off;
567 
568 		return btf__name_by_offset(btf, name_off);
569 	}
570 	case BTF_KIND_ARRAY:
571 		return btf_type_sort_name(btf, btf_array(t)->type, true);
572 	case BTF_KIND_TYPE_TAG:
573 	case BTF_KIND_CONST:
574 	case BTF_KIND_PTR:
575 	case BTF_KIND_VOLATILE:
576 	case BTF_KIND_RESTRICT:
577 	case BTF_KIND_TYPEDEF:
578 	case BTF_KIND_DECL_TAG:
579 		return btf_type_sort_name(btf, t->type, true);
580 	default:
581 		return btf__name_by_offset(btf, t->name_off);
582 	}
583 	return NULL;
584 }
585 
586 static int btf_type_compare(const void *left, const void *right)
587 {
588 	const struct sort_datum *d1 = (const struct sort_datum *)left;
589 	const struct sort_datum *d2 = (const struct sort_datum *)right;
590 	int r;
591 
592 	if (d1->type_rank != d2->type_rank)
593 		return d1->type_rank < d2->type_rank ? -1 : 1;
594 
595 	r = strcmp(d1->sort_name, d2->sort_name);
596 	if (r)
597 		return r;
598 
599 	return strcmp(d1->own_name, d2->own_name);
600 }
601 
602 static struct sort_datum *sort_btf_c(const struct btf *btf)
603 {
604 	struct sort_datum *datums;
605 	int n;
606 
607 	n = btf__type_cnt(btf);
608 	datums = malloc(sizeof(struct sort_datum) * n);
609 	if (!datums)
610 		return NULL;
611 
612 	for (int i = 0; i < n; ++i) {
613 		struct sort_datum *d = datums + i;
614 		const struct btf_type *t = btf__type_by_id(btf, i);
615 
616 		d->index = i;
617 		d->type_rank = btf_type_rank(btf, i, false);
618 		d->sort_name = btf_type_sort_name(btf, i, false);
619 		d->own_name = btf__name_by_offset(btf, t->name_off);
620 	}
621 
622 	qsort(datums, n, sizeof(struct sort_datum), btf_type_compare);
623 
624 	return datums;
625 }
626 
627 static int dump_btf_c(const struct btf *btf,
628 		      __u32 *root_type_ids, int root_type_cnt, bool sort_dump)
629 {
630 	struct sort_datum *datums = NULL;
631 	struct btf_dump *d;
632 	int err = 0, i;
633 
634 	d = btf_dump__new(btf, btf_dump_printf, NULL, NULL);
635 	if (!d)
636 		return -errno;
637 
638 	printf("#ifndef __VMLINUX_H__\n");
639 	printf("#define __VMLINUX_H__\n");
640 	printf("\n");
641 	printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
642 	printf("#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)\n");
643 	printf("#endif\n\n");
644 	printf("#ifndef __ksym\n");
645 	printf("#define __ksym __attribute__((section(\".ksyms\")))\n");
646 	printf("#endif\n\n");
647 	printf("#ifndef __weak\n");
648 	printf("#define __weak __attribute__((weak))\n");
649 	printf("#endif\n\n");
650 
651 	if (root_type_cnt) {
652 		for (i = 0; i < root_type_cnt; i++) {
653 			err = btf_dump__dump_type(d, root_type_ids[i]);
654 			if (err)
655 				goto done;
656 		}
657 	} else {
658 		int cnt = btf__type_cnt(btf);
659 
660 		if (sort_dump)
661 			datums = sort_btf_c(btf);
662 		for (i = 1; i < cnt; i++) {
663 			int idx = datums ? datums[i].index : i;
664 
665 			err = btf_dump__dump_type(d, idx);
666 			if (err)
667 				goto done;
668 		}
669 
670 		err = dump_btf_kfuncs(d, btf);
671 		if (err)
672 			goto done;
673 	}
674 
675 	printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
676 	printf("#pragma clang attribute pop\n");
677 	printf("#endif\n");
678 	printf("\n");
679 	printf("#endif /* __VMLINUX_H__ */\n");
680 
681 done:
682 	free(datums);
683 	btf_dump__free(d);
684 	return err;
685 }
686 
687 static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux";
688 
689 static struct btf *get_vmlinux_btf_from_sysfs(void)
690 {
691 	struct btf *base;
692 
693 	base = btf__parse(sysfs_vmlinux, NULL);
694 	if (!base)
695 		p_err("failed to parse vmlinux BTF at '%s': %d\n",
696 		      sysfs_vmlinux, -errno);
697 
698 	return base;
699 }
700 
701 #define BTF_NAME_BUFF_LEN 64
702 
703 static bool btf_is_kernel_module(__u32 btf_id)
704 {
705 	struct bpf_btf_info btf_info = {};
706 	char btf_name[BTF_NAME_BUFF_LEN];
707 	int btf_fd;
708 	__u32 len;
709 	int err;
710 
711 	btf_fd = bpf_btf_get_fd_by_id(btf_id);
712 	if (btf_fd < 0) {
713 		p_err("can't get BTF object by id (%u): %s", btf_id, strerror(errno));
714 		return false;
715 	}
716 
717 	len = sizeof(btf_info);
718 	btf_info.name = ptr_to_u64(btf_name);
719 	btf_info.name_len = sizeof(btf_name);
720 	err = bpf_btf_get_info_by_fd(btf_fd, &btf_info, &len);
721 	close(btf_fd);
722 	if (err) {
723 		p_err("can't get BTF (ID %u) object info: %s", btf_id, strerror(errno));
724 		return false;
725 	}
726 
727 	return btf_info.kernel_btf && strncmp(btf_name, "vmlinux", sizeof(btf_name)) != 0;
728 }
729 
730 static int do_dump(int argc, char **argv)
731 {
732 	bool dump_c = false, sort_dump_c = true;
733 	struct btf *btf = NULL, *base = NULL;
734 	__u32 root_type_ids[2];
735 	int root_type_cnt = 0;
736 	__u32 btf_id = -1;
737 	const char *src;
738 	int fd = -1;
739 	int err = 0;
740 
741 	if (!REQ_ARGS(2)) {
742 		usage();
743 		return -1;
744 	}
745 	src = GET_ARG();
746 	if (is_prefix(src, "map")) {
747 		struct bpf_map_info info = {};
748 		__u32 len = sizeof(info);
749 
750 		if (!REQ_ARGS(2)) {
751 			usage();
752 			return -1;
753 		}
754 
755 		fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
756 		if (fd < 0)
757 			return -1;
758 
759 		btf_id = info.btf_id;
760 		if (argc && is_prefix(*argv, "key")) {
761 			root_type_ids[root_type_cnt++] = info.btf_key_type_id;
762 			NEXT_ARG();
763 		} else if (argc && is_prefix(*argv, "value")) {
764 			root_type_ids[root_type_cnt++] = info.btf_value_type_id;
765 			NEXT_ARG();
766 		} else if (argc && is_prefix(*argv, "all")) {
767 			NEXT_ARG();
768 		} else if (argc && is_prefix(*argv, "kv")) {
769 			root_type_ids[root_type_cnt++] = info.btf_key_type_id;
770 			root_type_ids[root_type_cnt++] = info.btf_value_type_id;
771 			NEXT_ARG();
772 		} else {
773 			root_type_ids[root_type_cnt++] = info.btf_key_type_id;
774 			root_type_ids[root_type_cnt++] = info.btf_value_type_id;
775 		}
776 	} else if (is_prefix(src, "prog")) {
777 		struct bpf_prog_info info = {};
778 		__u32 len = sizeof(info);
779 
780 		if (!REQ_ARGS(2)) {
781 			usage();
782 			return -1;
783 		}
784 
785 		fd = prog_parse_fd(&argc, &argv);
786 		if (fd < 0)
787 			return -1;
788 
789 		err = bpf_prog_get_info_by_fd(fd, &info, &len);
790 		if (err) {
791 			p_err("can't get prog info: %s", strerror(errno));
792 			goto done;
793 		}
794 
795 		btf_id = info.btf_id;
796 	} else if (is_prefix(src, "id")) {
797 		char *endptr;
798 
799 		btf_id = strtoul(*argv, &endptr, 0);
800 		if (*endptr) {
801 			p_err("can't parse %s as ID", *argv);
802 			return -1;
803 		}
804 		NEXT_ARG();
805 	} else if (is_prefix(src, "file")) {
806 		const char sysfs_prefix[] = "/sys/kernel/btf/";
807 
808 		if (!base_btf &&
809 		    strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 &&
810 		    strcmp(*argv, sysfs_vmlinux) != 0)
811 			base = get_vmlinux_btf_from_sysfs();
812 
813 		btf = btf__parse_split(*argv, base ?: base_btf);
814 		if (!btf) {
815 			err = -errno;
816 			p_err("failed to load BTF from %s: %s",
817 			      *argv, strerror(errno));
818 			goto done;
819 		}
820 		NEXT_ARG();
821 	} else {
822 		err = -1;
823 		p_err("unrecognized BTF source specifier: '%s'", src);
824 		goto done;
825 	}
826 
827 	while (argc) {
828 		if (is_prefix(*argv, "format")) {
829 			NEXT_ARG();
830 			if (argc < 1) {
831 				p_err("expecting value for 'format' option\n");
832 				err = -EINVAL;
833 				goto done;
834 			}
835 			if (strcmp(*argv, "c") == 0) {
836 				dump_c = true;
837 			} else if (strcmp(*argv, "raw") == 0) {
838 				dump_c = false;
839 			} else {
840 				p_err("unrecognized format specifier: '%s', possible values: raw, c",
841 				      *argv);
842 				err = -EINVAL;
843 				goto done;
844 			}
845 			NEXT_ARG();
846 		} else if (is_prefix(*argv, "unsorted")) {
847 			sort_dump_c = false;
848 			NEXT_ARG();
849 		} else {
850 			p_err("unrecognized option: '%s'", *argv);
851 			err = -EINVAL;
852 			goto done;
853 		}
854 	}
855 
856 	if (!btf) {
857 		if (!base_btf && btf_is_kernel_module(btf_id)) {
858 			p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)",
859 			       sysfs_vmlinux);
860 			base_btf = get_vmlinux_btf_from_sysfs();
861 		}
862 
863 		btf = btf__load_from_kernel_by_id_split(btf_id, base_btf);
864 		if (!btf) {
865 			err = -errno;
866 			p_err("get btf by id (%u): %s", btf_id, strerror(errno));
867 			goto done;
868 		}
869 	}
870 
871 	if (dump_c) {
872 		if (json_output) {
873 			p_err("JSON output for C-syntax dump is not supported");
874 			err = -ENOTSUP;
875 			goto done;
876 		}
877 		err = dump_btf_c(btf, root_type_ids, root_type_cnt, sort_dump_c);
878 	} else {
879 		err = dump_btf_raw(btf, root_type_ids, root_type_cnt);
880 	}
881 
882 done:
883 	close(fd);
884 	btf__free(btf);
885 	btf__free(base);
886 	return err;
887 }
888 
889 static int btf_parse_fd(int *argc, char ***argv)
890 {
891 	unsigned int id;
892 	char *endptr;
893 	int fd;
894 
895 	if (!is_prefix(*argv[0], "id")) {
896 		p_err("expected 'id', got: '%s'?", **argv);
897 		return -1;
898 	}
899 	NEXT_ARGP();
900 
901 	id = strtoul(**argv, &endptr, 0);
902 	if (*endptr) {
903 		p_err("can't parse %s as ID", **argv);
904 		return -1;
905 	}
906 	NEXT_ARGP();
907 
908 	fd = bpf_btf_get_fd_by_id(id);
909 	if (fd < 0)
910 		p_err("can't get BTF object by id (%u): %s",
911 		      id, strerror(errno));
912 
913 	return fd;
914 }
915 
916 static int
917 build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
918 		     void *info, __u32 *len)
919 {
920 	static const char * const names[] = {
921 		[BPF_OBJ_UNKNOWN]	= "unknown",
922 		[BPF_OBJ_PROG]		= "prog",
923 		[BPF_OBJ_MAP]		= "map",
924 	};
925 	__u32 btf_id, id = 0;
926 	int err;
927 	int fd;
928 
929 	while (true) {
930 		switch (type) {
931 		case BPF_OBJ_PROG:
932 			err = bpf_prog_get_next_id(id, &id);
933 			break;
934 		case BPF_OBJ_MAP:
935 			err = bpf_map_get_next_id(id, &id);
936 			break;
937 		default:
938 			err = -1;
939 			p_err("unexpected object type: %d", type);
940 			goto err_free;
941 		}
942 		if (err) {
943 			if (errno == ENOENT) {
944 				err = 0;
945 				break;
946 			}
947 			p_err("can't get next %s: %s%s", names[type],
948 			      strerror(errno),
949 			      errno == EINVAL ? " -- kernel too old?" : "");
950 			goto err_free;
951 		}
952 
953 		switch (type) {
954 		case BPF_OBJ_PROG:
955 			fd = bpf_prog_get_fd_by_id(id);
956 			break;
957 		case BPF_OBJ_MAP:
958 			fd = bpf_map_get_fd_by_id(id);
959 			break;
960 		default:
961 			err = -1;
962 			p_err("unexpected object type: %d", type);
963 			goto err_free;
964 		}
965 		if (fd < 0) {
966 			if (errno == ENOENT)
967 				continue;
968 			p_err("can't get %s by id (%u): %s", names[type], id,
969 			      strerror(errno));
970 			err = -1;
971 			goto err_free;
972 		}
973 
974 		memset(info, 0, *len);
975 		if (type == BPF_OBJ_PROG)
976 			err = bpf_prog_get_info_by_fd(fd, info, len);
977 		else
978 			err = bpf_map_get_info_by_fd(fd, info, len);
979 		close(fd);
980 		if (err) {
981 			p_err("can't get %s info: %s", names[type],
982 			      strerror(errno));
983 			goto err_free;
984 		}
985 
986 		switch (type) {
987 		case BPF_OBJ_PROG:
988 			btf_id = ((struct bpf_prog_info *)info)->btf_id;
989 			break;
990 		case BPF_OBJ_MAP:
991 			btf_id = ((struct bpf_map_info *)info)->btf_id;
992 			break;
993 		default:
994 			err = -1;
995 			p_err("unexpected object type: %d", type);
996 			goto err_free;
997 		}
998 		if (!btf_id)
999 			continue;
1000 
1001 		err = hashmap__append(tab, btf_id, id);
1002 		if (err) {
1003 			p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s",
1004 			      btf_id, id, strerror(-err));
1005 			goto err_free;
1006 		}
1007 	}
1008 
1009 	return 0;
1010 
1011 err_free:
1012 	hashmap__free(tab);
1013 	return err;
1014 }
1015 
1016 static int
1017 build_btf_tables(struct hashmap *btf_prog_table,
1018 		 struct hashmap *btf_map_table)
1019 {
1020 	struct bpf_prog_info prog_info;
1021 	__u32 prog_len = sizeof(prog_info);
1022 	struct bpf_map_info map_info;
1023 	__u32 map_len = sizeof(map_info);
1024 	int err = 0;
1025 
1026 	err = build_btf_type_table(btf_prog_table, BPF_OBJ_PROG, &prog_info,
1027 				   &prog_len);
1028 	if (err)
1029 		return err;
1030 
1031 	err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info,
1032 				   &map_len);
1033 	if (err) {
1034 		hashmap__free(btf_prog_table);
1035 		return err;
1036 	}
1037 
1038 	return 0;
1039 }
1040 
1041 static void
1042 show_btf_plain(struct bpf_btf_info *info, int fd,
1043 	       struct hashmap *btf_prog_table,
1044 	       struct hashmap *btf_map_table)
1045 {
1046 	struct hashmap_entry *entry;
1047 	const char *name = u64_to_ptr(info->name);
1048 	int n;
1049 
1050 	printf("%u: ", info->id);
1051 	if (info->kernel_btf)
1052 		printf("name [%s]  ", name);
1053 	else if (name && name[0])
1054 		printf("name %s  ", name);
1055 	else
1056 		printf("name <anon>  ");
1057 	printf("size %uB", info->btf_size);
1058 
1059 	n = 0;
1060 	hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
1061 		printf("%s%lu", n++ == 0 ? "  prog_ids " : ",", entry->value);
1062 	}
1063 
1064 	n = 0;
1065 	hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
1066 		printf("%s%lu", n++ == 0 ? "  map_ids " : ",", entry->value);
1067 	}
1068 
1069 	emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
1070 
1071 	printf("\n");
1072 }
1073 
1074 static void
1075 show_btf_json(struct bpf_btf_info *info, int fd,
1076 	      struct hashmap *btf_prog_table,
1077 	      struct hashmap *btf_map_table)
1078 {
1079 	struct hashmap_entry *entry;
1080 	const char *name = u64_to_ptr(info->name);
1081 
1082 	jsonw_start_object(json_wtr);	/* btf object */
1083 	jsonw_uint_field(json_wtr, "id", info->id);
1084 	jsonw_uint_field(json_wtr, "size", info->btf_size);
1085 
1086 	jsonw_name(json_wtr, "prog_ids");
1087 	jsonw_start_array(json_wtr);	/* prog_ids */
1088 	hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
1089 		jsonw_uint(json_wtr, entry->value);
1090 	}
1091 	jsonw_end_array(json_wtr);	/* prog_ids */
1092 
1093 	jsonw_name(json_wtr, "map_ids");
1094 	jsonw_start_array(json_wtr);	/* map_ids */
1095 	hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
1096 		jsonw_uint(json_wtr, entry->value);
1097 	}
1098 	jsonw_end_array(json_wtr);	/* map_ids */
1099 
1100 	emit_obj_refs_json(refs_table, info->id, json_wtr); /* pids */
1101 
1102 	jsonw_bool_field(json_wtr, "kernel", info->kernel_btf);
1103 
1104 	if (name && name[0])
1105 		jsonw_string_field(json_wtr, "name", name);
1106 
1107 	jsonw_end_object(json_wtr);	/* btf object */
1108 }
1109 
1110 static int
1111 show_btf(int fd, struct hashmap *btf_prog_table,
1112 	 struct hashmap *btf_map_table)
1113 {
1114 	struct bpf_btf_info info;
1115 	__u32 len = sizeof(info);
1116 	char name[64];
1117 	int err;
1118 
1119 	memset(&info, 0, sizeof(info));
1120 	err = bpf_btf_get_info_by_fd(fd, &info, &len);
1121 	if (err) {
1122 		p_err("can't get BTF object info: %s", strerror(errno));
1123 		return -1;
1124 	}
1125 	/* if kernel support emitting BTF object name, pass name pointer */
1126 	if (info.name_len) {
1127 		memset(&info, 0, sizeof(info));
1128 		info.name_len = sizeof(name);
1129 		info.name = ptr_to_u64(name);
1130 		len = sizeof(info);
1131 
1132 		err = bpf_btf_get_info_by_fd(fd, &info, &len);
1133 		if (err) {
1134 			p_err("can't get BTF object info: %s", strerror(errno));
1135 			return -1;
1136 		}
1137 	}
1138 
1139 	if (json_output)
1140 		show_btf_json(&info, fd, btf_prog_table, btf_map_table);
1141 	else
1142 		show_btf_plain(&info, fd, btf_prog_table, btf_map_table);
1143 
1144 	return 0;
1145 }
1146 
1147 static int do_show(int argc, char **argv)
1148 {
1149 	struct hashmap *btf_prog_table;
1150 	struct hashmap *btf_map_table;
1151 	int err, fd = -1;
1152 	__u32 id = 0;
1153 
1154 	if (argc == 2) {
1155 		fd = btf_parse_fd(&argc, &argv);
1156 		if (fd < 0)
1157 			return -1;
1158 	}
1159 
1160 	if (argc) {
1161 		if (fd >= 0)
1162 			close(fd);
1163 		return BAD_ARG();
1164 	}
1165 
1166 	btf_prog_table = hashmap__new(hash_fn_for_key_as_id,
1167 				      equal_fn_for_key_as_id, NULL);
1168 	btf_map_table = hashmap__new(hash_fn_for_key_as_id,
1169 				     equal_fn_for_key_as_id, NULL);
1170 	if (IS_ERR(btf_prog_table) || IS_ERR(btf_map_table)) {
1171 		hashmap__free(btf_prog_table);
1172 		hashmap__free(btf_map_table);
1173 		if (fd >= 0)
1174 			close(fd);
1175 		p_err("failed to create hashmap for object references");
1176 		return -1;
1177 	}
1178 	err = build_btf_tables(btf_prog_table, btf_map_table);
1179 	if (err) {
1180 		if (fd >= 0)
1181 			close(fd);
1182 		return err;
1183 	}
1184 	build_obj_refs_table(&refs_table, BPF_OBJ_BTF);
1185 
1186 	if (fd >= 0) {
1187 		err = show_btf(fd, btf_prog_table, btf_map_table);
1188 		close(fd);
1189 		goto exit_free;
1190 	}
1191 
1192 	if (json_output)
1193 		jsonw_start_array(json_wtr);	/* root array */
1194 
1195 	while (true) {
1196 		err = bpf_btf_get_next_id(id, &id);
1197 		if (err) {
1198 			if (errno == ENOENT) {
1199 				err = 0;
1200 				break;
1201 			}
1202 			p_err("can't get next BTF object: %s%s",
1203 			      strerror(errno),
1204 			      errno == EINVAL ? " -- kernel too old?" : "");
1205 			err = -1;
1206 			break;
1207 		}
1208 
1209 		fd = bpf_btf_get_fd_by_id(id);
1210 		if (fd < 0) {
1211 			if (errno == ENOENT)
1212 				continue;
1213 			p_err("can't get BTF object by id (%u): %s",
1214 			      id, strerror(errno));
1215 			err = -1;
1216 			break;
1217 		}
1218 
1219 		err = show_btf(fd, btf_prog_table, btf_map_table);
1220 		close(fd);
1221 		if (err)
1222 			break;
1223 	}
1224 
1225 	if (json_output)
1226 		jsonw_end_array(json_wtr);	/* root array */
1227 
1228 exit_free:
1229 	hashmap__free(btf_prog_table);
1230 	hashmap__free(btf_map_table);
1231 	delete_obj_refs_table(refs_table);
1232 
1233 	return err;
1234 }
1235 
1236 static int do_help(int argc, char **argv)
1237 {
1238 	if (json_output) {
1239 		jsonw_null(json_wtr);
1240 		return 0;
1241 	}
1242 
1243 	fprintf(stderr,
1244 		"Usage: %1$s %2$s { show | list } [id BTF_ID]\n"
1245 		"       %1$s %2$s dump BTF_SRC [format FORMAT]\n"
1246 		"       %1$s %2$s help\n"
1247 		"\n"
1248 		"       BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n"
1249 		"       FORMAT  := { raw | c [unsorted] }\n"
1250 		"       " HELP_SPEC_MAP "\n"
1251 		"       " HELP_SPEC_PROGRAM "\n"
1252 		"       " HELP_SPEC_OPTIONS " |\n"
1253 		"                    {-B|--base-btf} }\n"
1254 		"",
1255 		bin_name, "btf");
1256 
1257 	return 0;
1258 }
1259 
1260 static const struct cmd cmds[] = {
1261 	{ "show",	do_show },
1262 	{ "list",	do_show },
1263 	{ "help",	do_help },
1264 	{ "dump",	do_dump },
1265 	{ 0 }
1266 };
1267 
1268 int do_btf(int argc, char **argv)
1269 {
1270 	return cmd_select(cmds, argc, argv, do_help);
1271 }
1272