hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/tools/lib/bpf/btf_dump.c
....@@ -188,6 +188,17 @@
188188 return 0;
189189 }
190190
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
+
191202 void btf_dump__free(struct btf_dump *d)
192203 {
193204 int i;
....@@ -206,8 +217,8 @@
206217 free(d->cached_names);
207218 free(d->emit_queue);
208219 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);
211222
212223 free(d);
213224 }
....@@ -781,13 +792,8 @@
781792 const struct btf_type *t)
782793 {
783794 const struct btf_member *m;
784
- int align, i, bit_sz;
795
+ int max_align = 1, align, i, bit_sz;
785796 __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;
791797
792798 m = btf_members(t);
793799 vlen = btf_vlen(t);
....@@ -797,8 +803,11 @@
797803 bit_sz = btf_member_bitfield_size(t, i);
798804 if (align && bit_sz == 0 && m->offset % (8 * align) != 0)
799805 return true;
806
+ max_align = max(align, max_align);
800807 }
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;
802811 /*
803812 * if original struct was marked as packed, but its layout is
804813 * naturally aligned, we'll detect that it's not packed
....@@ -806,44 +815,97 @@
806815 return false;
807816 }
808817
809
-static int chip_away_bits(int total, int at_most)
810
-{
811
- return total % at_most ? : at_most;
812
-}
813
-
814818 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)
817821 {
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;
820830
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 */
827833
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;
831855
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;
844892 }
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
+ }
847909 }
848910 }
849911
....@@ -862,9 +924,11 @@
862924 {
863925 const struct btf_member *m = btf_members(t);
864926 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;
866929 __u16 vlen = btf_vlen(t);
867930
931
+ align = btf__align_of(d->btf, id);
868932 packed = is_struct ? btf_is_struct_packed(d->btf, id, t) : 0;
869933
870934 btf_dump_printf(d, "%s%s%s {",
....@@ -874,37 +938,47 @@
874938
875939 for (i = 0; i < vlen; i++, m++) {
876940 const char *fname;
877
- int m_off, m_sz;
941
+ int m_off, m_sz, m_align;
942
+ bool in_bitfield;
878943
879944 fname = btf_name_of(d, m->name_off);
880945 m_sz = btf_member_bitfield_size(t, i);
881946 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);
883948
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);
885952 btf_dump_printf(d, "\n%s", pfx(lvl + 1));
886953 btf_dump_emit_type_decl(d, m->type, fname, lvl + 1);
887954
888955 if (m_sz) {
889956 btf_dump_printf(d, ": %d", m_sz);
890957 off = m_off + m_sz;
958
+ prev_bitfield = true;
891959 } else {
892960 m_sz = max((__s64)0, btf__resolve_size(d->btf, m->type));
893961 off = m_off + m_sz * 8;
962
+ prev_bitfield = false;
894963 }
964
+
895965 btf_dump_printf(d, ";");
896966 }
897967
898968 /* 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);
904971
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) {
906977 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
+ }
908982 if (packed)
909983 btf_dump_printf(d, " __attribute__((packed))");
910984 }
....@@ -1392,11 +1466,23 @@
13921466 static size_t btf_dump_name_dups(struct btf_dump *d, struct hashmap *name_map,
13931467 const char *orig_name)
13941468 {
1469
+ char *old_name, *new_name;
13951470 size_t dup_cnt = 0;
1471
+ int err;
1472
+
1473
+ new_name = strdup(orig_name);
1474
+ if (!new_name)
1475
+ return 1;
13961476
13971477 hashmap__find(name_map, orig_name, (void **)&dup_cnt);
13981478 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);
14001486
14011487 return dup_cnt;
14021488 }