[PATCH 07/31] dwarves: Don't search for holes before member byte sizes are cached
Arnaldo Carvalho de Melo <[email protected]> Wed, 29 Jul 2026 16:07:07 -0300
| Newsgroups | org.kernel.vger.dwarves,org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
From: Arnaldo Carvalho de Melo <[email protected]> cus__add() called cu__find_class_holes() which ran class__find_holes() on all structs before cu__finalize() had cached member byte_sizes via class_member__cache_byte_size(). In the merge path, cus__add() is called during the CU-processing loop, but cu__finalize() runs after the loop completes. With uncached byte_sizes (still 0), every member appeared zero-sized, producing phantom holes between contiguous members. The holes_searched flag then prevented re-computation when class__find_holes() was called again during printing. This caused 36 false "BRAIN FART ALERT!" warnings and phantom "XXX 8 bytes hole, try to pack" messages when processing Firefox debug info, all on Rust vtable/trait types where members are contiguous at 8-byte intervals. Before (Firefox, 152.0-1.fc44.x86_64): $ pahole -F dwarf firefox-*.debug 2>&1 | grep -c "BRAIN FART" 36 After: $ pahole -F dwarf firefox-*.debug 2>&1 | grep -c "BRAIN FART" 0 All consumers already call class__find_holes() lazily, guarded by the holes_searched flag, so the eager call in cus__add() was redundant. Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> --- codiff.c | 3 +++ ctracer.c | 1 + dwarves.c | 11 ----------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/codiff.c b/codiff.c index 9e5c56546c314231..72a2c4d720f7ac78 100644 --- a/codiff.c +++ b/codiff.c @@ -286,6 +286,9 @@ static void diff_struct(const struct cu *new_cu, struct class *structure, assert(class__is_struct(new_structure)); + class__find_holes(structure); + class__find_holes(new_structure); + diff = class__size(structure) != class__size(new_structure) || class__nr_members(structure) != class__nr_members(new_structure) || check_print_members_changes(structure, cu, diff --git a/ctracer.c b/ctracer.c index 6894766abc236b45..f3f7f937bb981a58 100644 --- a/ctracer.c +++ b/ctracer.c @@ -354,6 +354,7 @@ static struct class *class__clone_base_types(const struct tag *tag, if (clone == NULL) return NULL; + class__find_holes(clone); type__for_each_data_member_safe(&clone->type, pos, next) { struct tag *member_type = cu__type(cu, pos->tag.type); diff --git a/dwarves.c b/dwarves.c index 95a8dcd66f861be9..57a4bd063cc9413d 100644 --- a/dwarves.c +++ b/dwarves.c @@ -506,15 +506,6 @@ reevaluate: return result; } -static void cu__find_class_holes(struct cu *cu) -{ - uint32_t id; - struct class *pos; - - cu__for_each_struct(cu, id, pos) - class__find_holes(pos); -} - struct cus { uint32_t nr_entries; struct list_head cus; @@ -567,8 +558,6 @@ void cus__add(struct cus *cus, struct cu *cu) cus__lock(cus); __cus__add(cus, cu); cus__unlock(cus); - - cu__find_class_holes(cu); } static void ptr_table__init(struct ptr_table *pt) -- 2.55.0