llvm-dwp could spin forever (100% CPU, never terminating) when packaging
a
DWARFv5 .dwo whose abbreviation table uses DW_FORM_implicit_const.
A DWARF abbreviation declaration is a list of (attribute, form) ULEB128
pairs terminated by a (0, 0) pair. DW_FORM_implicit_const is the only
form
that stores an additional value -- an SLEB128 constant -- in the
abbreviation declaration itself (the value is not present in
.debug_info).
getCUAbbrev() and getCUIdentifiers() in llvm/lib/DWP/DWP.cpp walked
these
pairs but never consumed that extra SLEB128, so every implicit_const
entry
shifted the cursor by one ULEB and desynced the rest of the table walk.
With enough implicit_const attributes preceding the compile unit's
abbreviation code, the scan in getCUAbbrev() runs off the end of
.debug_abbrev without ever matching the code. Past end-of-buffer
DataExtractor::getULEB128 returns 0 without advancing the offset, so the
loop `while (getULEB128(&Offset) != AbbrCode)` spins on `0 != AbbrCode`
forever. The input is valid DWARFv5; the bug is entirely in llvm-dwp.
Consume the implicit_const SLEB128 in both abbreviation-walk loops so
the
(attribute, form) walk stays aligned, matching how
DWARFAbbreviationDeclaration::extract parses the same data.
Adds a regression test that hangs before this change and passes after
it.
AI assisted with: claude