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