[PATCH pahole v2] dwarves_fprintf: count bitfield member sizes separately

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Andrii Nakryiko <andriin@xxxxxx>

Counting field sizes only in bits causes confusion and lots of differing
output, when compared to previous logic. This commit changes logic so
that it counts bit size of bitfield fields separately from byte size of
non-bitfield fields. In the end, if there were bit holes, this bit size
is emitted explicitly. This makes output for struct/unions not using
bitfields identical, while also preserving correctness (and data
completeness) for cases with bitfields and bit holes.

Example (-before/+after):
 struct cfg80211_pmsr_request_peer {
        u8                         addr[6];              /*     0     6 */

        /* XXX 2 bytes hole, try to pack */

        struct cfg80211_chan_def   chandef;              /*     8    24 */

        /* XXX last struct has 4 bytes of padding */

        u8                         report_ap_tsf:1;      /*    32: 0  1 */

        /* XXX 7 bits hole, try to pack */
        /* XXX 3 bytes hole, try to pack */

        struct cfg80211_pmsr_ftm_request_peer ftm;       /*    36    12 */

        /* XXX last struct has 1 byte of padding */

        /* size: 48, cachelines: 1, members: 4 */
-       /* sum members: 43, holes: 2, sum holes: 5 */
-       /* bit holes: 1, sum bit holes: 7 bits */
+       /* sum members: 42, holes: 2, sum holes: 5 */
+       /* sum bitfield members: 1 bits, bit holes: 1, sum bit holes: 7 bits */
        /* paddings: 2, sum paddings: 5 */
        /* last cacheline: 48 bytes */
 };

For cases where there is only byte or bit hole, we still emit total byte and
bit sizes of all members as to not mislead user:
 struct sched_dl_entity {
... <snip ...
        unsigned int               dl_non_contending:1;  /*    84: 3  4 */
        unsigned int               dl_overrun:1;         /*    84: 4  4 */

        /* XXX 27 bits hole, try to pack */

        struct hrtimer             dl_timer;             /*    88    64 */

        /* XXX last struct has 5 bytes of padding */

        /* --- cacheline 2 boundary (128 bytes) was 24 bytes ago --- */
        struct hrtimer             inactive_timer;       /*   152    64 */

        /* XXX last struct has 5 bytes of padding */

        /* size: 216, cachelines: 4, members: 16 */
-       /* bit holes: 1, sum bit holes: 27 bits */
+       /* sum members: 212 */
+       /* sum bitfield members: 5 bits, bit holes: 1, sum bit holes: 27 bits */
        /* paddings: 2, sum paddings: 10 */
        /* last cacheline: 24 bytes */
 };

For structs with tightly packed bitfield, we emit total number of bits and also
convert them to bytes. E.g., for struct sock output :
struct sock {
... <snip ...
        /* size: 720, cachelines: 12, members: 84 */
-       /* sum members: 712, holes: 4, sum holes: 8 */
+       /* sum members: 707, holes: 4, sum holes: 8 */
+       /* sum bitfield members: 40 bits (5 bytes) */
        /* paddings: 1, sum paddings: 4 */
        /* last cacheline: 16 bytes */
 };

Suggested-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Signed-off-by: Andrii Nakryiko <andriin@xxxxxx>
---
 dwarves_fprintf.c | 45 ++++++++++++++++++++++++++++++---------------
 1 file changed, 30 insertions(+), 15 deletions(-)

diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
index 4a9b26c..faae3ba 100644
--- a/dwarves_fprintf.c
+++ b/dwarves_fprintf.c
@@ -1228,7 +1228,7 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
 	size_t last_size = 0, size;
 	uint8_t newline = 0;
 	uint16_t nr_paddings = 0;
-	uint32_t sum = 0;
+	uint32_t sum_bytes = 0, sum_bits = 0;
 	uint32_t sum_holes = 0;
 	uint32_t sum_paddings = 0;
 	uint32_t sum_bit_holes = 0;
@@ -1444,7 +1444,11 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
 			continue;
 #endif
 
-		sum += pos->bitfield_size ? pos->bitfield_size : pos->bit_size;
+		if (pos->bitfield_size) {
+			sum_bits += pos->bitfield_size;
+		} else {
+			sum_bytes += pos->byte_size;
+		}
 
 		if (last == NULL || /* First member */
 		    /*
@@ -1486,16 +1490,26 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
 
 	printed += type__fprintf_stats(type, cu, &cconf, fp);
 
-	if (sum_holes > 0)
-		printed += fprintf(fp, "%.*s/* sum members (bits): %u, holes: %d, "
-				   "sum holes: %u */\n",
-				   cconf.indent, tabs,
-				   sum, class->nr_holes, sum_holes);
-	if (sum_bit_holes > 0)
-		printed += fprintf(fp, "%.*s/* bit holes: %d, sum bit "
-				   "holes: %u bits */\n",
-				   cconf.indent, tabs,
-				   class->nr_bit_holes, sum_bit_holes);
+	if (sum_holes > 0 || sum_bit_holes > 0) {
+		if (sum_bytes > 0) {
+			printed += fprintf(fp, "%.*s/* sum members: %u",
+					   cconf.indent, tabs, sum_bytes);
+			if (sum_holes > 0)
+				printed += fprintf(fp, ", holes: %d, sum holes: %u",
+						   class->nr_holes, sum_holes);
+			printed += fprintf(fp, " */\n");
+		}
+		if (sum_bits > 0) {
+			printed += fprintf(fp, "%.*s/* sum bitfield members: %u bits",
+					   cconf.indent, tabs, sum_bits);
+			if (sum_bit_holes > 0)
+				printed += fprintf(fp, ", bit holes: %d, sum bit holes: %u bits",
+						   class->nr_bit_holes, sum_bit_holes);
+			else
+				printed += fprintf(fp, " (%u bytes)", sum_bits / 8);
+			printed += fprintf(fp, " */\n");
+		}
+	}
 	if (class->padding > 0)
 		printed += fprintf(fp, "%.*s/* padding: %u */\n",
 				   cconf.indent,
@@ -1524,13 +1538,14 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
 				   m->byte_size);
 	}
 
-	size_diff = type->size * 8 - (sum + sum_holes * 8 + sum_bit_holes +
+	size_diff = type->size * 8 - (sum_bytes * 8 + sum_bits + sum_holes * 8 + sum_bit_holes +
 				      class->padding * 8 + class->bit_padding);
 	if (size_diff && type->nr_members != 0)
-		printed += fprintf(fp, "\n%.*s/* BRAIN FART ALERT! %d bytes != %u (member bits) "
+		printed += fprintf(fp, "\n%.*s/* BRAIN FART ALERT! %d bytes != "
+				   "%u (member bytes) + %u (member bits) "
 				   "+ %u (byte holes) + %u (bit holes), diff = %d bits */\n",
 				   cconf.indent, tabs,
-				   type->size, sum, sum_holes, sum_bit_holes, size_diff);
+				   type->size, sum_bytes, sum_bits, sum_holes, sum_bit_holes, size_diff);
 out:
 	return printed + fprintf(fp, "%.*s}%s%s", indent, tabs,
 				 cconf.suffix ? " ": "", cconf.suffix ?: "");
-- 
2.17.1




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux