1
2
3
4
5
6
7
8
9#include <stdbool.h>
10#include <stddef.h>
11#include <stdlib.h>
12#include <string.h>
13#include <errno.h>
14#include <linux/err.h>
15#include <linux/btf.h>
16#include <linux/kernel.h>
17#include "btf.h"
18#include "hashmap.h"
19#include "libbpf.h"
20#include "libbpf_internal.h"
21
22static const char PREFIXES[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t";
23static const size_t PREFIX_CNT = sizeof(PREFIXES) - 1;
24
25static const char *pfx(int lvl)
26{
27 return lvl >= PREFIX_CNT ? PREFIXES : &PREFIXES[PREFIX_CNT - lvl];
28}
29
30enum btf_dump_type_order_state {
31 NOT_ORDERED,
32 ORDERING,
33 ORDERED,
34};
35
36enum btf_dump_type_emit_state {
37 NOT_EMITTED,
38 EMITTING,
39 EMITTED,
40};
41
42
43struct btf_dump_type_aux_state {
44
45 enum btf_dump_type_order_state order_state: 2;
46
47 enum btf_dump_type_emit_state emit_state: 2;
48
49 __u8 fwd_emitted: 1;
50
51 __u8 name_resolved: 1;
52
53 __u8 referenced: 1;
54};
55
56struct btf_dump {
57 const struct btf *btf;
58 const struct btf_ext *btf_ext;
59 btf_dump_printf_fn_t printf_fn;
60 struct btf_dump_opts opts;
61 int ptr_sz;
62 bool strip_mods;
63 int last_id;
64
65
66 struct btf_dump_type_aux_state *type_states;
67 size_t type_states_cap;
68
69 const char **cached_names;
70 size_t cached_names_cap;
71
72
73 __u32 *emit_queue;
74 int emit_queue_cap;
75 int emit_queue_cnt;
76
77
78
79
80
81 __u32 *decl_stack;
82 int decl_stack_cap;
83 int decl_stack_cnt;
84
85
86 struct hashmap *type_names;
87
88
89
90
91 struct hashmap *ident_names;
92};
93
94static size_t str_hash_fn(const void *key, void *ctx)
95{
96 return str_hash(key);
97}
98
99static bool str_equal_fn(const void *a, const void *b, void *ctx)
100{
101 return strcmp(a, b) == 0;
102}
103
104static const char *btf_name_of(const struct btf_dump *d, __u32 name_off)
105{
106 return btf__name_by_offset(d->btf, name_off);
107}
108
109static void btf_dump_printf(const struct btf_dump *d, const char *fmt, ...)
110{
111 va_list args;
112
113 va_start(args, fmt);
114 d->printf_fn(d->opts.ctx, fmt, args);
115 va_end(args);
116}
117
118static int btf_dump_mark_referenced(struct btf_dump *d);
119static int btf_dump_resize(struct btf_dump *d);
120
121struct btf_dump *btf_dump__new(const struct btf *btf,
122 const struct btf_ext *btf_ext,
123 const struct btf_dump_opts *opts,
124 btf_dump_printf_fn_t printf_fn)
125{
126 struct btf_dump *d;
127 int err;
128
129 d = calloc(1, sizeof(struct btf_dump));
130 if (!d)
131 return libbpf_err_ptr(-ENOMEM);
132
133 d->btf = btf;
134 d->btf_ext = btf_ext;
135 d->printf_fn = printf_fn;
136 d->opts.ctx = opts ? opts->ctx : NULL;
137 d->ptr_sz = btf__pointer_size(btf) ? : sizeof(void *);
138
139 d->type_names = hashmap__new(str_hash_fn, str_equal_fn, NULL);
140 if (IS_ERR(d->type_names)) {
141 err = PTR_ERR(d->type_names);
142 d->type_names = NULL;
143 goto err;
144 }
145 d->ident_names = hashmap__new(str_hash_fn, str_equal_fn, NULL);
146 if (IS_ERR(d->ident_names)) {
147 err = PTR_ERR(d->ident_names);
148 d->ident_names = NULL;
149 goto err;
150 }
151
152 err = btf_dump_resize(d);
153 if (err)
154 goto err;
155
156 return d;
157err:
158 btf_dump__free(d);
159 return libbpf_err_ptr(err);
160}
161
162static int btf_dump_resize(struct btf_dump *d)
163{
164 int err, last_id = btf__get_nr_types(d->btf);
165
166 if (last_id <= d->last_id)
167 return 0;
168
169 if (libbpf_ensure_mem((void **)&d->type_states, &d->type_states_cap,
170 sizeof(*d->type_states), last_id + 1))
171 return -ENOMEM;
172 if (libbpf_ensure_mem((void **)&d->cached_names, &d->cached_names_cap,
173 sizeof(*d->cached_names), last_id + 1))
174 return -ENOMEM;
175
176 if (d->last_id == 0) {
177
178 d->type_states[0].order_state = ORDERED;
179 d->type_states[0].emit_state = EMITTED;
180 }
181
182
183 err = btf_dump_mark_referenced(d);
184 if (err)
185 return err;
186
187 d->last_id = last_id;
188 return 0;
189}
190
191void btf_dump__free(struct btf_dump *d)
192{
193 int i;
194
195 if (IS_ERR_OR_NULL(d))
196 return;
197
198 free(d->type_states);
199 if (d->cached_names) {
200
201 for (i = 0; i <= d->last_id; i++) {
202 if (d->cached_names[i])
203 free((void *)d->cached_names[i]);
204 }
205 }
206 free(d->cached_names);
207 free(d->emit_queue);
208 free(d->decl_stack);
209 hashmap__free(d->type_names);
210 hashmap__free(d->ident_names);
211
212 free(d);
213}
214
215static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr);
216static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id);
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234int btf_dump__dump_type(struct btf_dump *d, __u32 id)
235{
236 int err, i;
237
238 if (id > btf__get_nr_types(d->btf))
239 return libbpf_err(-EINVAL);
240
241 err = btf_dump_resize(d);
242 if (err)
243 return libbpf_err(err);
244
245 d->emit_queue_cnt = 0;
246 err = btf_dump_order_type(d, id, false);
247 if (err < 0)
248 return libbpf_err(err);
249
250 for (i = 0; i < d->emit_queue_cnt; i++)
251 btf_dump_emit_type(d, d->emit_queue[i], 0 );
252
253 return 0;
254}
255
256
257
258
259
260
261
262
263
264
265
266
267
268static int btf_dump_mark_referenced(struct btf_dump *d)
269{
270 int i, j, n = btf__get_nr_types(d->btf);
271 const struct btf_type *t;
272 __u16 vlen;
273
274 for (i = d->last_id + 1; i <= n; i++) {
275 t = btf__type_by_id(d->btf, i);
276 vlen = btf_vlen(t);
277
278 switch (btf_kind(t)) {
279 case BTF_KIND_INT:
280 case BTF_KIND_ENUM:
281 case BTF_KIND_FWD:
282 case BTF_KIND_FLOAT:
283 break;
284
285 case BTF_KIND_VOLATILE:
286 case BTF_KIND_CONST:
287 case BTF_KIND_RESTRICT:
288 case BTF_KIND_PTR:
289 case BTF_KIND_TYPEDEF:
290 case BTF_KIND_FUNC:
291 case BTF_KIND_VAR:
292 d->type_states[t->type].referenced = 1;
293 break;
294
295 case BTF_KIND_ARRAY: {
296 const struct btf_array *a = btf_array(t);
297
298 d->type_states[a->index_type].referenced = 1;
299 d->type_states[a->type].referenced = 1;
300 break;
301 }
302 case BTF_KIND_STRUCT:
303 case BTF_KIND_UNION: {
304 const struct btf_member *m = btf_members(t);
305
306 for (j = 0; j < vlen; j++, m++)
307 d->type_states[m->type].referenced = 1;
308 break;
309 }
310 case BTF_KIND_FUNC_PROTO: {
311 const struct btf_param *p = btf_params(t);
312
313 for (j = 0; j < vlen; j++, p++)
314 d->type_states[p->type].referenced = 1;
315 break;
316 }
317 case BTF_KIND_DATASEC: {
318 const struct btf_var_secinfo *v = btf_var_secinfos(t);
319
320 for (j = 0; j < vlen; j++, v++)
321 d->type_states[v->type].referenced = 1;
322 break;
323 }
324 default:
325 return -EINVAL;
326 }
327 }
328 return 0;
329}
330
331static int btf_dump_add_emit_queue_id(struct btf_dump *d, __u32 id)
332{
333 __u32 *new_queue;
334 size_t new_cap;
335
336 if (d->emit_queue_cnt >= d->emit_queue_cap) {
337 new_cap = max(16, d->emit_queue_cap * 3 / 2);
338 new_queue = libbpf_reallocarray(d->emit_queue, new_cap, sizeof(new_queue[0]));
339 if (!new_queue)
340 return -ENOMEM;
341 d->emit_queue = new_queue;
342 d->emit_queue_cap = new_cap;
343 }
344
345 d->emit_queue[d->emit_queue_cnt++] = id;
346 return 0;
347}
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr)
424{
425
426
427
428
429
430
431
432
433
434
435
436 struct btf_dump_type_aux_state *tstate = &d->type_states[id];
437 const struct btf_type *t;
438 __u16 vlen;
439 int err, i;
440
441
442 if (tstate->order_state == ORDERED)
443 return 1;
444
445 t = btf__type_by_id(d->btf, id);
446
447 if (tstate->order_state == ORDERING) {
448
449 if (btf_is_composite(t) && through_ptr && t->name_off != 0)
450 return 0;
451 pr_warn("unsatisfiable type cycle, id:[%u]\n", id);
452 return -ELOOP;
453 }
454
455 switch (btf_kind(t)) {
456 case BTF_KIND_INT:
457 case BTF_KIND_FLOAT:
458 tstate->order_state = ORDERED;
459 return 0;
460
461 case BTF_KIND_PTR:
462 err = btf_dump_order_type(d, t->type, true);
463 tstate->order_state = ORDERED;
464 return err;
465
466 case BTF_KIND_ARRAY:
467 return btf_dump_order_type(d, btf_array(t)->type, false);
468
469 case BTF_KIND_STRUCT:
470 case BTF_KIND_UNION: {
471 const struct btf_member *m = btf_members(t);
472
473
474
475
476
477 if (through_ptr && t->name_off != 0)
478 return 0;
479
480 tstate->order_state = ORDERING;
481
482 vlen = btf_vlen(t);
483 for (i = 0; i < vlen; i++, m++) {
484 err = btf_dump_order_type(d, m->type, false);
485 if (err < 0)
486 return err;
487 }
488
489 if (t->name_off != 0) {
490 err = btf_dump_add_emit_queue_id(d, id);
491 if (err < 0)
492 return err;
493 }
494
495 tstate->order_state = ORDERED;
496 return 1;
497 }
498 case BTF_KIND_ENUM:
499 case BTF_KIND_FWD:
500
501
502
503
504
505 if (t->name_off != 0 || !tstate->referenced) {
506 err = btf_dump_add_emit_queue_id(d, id);
507 if (err)
508 return err;
509 }
510 tstate->order_state = ORDERED;
511 return 1;
512
513 case BTF_KIND_TYPEDEF: {
514 int is_strong;
515
516 is_strong = btf_dump_order_type(d, t->type, through_ptr);
517 if (is_strong < 0)
518 return is_strong;
519
520
521 if (through_ptr && !is_strong)
522 return 0;
523
524
525 err = btf_dump_add_emit_queue_id(d, id);
526 if (err)
527 return err;
528
529 d->type_states[id].order_state = ORDERED;
530 return 1;
531 }
532 case BTF_KIND_VOLATILE:
533 case BTF_KIND_CONST:
534 case BTF_KIND_RESTRICT:
535 return btf_dump_order_type(d, t->type, through_ptr);
536
537 case BTF_KIND_FUNC_PROTO: {
538 const struct btf_param *p = btf_params(t);
539 bool is_strong;
540
541 err = btf_dump_order_type(d, t->type, through_ptr);
542 if (err < 0)
543 return err;
544 is_strong = err > 0;
545
546 vlen = btf_vlen(t);
547 for (i = 0; i < vlen; i++, p++) {
548 err = btf_dump_order_type(d, p->type, through_ptr);
549 if (err < 0)
550 return err;
551 if (err > 0)
552 is_strong = true;
553 }
554 return is_strong;
555 }
556 case BTF_KIND_FUNC:
557 case BTF_KIND_VAR:
558 case BTF_KIND_DATASEC:
559 d->type_states[id].order_state = ORDERED;
560 return 0;
561
562 default:
563 return -EINVAL;
564 }
565}
566
567static void btf_dump_emit_missing_aliases(struct btf_dump *d, __u32 id,
568 const struct btf_type *t);
569
570static void btf_dump_emit_struct_fwd(struct btf_dump *d, __u32 id,
571 const struct btf_type *t);
572static void btf_dump_emit_struct_def(struct btf_dump *d, __u32 id,
573 const struct btf_type *t, int lvl);
574
575static void btf_dump_emit_enum_fwd(struct btf_dump *d, __u32 id,
576 const struct btf_type *t);
577static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
578 const struct btf_type *t, int lvl);
579
580static void btf_dump_emit_fwd_def(struct btf_dump *d, __u32 id,
581 const struct btf_type *t);
582
583static void btf_dump_emit_typedef_def(struct btf_dump *d, __u32 id,
584 const struct btf_type *t, int lvl);
585
586
587struct id_stack {
588 const __u32 *ids;
589 int cnt;
590};
591
592static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id,
593 const char *fname, int lvl);
594static void btf_dump_emit_type_chain(struct btf_dump *d,
595 struct id_stack *decl_stack,
596 const char *fname, int lvl);
597
598static const char *btf_dump_type_name(struct btf_dump *d, __u32 id);
599static const char *btf_dump_ident_name(struct btf_dump *d, __u32 id);
600static size_t btf_dump_name_dups(struct btf_dump *d, struct hashmap *name_map,
601 const char *orig_name);
602
603static bool btf_dump_is_blacklisted(struct btf_dump *d, __u32 id)
604{
605 const struct btf_type *t = btf__type_by_id(d->btf, id);
606
607
608
609
610
611
612
613 if (t->name_off == 0)
614 return false;
615 return strcmp(btf_name_of(d, t->name_off), "__builtin_va_list") == 0;
616}
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id)
637{
638 struct btf_dump_type_aux_state *tstate = &d->type_states[id];
639 bool top_level_def = cont_id == 0;
640 const struct btf_type *t;
641 __u16 kind;
642
643 if (tstate->emit_state == EMITTED)
644 return;
645
646 t = btf__type_by_id(d->btf, id);
647 kind = btf_kind(t);
648
649 if (tstate->emit_state == EMITTING) {
650 if (tstate->fwd_emitted)
651 return;
652
653 switch (kind) {
654 case BTF_KIND_STRUCT:
655 case BTF_KIND_UNION:
656
657
658
659
660 if (id == cont_id)
661 return;
662 if (t->name_off == 0) {
663 pr_warn("anonymous struct/union loop, id:[%u]\n",
664 id);
665 return;
666 }
667 btf_dump_emit_struct_fwd(d, id, t);
668 btf_dump_printf(d, ";\n\n");
669 tstate->fwd_emitted = 1;
670 break;
671 case BTF_KIND_TYPEDEF:
672
673
674
675
676
677 if (!btf_dump_is_blacklisted(d, id)) {
678 btf_dump_emit_typedef_def(d, id, t, 0);
679 btf_dump_printf(d, ";\n\n");
680 }
681 tstate->fwd_emitted = 1;
682 break;
683 default:
684 break;
685 }
686
687 return;
688 }
689
690 switch (kind) {
691 case BTF_KIND_INT:
692
693 btf_dump_emit_missing_aliases(d, id, t);
694
695 tstate->emit_state = EMITTED;
696 break;
697 case BTF_KIND_ENUM:
698 if (top_level_def) {
699 btf_dump_emit_enum_def(d, id, t, 0);
700 btf_dump_printf(d, ";\n\n");
701 }
702 tstate->emit_state = EMITTED;
703 break;
704 case BTF_KIND_PTR:
705 case BTF_KIND_VOLATILE:
706 case BTF_KIND_CONST:
707 case BTF_KIND_RESTRICT:
708 btf_dump_emit_type(d, t->type, cont_id);
709 break;
710 case BTF_KIND_ARRAY:
711 btf_dump_emit_type(d, btf_array(t)->type, cont_id);
712 break;
713 case BTF_KIND_FWD:
714 btf_dump_emit_fwd_def(d, id, t);
715 btf_dump_printf(d, ";\n\n");
716 tstate->emit_state = EMITTED;
717 break;
718 case BTF_KIND_TYPEDEF:
719 tstate->emit_state = EMITTING;
720 btf_dump_emit_type(d, t->type, id);
721
722
723
724
725
726
727
728 if (!tstate->fwd_emitted && !btf_dump_is_blacklisted(d, id)) {
729 btf_dump_emit_typedef_def(d, id, t, 0);
730 btf_dump_printf(d, ";\n\n");
731 }
732 tstate->emit_state = EMITTED;
733 break;
734 case BTF_KIND_STRUCT:
735 case BTF_KIND_UNION:
736 tstate->emit_state = EMITTING;
737
738
739
740
741
742
743
744 if (top_level_def || t->name_off == 0) {
745 const struct btf_member *m = btf_members(t);
746 __u16 vlen = btf_vlen(t);
747 int i, new_cont_id;
748
749 new_cont_id = t->name_off == 0 ? cont_id : id;
750 for (i = 0; i < vlen; i++, m++)
751 btf_dump_emit_type(d, m->type, new_cont_id);
752 } else if (!tstate->fwd_emitted && id != cont_id) {
753 btf_dump_emit_struct_fwd(d, id, t);
754 btf_dump_printf(d, ";\n\n");
755 tstate->fwd_emitted = 1;
756 }
757
758 if (top_level_def) {
759 btf_dump_emit_struct_def(d, id, t, 0);
760 btf_dump_printf(d, ";\n\n");
761 tstate->emit_state = EMITTED;
762 } else {
763 tstate->emit_state = NOT_EMITTED;
764 }
765 break;
766 case BTF_KIND_FUNC_PROTO: {
767 const struct btf_param *p = btf_params(t);
768 __u16 vlen = btf_vlen(t);
769 int i;
770
771 btf_dump_emit_type(d, t->type, cont_id);
772 for (i = 0; i < vlen; i++, p++)
773 btf_dump_emit_type(d, p->type, cont_id);
774
775 break;
776 }
777 default:
778 break;
779 }
780}
781
782static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
783 const struct btf_type *t)
784{
785 const struct btf_member *m;
786 int align, i, bit_sz;
787 __u16 vlen;
788
789 align = btf__align_of(btf, id);
790
791 if (align && t->size % align)
792 return true;
793
794 m = btf_members(t);
795 vlen = btf_vlen(t);
796
797 for (i = 0; i < vlen; i++, m++) {
798 align = btf__align_of(btf, m->type);
799 bit_sz = btf_member_bitfield_size(t, i);
800 if (align && bit_sz == 0 && m->offset % (8 * align) != 0)
801 return true;
802 }
803
804
805
806
807
808 return false;
809}
810
811static int chip_away_bits(int total, int at_most)
812{
813 return total % at_most ? : at_most;
814}
815
816static void btf_dump_emit_bit_padding(const struct btf_dump *d,
817 int cur_off, int m_off, int m_bit_sz,
818 int align, int lvl)
819{
820 int off_diff = m_off - cur_off;
821 int ptr_bits = d->ptr_sz * 8;
822
823 if (off_diff <= 0)
824
825 return;
826 if (m_bit_sz == 0 && off_diff < align * 8)
827
828 return;
829
830 while (off_diff > 0) {
831 const char *pad_type;
832 int pad_bits;
833
834 if (ptr_bits > 32 && off_diff > 32) {
835 pad_type = "long";
836 pad_bits = chip_away_bits(off_diff, ptr_bits);
837 } else if (off_diff > 16) {
838 pad_type = "int";
839 pad_bits = chip_away_bits(off_diff, 32);
840 } else if (off_diff > 8) {
841 pad_type = "short";
842 pad_bits = chip_away_bits(off_diff, 16);
843 } else {
844 pad_type = "char";
845 pad_bits = chip_away_bits(off_diff, 8);
846 }
847 btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, pad_bits);
848 off_diff -= pad_bits;
849 }
850}
851
852static void btf_dump_emit_struct_fwd(struct btf_dump *d, __u32 id,
853 const struct btf_type *t)
854{
855 btf_dump_printf(d, "%s %s",
856 btf_is_struct(t) ? "struct" : "union",
857 btf_dump_type_name(d, id));
858}
859
860static void btf_dump_emit_struct_def(struct btf_dump *d,
861 __u32 id,
862 const struct btf_type *t,
863 int lvl)
864{
865 const struct btf_member *m = btf_members(t);
866 bool is_struct = btf_is_struct(t);
867 int align, i, packed, off = 0;
868 __u16 vlen = btf_vlen(t);
869
870 packed = is_struct ? btf_is_struct_packed(d->btf, id, t) : 0;
871
872 btf_dump_printf(d, "%s%s%s {",
873 is_struct ? "struct" : "union",
874 t->name_off ? " " : "",
875 btf_dump_type_name(d, id));
876
877 for (i = 0; i < vlen; i++, m++) {
878 const char *fname;
879 int m_off, m_sz;
880
881 fname = btf_name_of(d, m->name_off);
882 m_sz = btf_member_bitfield_size(t, i);
883 m_off = btf_member_bit_offset(t, i);
884 align = packed ? 1 : btf__align_of(d->btf, m->type);
885
886 btf_dump_emit_bit_padding(d, off, m_off, m_sz, align, lvl + 1);
887 btf_dump_printf(d, "\n%s", pfx(lvl + 1));
888 btf_dump_emit_type_decl(d, m->type, fname, lvl + 1);
889
890 if (m_sz) {
891 btf_dump_printf(d, ": %d", m_sz);
892 off = m_off + m_sz;
893 } else {
894 m_sz = max((__s64)0, btf__resolve_size(d->btf, m->type));
895 off = m_off + m_sz * 8;
896 }
897 btf_dump_printf(d, ";");
898 }
899
900
901 if (is_struct) {
902 align = packed ? 1 : btf__align_of(d->btf, id);
903 btf_dump_emit_bit_padding(d, off, t->size * 8, 0, align,
904 lvl + 1);
905 }
906
907 if (vlen)
908 btf_dump_printf(d, "\n");
909 btf_dump_printf(d, "%s}", pfx(lvl));
910 if (packed)
911 btf_dump_printf(d, " __attribute__((packed))");
912}
913
914static const char *missing_base_types[][2] = {
915
916
917
918
919 { "__Poly8_t", "unsigned char" },
920 { "__Poly16_t", "unsigned short" },
921 { "__Poly64_t", "unsigned long long" },
922 { "__Poly128_t", "unsigned __int128" },
923};
924
925static void btf_dump_emit_missing_aliases(struct btf_dump *d, __u32 id,
926 const struct btf_type *t)
927{
928 const char *name = btf_dump_type_name(d, id);
929 int i;
930
931 for (i = 0; i < ARRAY_SIZE(missing_base_types); i++) {
932 if (strcmp(name, missing_base_types[i][0]) == 0) {
933 btf_dump_printf(d, "typedef %s %s;\n\n",
934 missing_base_types[i][1], name);
935 break;
936 }
937 }
938}
939
940static void btf_dump_emit_enum_fwd(struct btf_dump *d, __u32 id,
941 const struct btf_type *t)
942{
943 btf_dump_printf(d, "enum %s", btf_dump_type_name(d, id));
944}
945
946static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
947 const struct btf_type *t,
948 int lvl)
949{
950 const struct btf_enum *v = btf_enum(t);
951 __u16 vlen = btf_vlen(t);
952 const char *name;
953 size_t dup_cnt;
954 int i;
955
956 btf_dump_printf(d, "enum%s%s",
957 t->name_off ? " " : "",
958 btf_dump_type_name(d, id));
959
960 if (vlen) {
961 btf_dump_printf(d, " {");
962 for (i = 0; i < vlen; i++, v++) {
963 name = btf_name_of(d, v->name_off);
964
965 dup_cnt = btf_dump_name_dups(d, d->ident_names, name);
966 if (dup_cnt > 1) {
967 btf_dump_printf(d, "\n%s%s___%zu = %u,",
968 pfx(lvl + 1), name, dup_cnt,
969 (__u32)v->val);
970 } else {
971 btf_dump_printf(d, "\n%s%s = %u,",
972 pfx(lvl + 1), name,
973 (__u32)v->val);
974 }
975 }
976 btf_dump_printf(d, "\n%s}", pfx(lvl));
977 }
978}
979
980static void btf_dump_emit_fwd_def(struct btf_dump *d, __u32 id,
981 const struct btf_type *t)
982{
983 const char *name = btf_dump_type_name(d, id);
984
985 if (btf_kflag(t))
986 btf_dump_printf(d, "union %s", name);
987 else
988 btf_dump_printf(d, "struct %s", name);
989}
990
991static void btf_dump_emit_typedef_def(struct btf_dump *d, __u32 id,
992 const struct btf_type *t, int lvl)
993{
994 const char *name = btf_dump_ident_name(d, id);
995
996
997
998
999
1000
1001
1002 if (t->type == 0 && strcmp(name, "__gnuc_va_list") == 0) {
1003 btf_dump_printf(d, "typedef __builtin_va_list __gnuc_va_list");
1004 return;
1005 }
1006
1007 btf_dump_printf(d, "typedef ");
1008 btf_dump_emit_type_decl(d, t->type, name, lvl);
1009}
1010
1011static int btf_dump_push_decl_stack_id(struct btf_dump *d, __u32 id)
1012{
1013 __u32 *new_stack;
1014 size_t new_cap;
1015
1016 if (d->decl_stack_cnt >= d->decl_stack_cap) {
1017 new_cap = max(16, d->decl_stack_cap * 3 / 2);
1018 new_stack = libbpf_reallocarray(d->decl_stack, new_cap, sizeof(new_stack[0]));
1019 if (!new_stack)
1020 return -ENOMEM;
1021 d->decl_stack = new_stack;
1022 d->decl_stack_cap = new_cap;
1023 }
1024
1025 d->decl_stack[d->decl_stack_cnt++] = id;
1026
1027 return 0;
1028}
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071int btf_dump__emit_type_decl(struct btf_dump *d, __u32 id,
1072 const struct btf_dump_emit_type_decl_opts *opts)
1073{
1074 const char *fname;
1075 int lvl, err;
1076
1077 if (!OPTS_VALID(opts, btf_dump_emit_type_decl_opts))
1078 return libbpf_err(-EINVAL);
1079
1080 err = btf_dump_resize(d);
1081 if (err)
1082 return libbpf_err(err);
1083
1084 fname = OPTS_GET(opts, field_name, "");
1085 lvl = OPTS_GET(opts, indent_level, 0);
1086 d->strip_mods = OPTS_GET(opts, strip_mods, false);
1087 btf_dump_emit_type_decl(d, id, fname, lvl);
1088 d->strip_mods = false;
1089 return 0;
1090}
1091
1092static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id,
1093 const char *fname, int lvl)
1094{
1095 struct id_stack decl_stack;
1096 const struct btf_type *t;
1097 int err, stack_start;
1098
1099 stack_start = d->decl_stack_cnt;
1100 for (;;) {
1101 t = btf__type_by_id(d->btf, id);
1102 if (d->strip_mods && btf_is_mod(t))
1103 goto skip_mod;
1104
1105 err = btf_dump_push_decl_stack_id(d, id);
1106 if (err < 0) {
1107
1108
1109
1110
1111
1112 pr_warn("not enough memory for decl stack:%d", err);
1113 d->decl_stack_cnt = stack_start;
1114 return;
1115 }
1116skip_mod:
1117
1118 if (id == 0)
1119 break;
1120
1121 switch (btf_kind(t)) {
1122 case BTF_KIND_PTR:
1123 case BTF_KIND_VOLATILE:
1124 case BTF_KIND_CONST:
1125 case BTF_KIND_RESTRICT:
1126 case BTF_KIND_FUNC_PROTO:
1127 id = t->type;
1128 break;
1129 case BTF_KIND_ARRAY:
1130 id = btf_array(t)->type;
1131 break;
1132 case BTF_KIND_INT:
1133 case BTF_KIND_ENUM:
1134 case BTF_KIND_FWD:
1135 case BTF_KIND_STRUCT:
1136 case BTF_KIND_UNION:
1137 case BTF_KIND_TYPEDEF:
1138 case BTF_KIND_FLOAT:
1139 goto done;
1140 default:
1141 pr_warn("unexpected type in decl chain, kind:%u, id:[%u]\n",
1142 btf_kind(t), id);
1143 goto done;
1144 }
1145 }
1146done:
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157 decl_stack.ids = d->decl_stack + stack_start;
1158 decl_stack.cnt = d->decl_stack_cnt - stack_start;
1159 btf_dump_emit_type_chain(d, &decl_stack, fname, lvl);
1160
1161
1162
1163
1164
1165
1166
1167
1168 d->decl_stack_cnt = stack_start;
1169}
1170
1171static void btf_dump_emit_mods(struct btf_dump *d, struct id_stack *decl_stack)
1172{
1173 const struct btf_type *t;
1174 __u32 id;
1175
1176 while (decl_stack->cnt) {
1177 id = decl_stack->ids[decl_stack->cnt - 1];
1178 t = btf__type_by_id(d->btf, id);
1179
1180 switch (btf_kind(t)) {
1181 case BTF_KIND_VOLATILE:
1182 btf_dump_printf(d, "volatile ");
1183 break;
1184 case BTF_KIND_CONST:
1185 btf_dump_printf(d, "const ");
1186 break;
1187 case BTF_KIND_RESTRICT:
1188 btf_dump_printf(d, "restrict ");
1189 break;
1190 default:
1191 return;
1192 }
1193 decl_stack->cnt--;
1194 }
1195}
1196
1197static void btf_dump_drop_mods(struct btf_dump *d, struct id_stack *decl_stack)
1198{
1199 const struct btf_type *t;
1200 __u32 id;
1201
1202 while (decl_stack->cnt) {
1203 id = decl_stack->ids[decl_stack->cnt - 1];
1204 t = btf__type_by_id(d->btf, id);
1205 if (!btf_is_mod(t))
1206 return;
1207 decl_stack->cnt--;
1208 }
1209}
1210
1211static void btf_dump_emit_name(const struct btf_dump *d,
1212 const char *name, bool last_was_ptr)
1213{
1214 bool separate = name[0] && !last_was_ptr;
1215
1216 btf_dump_printf(d, "%s%s", separate ? " " : "", name);
1217}
1218
1219static void btf_dump_emit_type_chain(struct btf_dump *d,
1220 struct id_stack *decls,
1221 const char *fname, int lvl)
1222{
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232 bool last_was_ptr = true;
1233 const struct btf_type *t;
1234 const char *name;
1235 __u16 kind;
1236 __u32 id;
1237
1238 while (decls->cnt) {
1239 id = decls->ids[--decls->cnt];
1240 if (id == 0) {
1241
1242 btf_dump_emit_mods(d, decls);
1243 btf_dump_printf(d, "void");
1244 last_was_ptr = false;
1245 continue;
1246 }
1247
1248 t = btf__type_by_id(d->btf, id);
1249 kind = btf_kind(t);
1250
1251 switch (kind) {
1252 case BTF_KIND_INT:
1253 case BTF_KIND_FLOAT:
1254 btf_dump_emit_mods(d, decls);
1255 name = btf_name_of(d, t->name_off);
1256 btf_dump_printf(d, "%s", name);
1257 break;
1258 case BTF_KIND_STRUCT:
1259 case BTF_KIND_UNION:
1260 btf_dump_emit_mods(d, decls);
1261
1262 if (t->name_off == 0)
1263 btf_dump_emit_struct_def(d, id, t, lvl);
1264 else
1265 btf_dump_emit_struct_fwd(d, id, t);
1266 break;
1267 case BTF_KIND_ENUM:
1268 btf_dump_emit_mods(d, decls);
1269
1270 if (t->name_off == 0)
1271 btf_dump_emit_enum_def(d, id, t, lvl);
1272 else
1273 btf_dump_emit_enum_fwd(d, id, t);
1274 break;
1275 case BTF_KIND_FWD:
1276 btf_dump_emit_mods(d, decls);
1277 btf_dump_emit_fwd_def(d, id, t);
1278 break;
1279 case BTF_KIND_TYPEDEF:
1280 btf_dump_emit_mods(d, decls);
1281 btf_dump_printf(d, "%s", btf_dump_ident_name(d, id));
1282 break;
1283 case BTF_KIND_PTR:
1284 btf_dump_printf(d, "%s", last_was_ptr ? "*" : " *");
1285 break;
1286 case BTF_KIND_VOLATILE:
1287 btf_dump_printf(d, " volatile");
1288 break;
1289 case BTF_KIND_CONST:
1290 btf_dump_printf(d, " const");
1291 break;
1292 case BTF_KIND_RESTRICT:
1293 btf_dump_printf(d, " restrict");
1294 break;
1295 case BTF_KIND_ARRAY: {
1296 const struct btf_array *a = btf_array(t);
1297 const struct btf_type *next_t;
1298 __u32 next_id;
1299 bool multidim;
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310 btf_dump_drop_mods(d, decls);
1311
1312 if (decls->cnt == 0) {
1313 btf_dump_emit_name(d, fname, last_was_ptr);
1314 btf_dump_printf(d, "[%u]", a->nelems);
1315 return;
1316 }
1317
1318 next_id = decls->ids[decls->cnt - 1];
1319 next_t = btf__type_by_id(d->btf, next_id);
1320 multidim = btf_is_array(next_t);
1321
1322 if (fname[0] && !last_was_ptr)
1323 btf_dump_printf(d, " ");
1324
1325 if (!multidim)
1326 btf_dump_printf(d, "(");
1327 btf_dump_emit_type_chain(d, decls, fname, lvl);
1328 if (!multidim)
1329 btf_dump_printf(d, ")");
1330 btf_dump_printf(d, "[%u]", a->nelems);
1331 return;
1332 }
1333 case BTF_KIND_FUNC_PROTO: {
1334 const struct btf_param *p = btf_params(t);
1335 __u16 vlen = btf_vlen(t);
1336 int i;
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346 btf_dump_drop_mods(d, decls);
1347 if (decls->cnt) {
1348 btf_dump_printf(d, " (");
1349 btf_dump_emit_type_chain(d, decls, fname, lvl);
1350 btf_dump_printf(d, ")");
1351 } else {
1352 btf_dump_emit_name(d, fname, last_was_ptr);
1353 }
1354 btf_dump_printf(d, "(");
1355
1356
1357
1358
1359
1360
1361 if (vlen == 1 && p->type == 0) {
1362 btf_dump_printf(d, ")");
1363 return;
1364 }
1365
1366 for (i = 0; i < vlen; i++, p++) {
1367 if (i > 0)
1368 btf_dump_printf(d, ", ");
1369
1370
1371 if (i == vlen - 1 && p->type == 0) {
1372 btf_dump_printf(d, "...");
1373 break;
1374 }
1375
1376 name = btf_name_of(d, p->name_off);
1377 btf_dump_emit_type_decl(d, p->type, name, lvl);
1378 }
1379
1380 btf_dump_printf(d, ")");
1381 return;
1382 }
1383 default:
1384 pr_warn("unexpected type in decl chain, kind:%u, id:[%u]\n",
1385 kind, id);
1386 return;
1387 }
1388
1389 last_was_ptr = kind == BTF_KIND_PTR;
1390 }
1391
1392 btf_dump_emit_name(d, fname, last_was_ptr);
1393}
1394
1395
1396static size_t btf_dump_name_dups(struct btf_dump *d, struct hashmap *name_map,
1397 const char *orig_name)
1398{
1399 size_t dup_cnt = 0;
1400
1401 hashmap__find(name_map, orig_name, (void **)&dup_cnt);
1402 dup_cnt++;
1403 hashmap__set(name_map, orig_name, (void *)dup_cnt, NULL, NULL);
1404
1405 return dup_cnt;
1406}
1407
1408static const char *btf_dump_resolve_name(struct btf_dump *d, __u32 id,
1409 struct hashmap *name_map)
1410{
1411 struct btf_dump_type_aux_state *s = &d->type_states[id];
1412 const struct btf_type *t = btf__type_by_id(d->btf, id);
1413 const char *orig_name = btf_name_of(d, t->name_off);
1414 const char **cached_name = &d->cached_names[id];
1415 size_t dup_cnt;
1416
1417 if (t->name_off == 0)
1418 return "";
1419
1420 if (s->name_resolved)
1421 return *cached_name ? *cached_name : orig_name;
1422
1423 dup_cnt = btf_dump_name_dups(d, name_map, orig_name);
1424 if (dup_cnt > 1) {
1425 const size_t max_len = 256;
1426 char new_name[max_len];
1427
1428 snprintf(new_name, max_len, "%s___%zu", orig_name, dup_cnt);
1429 *cached_name = strdup(new_name);
1430 }
1431
1432 s->name_resolved = 1;
1433 return *cached_name ? *cached_name : orig_name;
1434}
1435
1436static const char *btf_dump_type_name(struct btf_dump *d, __u32 id)
1437{
1438 return btf_dump_resolve_name(d, id, d->type_names);
1439}
1440
1441static const char *btf_dump_ident_name(struct btf_dump *d, __u32 id)
1442{
1443 return btf_dump_resolve_name(d, id, d->ident_names);
1444}
1445