[PATCH 15/31] dwarf_loader: Fix --fixup_silly_bitfields condition check

Arnaldo Carvalho de Melo <[email protected]> Wed, 29 Jul 2026 16:07:15 -0300
Newsgroups org.kernel.vger.dwarves,org.kernel.vger.bpf
Message-ID <[email protected]>
From: Arnaldo Carvalho de Melo <[email protected]>

The condition for detecting silly bitfields (bitfields that use all bits
of their underlying type, e.g. "unsigned int x:32") was inverted since
commit 03d9b6ebcac7422f ("dwarf_loader: Fix bitfield fixup logic for
DWARF").

The check compared byte_size == 8 * bitfield_size, but byte_size is in
bytes and bitfield_size is in bits. For a "unsigned char val:8" silly
bitfield: byte_size=1, bitfield_size=8, so 1 == 8*8 = 64 was always
false.

Fix by multiplying byte_size by 8 to convert to bits before comparing:
byte_size * 8 == bitfield_size.

Before:
  $ pahole --fixup_silly_bitfields -C silly test.o
  unsigned int  reserved:32;   /* not fixed */
  unsigned char flags:8;       /* not fixed */

After:
  $ pahole --fixup_silly_bitfields -C silly test.o
  unsigned int  reserved;      /* fixed */
  unsigned char flags;         /* fixed */

Fixes: 03d9b6ebcac7422f ("dwarf_loader: Fix bitfield fixup logic for DWARF")
Cc: Andrii Nakryiko <[email protected]>
Reported-by: Sashiko:gemini-3-1-pro-preview
Assisted-by: Claude:claude-sonnet-4-5
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
 dwarf_loader.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/dwarf_loader.c b/dwarf_loader.c
index ddf7cdcfd467beb4..ce0bead0e76e1876 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -3798,10 +3798,14 @@ static int class_member__cache_byte_size(struct tag *tag, struct cu *cu,
 		member->byte_offset += member->byte_size;
 	}
 
+	/* A "silly" bitfield uses all bits of its underlying type
+	 * (e.g. unsigned char val:8).  Convert it to a plain field,
+	 * but only when byte-aligned — in packed structs a full-size
+	 * bitfield can start at a non-zero bit offset. */
 	if (conf_load && conf_load->fixup_silly_bitfields &&
-	    member->byte_size == 8 * member->bitfield_size) {
+	    member->byte_size * 8 == member->bitfield_size &&
+	    member->bitfield_offset == 0) {
 		member->bitfield_size = 0;
-		member->bitfield_offset = 0;
 	}
 
 	return 0;
-- 
2.55.0