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