Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -70,7 +70,7 @@ getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; void dump(raw_ostream &OS) const; - void parse() const; + Error parse() const; DWARFAbbreviationDeclarationSetMap::const_iterator begin() const { assert(!Data && "Must call parse before iterating over DWARFDebugAbbrev"); Index: llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp @@ -105,9 +105,9 @@ DWARFDebugAbbrev::DWARFDebugAbbrev(DataExtractor Data) : AbbrDeclSets(), PrevAbbrOffsetPos(AbbrDeclSets.end()), Data(Data) {} -void DWARFDebugAbbrev::parse() const { +Error DWARFDebugAbbrev::parse() const { if (!Data) - return; + return Error::success(); uint64_t Offset = 0; auto I = AbbrDeclSets.begin(); while (Data->isValidOffset(Offset)) { @@ -116,17 +116,19 @@ uint64_t CUAbbrOffset = Offset; DWARFAbbreviationDeclarationSet AbbrDecls; if (Error Err = AbbrDecls.extract(*Data, &Offset)) { - // FIXME: We should propagate the error upwards. - consumeError(std::move(Err)); - break; + Data = std::nullopt; + return Err; } AbbrDeclSets.insert(I, std::make_pair(CUAbbrOffset, std::move(AbbrDecls))); } Data = std::nullopt; + return Error::success(); } void DWARFDebugAbbrev::dump(raw_ostream &OS) const { - parse(); + if (Error Err = parse()) + // FIXME: We should propagate this error or otherwise display it. + llvm::consumeError(std::move(Err)); if (AbbrDeclSets.empty()) { OS << "< EMPTY >\n"; Index: llvm/tools/obj2yaml/dwarf2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/dwarf2yaml.cpp +++ llvm/tools/obj2yaml/dwarf2yaml.cpp @@ -22,11 +22,12 @@ using namespace llvm; -void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) { +Error dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) { auto AbbrevSetPtr = DCtx.getDebugAbbrev(); if (AbbrevSetPtr) { uint64_t AbbrevTableID = 0; - AbbrevSetPtr->parse(); + if (Error Err = AbbrevSetPtr->parse()) + return Err; for (auto AbbrvDeclSet : *AbbrevSetPtr) { Y.DebugAbbrev.emplace_back(); Y.DebugAbbrev.back().ID = AbbrevTableID++; @@ -48,6 +49,7 @@ } } } + return Error::success(); } Error dumpDebugAddr(DWARFContext &DCtx, DWARFYAML::Data &Y) { @@ -220,7 +222,12 @@ if (NewUnit.Version >= 5) NewUnit.Type = (dwarf::UnitType)CU->getUnitType(); const DWARFDebugAbbrev *DebugAbbrev = DCtx.getDebugAbbrev(); - DebugAbbrev->parse(); + // FIXME: Ideally we would propagate this error upwards, but that would + // prevent us from displaying any debug info at all. For now we just consume + // the error and display everything that was parsed successfully. + if (Error Err = DebugAbbrev->parse()) + llvm::consumeError(std::move(Err)); + NewUnit.AbbrevTableID = std::distance( DebugAbbrev->begin(), llvm::find_if( Index: llvm/tools/obj2yaml/macho2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/macho2yaml.cpp +++ llvm/tools/obj2yaml/macho2yaml.cpp @@ -139,10 +139,8 @@ static Error dumpDebugSection(StringRef SecName, DWARFContext &DCtx, DWARFYAML::Data &DWARF) { - if (SecName == "__debug_abbrev") { - dumpDebugAbbrev(DCtx, DWARF); - return Error::success(); - } + if (SecName == "__debug_abbrev") + return dumpDebugAbbrev(DCtx, DWARF); if (SecName == "__debug_aranges") return dumpDebugARanges(DCtx, DWARF); if (SecName == "__debug_info") { Index: llvm/tools/obj2yaml/obj2yaml.h =================================================================== --- llvm/tools/obj2yaml/obj2yaml.h +++ llvm/tools/obj2yaml/obj2yaml.h @@ -46,7 +46,7 @@ } } // namespace llvm -void dumpDebugAbbrev(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); +llvm::Error dumpDebugAbbrev(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); llvm::Error dumpDebugAddr(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); llvm::Error dumpDebugARanges(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); Index: llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp =================================================================== --- llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp +++ llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp @@ -412,3 +412,28 @@ "abbreviation declaration attribute list was not terminated with a " "null entry")); } + +TEST(DWARFDebugAbbrevTest, DWARFDebugAbbrevParseError) { + SmallString<64> RawData; + raw_svector_ostream OS(RawData); + const uint32_t FirstCode = 70; + // First, we're going to manually add good data. + writeValidAbbreviationDeclarations(OS, FirstCode, InOrder); + + // Afterwards, we're going to write an Abbreviation Decl manually without a + // termintating sequence. + encodeULEB128(FirstCode - 1, OS); + encodeULEB128(DW_TAG_compile_unit, OS); + OS << static_cast(DW_CHILDREN_no); + encodeULEB128(DW_AT_name, OS); + encodeULEB128(DW_FORM_strp, OS); + + // The specific error should percolate up to the DWARFDebugAbbrev::parse(). + DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t)); + DWARFDebugAbbrev DebugAbbrev(Data); + EXPECT_THAT_ERROR( + DebugAbbrev.parse(), + FailedWithMessage( + "abbreviation declaration attribute list was not terminated with a " + "null entry")); +}