.. | .. |
---|
188 | 188 | return 0; |
---|
189 | 189 | } |
---|
190 | 190 | |
---|
| 191 | +static void btf_dump_free_names(struct hashmap *map) |
---|
| 192 | +{ |
---|
| 193 | + size_t bkt; |
---|
| 194 | + struct hashmap_entry *cur; |
---|
| 195 | + |
---|
| 196 | + hashmap__for_each_entry(map, cur, bkt) |
---|
| 197 | + free((void *)cur->key); |
---|
| 198 | + |
---|
| 199 | + hashmap__free(map); |
---|
| 200 | +} |
---|
| 201 | + |
---|
191 | 202 | void btf_dump__free(struct btf_dump *d) |
---|
192 | 203 | { |
---|
193 | 204 | int i; |
---|
.. | .. |
---|
206 | 217 | free(d->cached_names); |
---|
207 | 218 | free(d->emit_queue); |
---|
208 | 219 | free(d->decl_stack); |
---|
209 | | - hashmap__free(d->type_names); |
---|
210 | | - hashmap__free(d->ident_names); |
---|
| 220 | + btf_dump_free_names(d->type_names); |
---|
| 221 | + btf_dump_free_names(d->ident_names); |
---|
211 | 222 | |
---|
212 | 223 | free(d); |
---|
213 | 224 | } |
---|
.. | .. |
---|
781 | 792 | const struct btf_type *t) |
---|
782 | 793 | { |
---|
783 | 794 | const struct btf_member *m; |
---|
784 | | - int align, i, bit_sz; |
---|
| 795 | + int max_align = 1, align, i, bit_sz; |
---|
785 | 796 | __u16 vlen; |
---|
786 | | - |
---|
787 | | - align = btf__align_of(btf, id); |
---|
788 | | - /* size of a non-packed struct has to be a multiple of its alignment*/ |
---|
789 | | - if (align && t->size % align) |
---|
790 | | - return true; |
---|
791 | 797 | |
---|
792 | 798 | m = btf_members(t); |
---|
793 | 799 | vlen = btf_vlen(t); |
---|
.. | .. |
---|
797 | 803 | bit_sz = btf_member_bitfield_size(t, i); |
---|
798 | 804 | if (align && bit_sz == 0 && m->offset % (8 * align) != 0) |
---|
799 | 805 | return true; |
---|
| 806 | + max_align = max(align, max_align); |
---|
800 | 807 | } |
---|
801 | | - |
---|
| 808 | + /* size of a non-packed struct has to be a multiple of its alignment */ |
---|
| 809 | + if (t->size % max_align != 0) |
---|
| 810 | + return true; |
---|
802 | 811 | /* |
---|
803 | 812 | * if original struct was marked as packed, but its layout is |
---|
804 | 813 | * naturally aligned, we'll detect that it's not packed |
---|
.. | .. |
---|
806 | 815 | return false; |
---|
807 | 816 | } |
---|
808 | 817 | |
---|
809 | | -static int chip_away_bits(int total, int at_most) |
---|
810 | | -{ |
---|
811 | | - return total % at_most ? : at_most; |
---|
812 | | -} |
---|
813 | | - |
---|
814 | 818 | static void btf_dump_emit_bit_padding(const struct btf_dump *d, |
---|
815 | | - int cur_off, int m_off, int m_bit_sz, |
---|
816 | | - int align, int lvl) |
---|
| 819 | + int cur_off, int next_off, int next_align, |
---|
| 820 | + bool in_bitfield, int lvl) |
---|
817 | 821 | { |
---|
818 | | - int off_diff = m_off - cur_off; |
---|
819 | | - int ptr_bits = d->ptr_sz * 8; |
---|
| 822 | + const struct { |
---|
| 823 | + const char *name; |
---|
| 824 | + int bits; |
---|
| 825 | + } pads[] = { |
---|
| 826 | + {"long", d->ptr_sz * 8}, {"int", 32}, {"short", 16}, {"char", 8} |
---|
| 827 | + }; |
---|
| 828 | + int new_off, pad_bits, bits, i; |
---|
| 829 | + const char *pad_type; |
---|
820 | 830 | |
---|
821 | | - if (off_diff <= 0) |
---|
822 | | - /* no gap */ |
---|
823 | | - return; |
---|
824 | | - if (m_bit_sz == 0 && off_diff < align * 8) |
---|
825 | | - /* natural padding will take care of a gap */ |
---|
826 | | - return; |
---|
| 831 | + if (cur_off >= next_off) |
---|
| 832 | + return; /* no gap */ |
---|
827 | 833 | |
---|
828 | | - while (off_diff > 0) { |
---|
829 | | - const char *pad_type; |
---|
830 | | - int pad_bits; |
---|
| 834 | + /* For filling out padding we want to take advantage of |
---|
| 835 | + * natural alignment rules to minimize unnecessary explicit |
---|
| 836 | + * padding. First, we find the largest type (among long, int, |
---|
| 837 | + * short, or char) that can be used to force naturally aligned |
---|
| 838 | + * boundary. Once determined, we'll use such type to fill in |
---|
| 839 | + * the remaining padding gap. In some cases we can rely on |
---|
| 840 | + * compiler filling some gaps, but sometimes we need to force |
---|
| 841 | + * alignment to close natural alignment with markers like |
---|
| 842 | + * `long: 0` (this is always the case for bitfields). Note |
---|
| 843 | + * that even if struct itself has, let's say 4-byte alignment |
---|
| 844 | + * (i.e., it only uses up to int-aligned types), using `long: |
---|
| 845 | + * X;` explicit padding doesn't actually change struct's |
---|
| 846 | + * overall alignment requirements, but compiler does take into |
---|
| 847 | + * account that type's (long, in this example) natural |
---|
| 848 | + * alignment requirements when adding implicit padding. We use |
---|
| 849 | + * this fact heavily and don't worry about ruining correct |
---|
| 850 | + * struct alignment requirement. |
---|
| 851 | + */ |
---|
| 852 | + for (i = 0; i < ARRAY_SIZE(pads); i++) { |
---|
| 853 | + pad_bits = pads[i].bits; |
---|
| 854 | + pad_type = pads[i].name; |
---|
831 | 855 | |
---|
832 | | - if (ptr_bits > 32 && off_diff > 32) { |
---|
833 | | - pad_type = "long"; |
---|
834 | | - pad_bits = chip_away_bits(off_diff, ptr_bits); |
---|
835 | | - } else if (off_diff > 16) { |
---|
836 | | - pad_type = "int"; |
---|
837 | | - pad_bits = chip_away_bits(off_diff, 32); |
---|
838 | | - } else if (off_diff > 8) { |
---|
839 | | - pad_type = "short"; |
---|
840 | | - pad_bits = chip_away_bits(off_diff, 16); |
---|
841 | | - } else { |
---|
842 | | - pad_type = "char"; |
---|
843 | | - pad_bits = chip_away_bits(off_diff, 8); |
---|
| 856 | + new_off = roundup(cur_off, pad_bits); |
---|
| 857 | + if (new_off <= next_off) |
---|
| 858 | + break; |
---|
| 859 | + } |
---|
| 860 | + |
---|
| 861 | + if (new_off > cur_off && new_off <= next_off) { |
---|
| 862 | + /* We need explicit `<type>: 0` aligning mark if next |
---|
| 863 | + * field is right on alignment offset and its |
---|
| 864 | + * alignment requirement is less strict than <type>'s |
---|
| 865 | + * alignment (so compiler won't naturally align to the |
---|
| 866 | + * offset we expect), or if subsequent `<type>: X`, |
---|
| 867 | + * will actually completely fit in the remaining hole, |
---|
| 868 | + * making compiler basically ignore `<type>: X` |
---|
| 869 | + * completely. |
---|
| 870 | + */ |
---|
| 871 | + if (in_bitfield || |
---|
| 872 | + (new_off == next_off && roundup(cur_off, next_align * 8) != new_off) || |
---|
| 873 | + (new_off != next_off && next_off - new_off <= new_off - cur_off)) |
---|
| 874 | + /* but for bitfields we'll emit explicit bit count */ |
---|
| 875 | + btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, |
---|
| 876 | + in_bitfield ? new_off - cur_off : 0); |
---|
| 877 | + cur_off = new_off; |
---|
| 878 | + } |
---|
| 879 | + |
---|
| 880 | + /* Now we know we start at naturally aligned offset for a chosen |
---|
| 881 | + * padding type (long, int, short, or char), and so the rest is just |
---|
| 882 | + * a straightforward filling of remaining padding gap with full |
---|
| 883 | + * `<type>: sizeof(<type>);` markers, except for the last one, which |
---|
| 884 | + * might need smaller than sizeof(<type>) padding. |
---|
| 885 | + */ |
---|
| 886 | + while (cur_off != next_off) { |
---|
| 887 | + bits = min(next_off - cur_off, pad_bits); |
---|
| 888 | + if (bits == pad_bits) { |
---|
| 889 | + btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, pad_bits); |
---|
| 890 | + cur_off += bits; |
---|
| 891 | + continue; |
---|
844 | 892 | } |
---|
845 | | - btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, pad_bits); |
---|
846 | | - off_diff -= pad_bits; |
---|
| 893 | + /* For the remainder padding that doesn't cover entire |
---|
| 894 | + * pad_type bit length, we pick the smallest necessary type. |
---|
| 895 | + * This is pure aesthetics, we could have just used `long`, |
---|
| 896 | + * but having smallest necessary one communicates better the |
---|
| 897 | + * scale of the padding gap. |
---|
| 898 | + */ |
---|
| 899 | + for (i = ARRAY_SIZE(pads) - 1; i >= 0; i--) { |
---|
| 900 | + pad_type = pads[i].name; |
---|
| 901 | + pad_bits = pads[i].bits; |
---|
| 902 | + if (pad_bits < bits) |
---|
| 903 | + continue; |
---|
| 904 | + |
---|
| 905 | + btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, bits); |
---|
| 906 | + cur_off += bits; |
---|
| 907 | + break; |
---|
| 908 | + } |
---|
847 | 909 | } |
---|
848 | 910 | } |
---|
849 | 911 | |
---|
.. | .. |
---|
862 | 924 | { |
---|
863 | 925 | const struct btf_member *m = btf_members(t); |
---|
864 | 926 | bool is_struct = btf_is_struct(t); |
---|
865 | | - int align, i, packed, off = 0; |
---|
| 927 | + bool packed, prev_bitfield = false; |
---|
| 928 | + int align, i, off = 0; |
---|
866 | 929 | __u16 vlen = btf_vlen(t); |
---|
867 | 930 | |
---|
| 931 | + align = btf__align_of(d->btf, id); |
---|
868 | 932 | packed = is_struct ? btf_is_struct_packed(d->btf, id, t) : 0; |
---|
869 | 933 | |
---|
870 | 934 | btf_dump_printf(d, "%s%s%s {", |
---|
.. | .. |
---|
874 | 938 | |
---|
875 | 939 | for (i = 0; i < vlen; i++, m++) { |
---|
876 | 940 | const char *fname; |
---|
877 | | - int m_off, m_sz; |
---|
| 941 | + int m_off, m_sz, m_align; |
---|
| 942 | + bool in_bitfield; |
---|
878 | 943 | |
---|
879 | 944 | fname = btf_name_of(d, m->name_off); |
---|
880 | 945 | m_sz = btf_member_bitfield_size(t, i); |
---|
881 | 946 | m_off = btf_member_bit_offset(t, i); |
---|
882 | | - align = packed ? 1 : btf__align_of(d->btf, m->type); |
---|
| 947 | + m_align = packed ? 1 : btf__align_of(d->btf, m->type); |
---|
883 | 948 | |
---|
884 | | - btf_dump_emit_bit_padding(d, off, m_off, m_sz, align, lvl + 1); |
---|
| 949 | + in_bitfield = prev_bitfield && m_sz != 0; |
---|
| 950 | + |
---|
| 951 | + btf_dump_emit_bit_padding(d, off, m_off, m_align, in_bitfield, lvl + 1); |
---|
885 | 952 | btf_dump_printf(d, "\n%s", pfx(lvl + 1)); |
---|
886 | 953 | btf_dump_emit_type_decl(d, m->type, fname, lvl + 1); |
---|
887 | 954 | |
---|
888 | 955 | if (m_sz) { |
---|
889 | 956 | btf_dump_printf(d, ": %d", m_sz); |
---|
890 | 957 | off = m_off + m_sz; |
---|
| 958 | + prev_bitfield = true; |
---|
891 | 959 | } else { |
---|
892 | 960 | m_sz = max((__s64)0, btf__resolve_size(d->btf, m->type)); |
---|
893 | 961 | off = m_off + m_sz * 8; |
---|
| 962 | + prev_bitfield = false; |
---|
894 | 963 | } |
---|
| 964 | + |
---|
895 | 965 | btf_dump_printf(d, ";"); |
---|
896 | 966 | } |
---|
897 | 967 | |
---|
898 | 968 | /* pad at the end, if necessary */ |
---|
899 | | - if (is_struct) { |
---|
900 | | - align = packed ? 1 : btf__align_of(d->btf, id); |
---|
901 | | - btf_dump_emit_bit_padding(d, off, t->size * 8, 0, align, |
---|
902 | | - lvl + 1); |
---|
903 | | - } |
---|
| 969 | + if (is_struct) |
---|
| 970 | + btf_dump_emit_bit_padding(d, off, t->size * 8, align, false, lvl + 1); |
---|
904 | 971 | |
---|
905 | | - if (vlen) |
---|
| 972 | + /* |
---|
| 973 | + * Keep `struct empty {}` on a single line, |
---|
| 974 | + * only print newline when there are regular or padding fields. |
---|
| 975 | + */ |
---|
| 976 | + if (vlen || t->size) { |
---|
906 | 977 | btf_dump_printf(d, "\n"); |
---|
907 | | - btf_dump_printf(d, "%s}", pfx(lvl)); |
---|
| 978 | + btf_dump_printf(d, "%s}", pfx(lvl)); |
---|
| 979 | + } else { |
---|
| 980 | + btf_dump_printf(d, "}"); |
---|
| 981 | + } |
---|
908 | 982 | if (packed) |
---|
909 | 983 | btf_dump_printf(d, " __attribute__((packed))"); |
---|
910 | 984 | } |
---|
.. | .. |
---|
1392 | 1466 | static size_t btf_dump_name_dups(struct btf_dump *d, struct hashmap *name_map, |
---|
1393 | 1467 | const char *orig_name) |
---|
1394 | 1468 | { |
---|
| 1469 | + char *old_name, *new_name; |
---|
1395 | 1470 | size_t dup_cnt = 0; |
---|
| 1471 | + int err; |
---|
| 1472 | + |
---|
| 1473 | + new_name = strdup(orig_name); |
---|
| 1474 | + if (!new_name) |
---|
| 1475 | + return 1; |
---|
1396 | 1476 | |
---|
1397 | 1477 | hashmap__find(name_map, orig_name, (void **)&dup_cnt); |
---|
1398 | 1478 | dup_cnt++; |
---|
1399 | | - hashmap__set(name_map, orig_name, (void *)dup_cnt, NULL, NULL); |
---|
| 1479 | + |
---|
| 1480 | + err = hashmap__set(name_map, new_name, (void *)dup_cnt, |
---|
| 1481 | + (const void **)&old_name, NULL); |
---|
| 1482 | + if (err) |
---|
| 1483 | + free(new_name); |
---|
| 1484 | + |
---|
| 1485 | + free(old_name); |
---|
1400 | 1486 | |
---|
1401 | 1487 | return dup_cnt; |
---|
1402 | 1488 | } |
---|