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