From: Andrii Nakryiko <andriin@xxxxxx> This patch fixes a bug in class__find_holes() with determining byte hole as a bit hole in case where previous member is not bitfield, but current one is aligned bitfield. See example below, notice hole classification hw_stopped field.. $ cat test/bit_test.c struct s { long unused: 62; /* 2 bit hole */ int hw_stopped; /* 4 byte hole */ long unused2: 55; /* 9 bit padding */ }; int main() { static struct s s; return 0; } $ clang -g test/bit_test.c -o test/bit_test $ pahole -JV test/bit_test File test/bit_test: [1] STRUCT s kind_flag=1 size=24 vlen=3 unused type_id=2 bitfield_size=62 bits_offset=0 hw_stopped type_id=3 bitfield_size=0 bits_offset=64 unused2 type_id=2 bitfield_size=55 bits_offset=128 [2] INT long int size=8 bit_offset=0 nr_bits=64 encoding=SIGNED [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED BEFORE: $ pahole -F btf test/bit_test struct s { long int unused:62; /* 0: 0 8 */ /* XXX 2 bits hole, try to pack */ int hw_stopped; /* 8 4 */ /* XXX 32 bits hole, try to pack */ long int unused2:55; /* 16: 0 8 */ /* size: 24, cachelines: 1, members: 3 */ /* sum members: 4 */ /* sum bitfield members: 117 bits, bit holes: 2, sum bit holes: 34 bits */ /* bit_padding: 9 bits */ /* last cacheline: 24 bytes */ }; AFTER: $ pahole -F btf test/bit_test struct s { long int unused:62; /* 0: 0 8 */ /* XXX 2 bits hole, try to pack */ int hw_stopped; /* 8 4 */ /* XXX 4 bytes hole, try to pack */ long int unused2:55; /* 16: 0 8 */ /* size: 24, cachelines: 1, members: 3 */ /* sum members: 4, holes: 1, sum holes: 4 */ /* sum bitfield members: 117 bits, bit holes: 1, sum bit holes: 2 bits */ /* bit_padding: 9 bits */ /* last cacheline: 24 bytes */ }; Signed-off-by: Andrii Nakryiko <andriin@xxxxxx> --- dwarves.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwarves.c b/dwarves.c index efa58a9..5be50b0 100644 --- a/dwarves.c +++ b/dwarves.c @@ -1223,9 +1223,9 @@ void class__find_holes(struct class *class) if (pos->bitfield_size) { int aligned_start = pos->byte_offset * 8; /* we can have some alignment byte padding left, - * but we need to be carful about bitfield spanning + * but we need to be careful about bitfield spanning * multiple aligned boundaries */ - if (last_seen_bit < aligned_start && aligned_start < bit_start) { + if (last_seen_bit < aligned_start && aligned_start <= bit_start) { byte_holes = pos->byte_offset - last_seen_bit / 8; last_seen_bit = aligned_start; } -- 2.17.1