diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -66,7 +66,7 @@ public: DWARFDebugAbbrev(DataExtractor Data); - const DWARFAbbreviationDeclarationSet * + Expected getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; void dump(raw_ostream &OS) const; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp @@ -139,32 +139,30 @@ } } -const DWARFAbbreviationDeclarationSet* +Expected DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const { const auto End = AbbrDeclSets.end(); if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) { - return &(PrevAbbrOffsetPos->second); + return &PrevAbbrOffsetPos->second; } const auto Pos = AbbrDeclSets.find(CUAbbrOffset); if (Pos != End) { PrevAbbrOffsetPos = Pos; - return &(Pos->second); + return &Pos->second; } - if (Data && CUAbbrOffset < Data->getData().size()) { - uint64_t Offset = CUAbbrOffset; - DWARFAbbreviationDeclarationSet AbbrDecls; - if (Error Err = AbbrDecls.extract(*Data, &Offset)) { - // FIXME: We should propagate the error upwards. - consumeError(std::move(Err)); - return nullptr; - } - PrevAbbrOffsetPos = - AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls))) - .first; - return &PrevAbbrOffsetPos->second; - } + if (!Data || CUAbbrOffset >= Data->getData().size()) + return make_error( + "the abbreviation offset into the .debug_abbrev section is not valid"); + + uint64_t Offset = CUAbbrOffset; + DWARFAbbreviationDeclarationSet AbbrDecls; + if (Error Err = AbbrDecls.extract(*Data, &Offset)) + return std::move(Err); - return nullptr; + PrevAbbrOffsetPos = + AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls))) + .first; + return &PrevAbbrOffsetPos->second; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -1040,8 +1040,16 @@ } const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { - if (!Abbrevs) - Abbrevs = Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset()); + if (!Abbrevs) { + Expected AbbrevsOrError = + Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset()); + if (!AbbrevsOrError) { + // FIXME: We should propagate this error upwards. + consumeError(AbbrevsOrError.takeError()); + return nullptr; + } + Abbrevs = *AbbrevsOrError; + } return Abbrevs; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -150,8 +150,15 @@ AddrSize = DebugInfoData.getU8(Offset); } - if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset)) + Expected AbbrevSetOrErr = + DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset); + if (!AbbrevSetOrErr) { ValidAbbrevOffset = false; + // FIXME: A problematic debug_abbrev section is reported below in the form + // of a `note:`. We should propagate this error there (or elsewhere) to + // avoid losing the specific problem with the debug_abbrev section. + consumeError(AbbrevSetOrErr.takeError()); + } ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3); ValidVersion = DWARFContext::isSupportedVersion(Version); @@ -302,14 +309,14 @@ if (!Abbrev) return 0; - const DWARFAbbreviationDeclarationSet *AbbrDecls = + Expected AbbrDeclsOrErr = Abbrev->getAbbreviationDeclarationSet(0); - // FIXME: If we failed to get a DWARFAbbreviationDeclarationSet, it's possible - // that there are errors. We need to propagate the error from - // getAbbreviationDeclarationSet. - if (!AbbrDecls) - return 0; + if (!AbbrDeclsOrErr) { + error() << toString(AbbrDeclsOrErr.takeError()) << "\n"; + return 1; + } + const auto *AbbrDecls = *AbbrDeclsOrErr; unsigned NumErrors = 0; for (auto AbbrDecl : *AbbrDecls) { SmallDenseSet AttributeSet; diff --git a/llvm/test/tools/llvm-dwarfdump/X86/empty-CU.s b/llvm/test/tools/llvm-dwarfdump/X86/empty-CU.s --- a/llvm/test/tools/llvm-dwarfdump/X86/empty-CU.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/empty-CU.s @@ -1,6 +1,7 @@ # RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \ # RUN: | not llvm-dwarfdump --verify --debug-info - \ # RUN: | FileCheck %s +# CHECK: error: unable to decode LEB128 at offset 0x00000005: malformed uleb128, extends past end # CHECK: error: Compilation unit without DIE. .section __DWARF,__debug_info,regular,debug @@ -17,5 +18,6 @@ .byte 1 # Abbrev code .byte 0x11 # TAG_compile_unit .byte 0 # no children -.byte 0 # no attributes -.byte 0 +.byte 0 # EOM(1) +.byte 0 # EOM(2) + # Intentionally missing EOM(3)