diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -91,6 +91,9 @@ std::unique_ptr RegInfo; + std::function RecoverableErrorHandler = defaultErrorHandler; + std::function WarningHandler = defaultWarningHandler; + /// Read compile units from the debug_info section (if necessary) /// and type units from the debug_types sections (if necessary) /// and store them in NormalUnits. @@ -343,9 +346,19 @@ const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); } + function_ref getRecoverableErrorHandler() { + return RecoverableErrorHandler; + } + + function_ref getWarningHandler() { return WarningHandler; } + /// Function used to handle default error reporting policy. Prints a error /// message and returns Continue, so DWARF context ignores the error. static ErrorPolicy defaultErrorHandler(Error E); + + /// Dump Error as warning message to stderr. + static void defaultWarningHandler(Error Warning); + static std::unique_ptr create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, function_ref HandleError = defaultErrorHandler, @@ -364,9 +377,6 @@ /// TODO: refactor compile_units() to make this const. uint8_t getCUAddrSize(); - /// Dump Error as warning message to stderr. - static void dumpWarning(Error Warning); - Triple::ArchType getArch() const { return getDWARFObj().getFile()->getArch(); } diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -1545,9 +1545,10 @@ if (needToTranslateStrings()) return TheDwarfEmitter->translateLineTable(LineExtractor, StmtOffset); - Error Err = LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf, - &Unit.getOrigUnit(), DWARFContext::dumpWarning); - DWARFContext::dumpWarning(std::move(Err)); + if (Error Err = + LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf, + &Unit.getOrigUnit(), OrigDwarf.getWarningHandler())) + OrigDwarf.getWarningHandler()(std::move(Err)); // This vector is the output line table. std::vector NewRows; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -133,7 +133,8 @@ static void dumpDWARFv5StringOffsetsSection( raw_ostream &OS, StringRef SectionName, const DWARFObject &Obj, const DWARFSection &StringOffsetsSection, StringRef StringSection, - DWARFContext::unit_iterator_range Units, bool LittleEndian) { + DWARFContext::unit_iterator_range Units, bool LittleEndian, + function_ref RecoverableErrorHandler) { auto Contributions = collectContributionData(Units); DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0); DataExtractor StrData(StringSection, LittleEndian, 0); @@ -159,10 +160,10 @@ // Detect overlapping contributions. if (Offset > ContributionHeader) { - WithColor::error() - << "overlapping contributions to string offsets table in section ." - << SectionName << ".\n"; - return; + RecoverableErrorHandler(createStringError( + errc::invalid_argument, + "overlapping contributions to string offsets table in section .%s.", + SectionName.data())); } // Report a gap in the table. if (Offset < ContributionHeader) { @@ -204,18 +205,18 @@ // a header containing size and version number. Alternatively, it may be a // monolithic series of string offsets, as generated by the pre-DWARF v5 // implementation of split DWARF. -static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName, - const DWARFObject &Obj, - const DWARFSection &StringOffsetsSection, - StringRef StringSection, - DWARFContext::unit_iterator_range Units, - bool LittleEndian, unsigned MaxVersion) { +static void dumpStringOffsetsSection( + raw_ostream &OS, StringRef SectionName, const DWARFObject &Obj, + const DWARFSection &StringOffsetsSection, StringRef StringSection, + DWARFContext::unit_iterator_range Units, bool LittleEndian, + unsigned MaxVersion, function_ref RecoverableErrorHandler) { // If we have at least one (compile or type) unit with DWARF v5 or greater, // we assume that the section is formatted like a DWARF v5 string offsets // section. if (MaxVersion >= 5) dumpDWARFv5StringOffsetsSection(OS, SectionName, Obj, StringOffsetsSection, - StringSection, Units, LittleEndian); + StringSection, Units, LittleEndian, + RecoverableErrorHandler); else { DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0); uint64_t offset = 0; @@ -242,14 +243,16 @@ // Dump the .debug_addr section. static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, DIDumpOptions DumpOpts, uint16_t Version, - uint8_t AddrSize) { + uint8_t AddrSize, + function_ref RecoverableErrorHandler, + function_ref WarningHandler) { uint64_t Offset = 0; while (AddrData.isValidOffset(Offset)) { DWARFDebugAddrTable AddrTable; uint64_t TableOffset = Offset; if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize, - DWARFContext::dumpWarning)) { - WithColor::error() << toString(std::move(Err)) << '\n'; + WarningHandler)) { + RecoverableErrorHandler(std::move(Err)); // Keep going after an error, if we can, assuming that the length field // could be read. If it couldn't, stop reading the section. if (auto TableLength = AddrTable.getFullLength()) { @@ -267,13 +270,13 @@ raw_ostream &OS, DWARFDataExtractor &rnglistData, llvm::function_ref(uint32_t)> LookupPooledAddress, - DIDumpOptions DumpOpts) { + DIDumpOptions DumpOpts, function_ref RecoverableErrorHandler) { uint64_t Offset = 0; while (rnglistData.isValidOffset(Offset)) { llvm::DWARFDebugRnglistTable Rnglists; uint64_t TableOffset = Offset; if (Error Err = Rnglists.extract(rnglistData, &Offset)) { - WithColor::error() << toString(std::move(Err)) << '\n'; + RecoverableErrorHandler(std::move(Err)); uint64_t Length = Rnglists.length(); // Keep going after an error, if we can, assuming that the length field // could be read. If it couldn't, stop reading the section. @@ -286,17 +289,17 @@ } } -static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, - DWARFDataExtractor Data, - const MCRegisterInfo *MRI, - const DWARFObject &Obj, - Optional DumpOffset) { +static void +dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, + DWARFDataExtractor Data, const MCRegisterInfo *MRI, + const DWARFObject &Obj, Optional DumpOffset, + function_ref RecoverableErrorHandler) { uint64_t Offset = 0; while (Data.isValidOffset(Offset)) { DWARFListTableHeader Header(".debug_loclists", "locations"); if (Error E = Header.extract(Data, &Offset)) { - WithColor::error() << toString(std::move(E)) << '\n'; + RecoverableErrorHandler(std::move(E)); return; } @@ -403,14 +406,16 @@ DObj->getLoclistsSection().Data)) { DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(), 0); - dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off); + dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off, + RecoverableErrorHandler); } if (const auto *Off = shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists, DObj->getLoclistsDWOSection().Data)) { DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(), isLittleEndian(), 0); - dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off); + dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off, + RecoverableErrorHandler); } if (const auto *Off = @@ -456,7 +461,7 @@ DWARFDebugArangeSet set; while (arangesData.isValidOffset(offset)) { if (Error E = set.extract(arangesData, &offset)) { - WithColor::error() << toString(std::move(E)) << '\n'; + RecoverableErrorHandler(std::move(E)); break; } set.dump(OS); @@ -468,16 +473,16 @@ Optional DumpOffset) { while (!Parser.done()) { if (DumpOffset && Parser.getOffset() != *DumpOffset) { - Parser.skip(dumpWarning, dumpWarning); + Parser.skip(WarningHandler, WarningHandler); continue; } OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset()) << "]\n"; if (DumpOpts.Verbose) { - Parser.parseNext(dumpWarning, dumpWarning, &OS); + Parser.parseNext(WarningHandler, WarningHandler, &OS); } else { DWARFDebugLine::LineTable LineTable = - Parser.parseNext(dumpWarning, dumpWarning); + Parser.parseNext(WarningHandler, WarningHandler); LineTable.dump(OS, DumpOpts); } } @@ -549,7 +554,8 @@ DObj->getAddrSection().Data)) { DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(), isLittleEndian(), 0); - dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize()); + dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize(), + RecoverableErrorHandler, WarningHandler); } if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges, @@ -561,7 +567,7 @@ DWARFDebugRangeList rangeList; while (rangesData.isValidOffset(offset)) { if (Error E = rangeList.extract(rangesData, &offset)) { - WithColor::error() << toString(std::move(E)) << '\n'; + RecoverableErrorHandler(std::move(E)); break; } rangeList.dump(OS); @@ -580,14 +586,16 @@ DObj->getRnglistsSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(), isLittleEndian(), 0); - dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts); + dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts, + RecoverableErrorHandler); } if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists, DObj->getRnglistsDWOSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(), isLittleEndian(), 0); - dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts); + dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts, + RecoverableErrorHandler); } if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames, @@ -614,16 +622,16 @@ if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets, DObj->getStrOffsetsSection().Data)) - dumpStringOffsetsSection(OS, "debug_str_offsets", *DObj, - DObj->getStrOffsetsSection(), - DObj->getStrSection(), normal_units(), - isLittleEndian(), getMaxVersion()); + dumpStringOffsetsSection( + OS, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(), + DObj->getStrSection(), normal_units(), isLittleEndian(), + getMaxVersion(), RecoverableErrorHandler); if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets, DObj->getStrOffsetsDWOSection().Data)) - dumpStringOffsetsSection(OS, "debug_str_offsets.dwo", *DObj, - DObj->getStrOffsetsDWOSection(), - DObj->getStrDWOSection(), dwo_units(), - isLittleEndian(), getMaxDWOVersion()); + dumpStringOffsetsSection( + OS, "debug_str_offsets.dwo", *DObj, DObj->getStrOffsetsDWOSection(), + DObj->getStrDWOSection(), dwo_units(), isLittleEndian(), + getMaxDWOVersion(), RecoverableErrorHandler); if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex, DObj->getGdbIndexSection())) { @@ -871,9 +879,9 @@ const DWARFDebugLine::LineTable * DWARFContext::getLineTableForUnit(DWARFUnit *U) { Expected ExpectedLineTable = - getLineTableForUnit(U, dumpWarning); + getLineTableForUnit(U, WarningHandler); if (!ExpectedLineTable) { - dumpWarning(ExpectedLineTable.takeError()); + WarningHandler(ExpectedLineTable.takeError()); return nullptr; } return *ExpectedLineTable; @@ -1425,10 +1433,18 @@ } ErrorPolicy DWARFContext::defaultErrorHandler(Error E) { - WithColor::error() << toString(std::move(E)) << '\n'; + handleAllErrors(std::move(E), [](ErrorInfoBase &Info) { + WithColor::error() << Info.message() << '\n'; + }); return ErrorPolicy::Continue; } +void DWARFContext::defaultWarningHandler(Error Warning) { + handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { + WithColor::warning() << Info.message() << '\n'; + }); +} + namespace { struct DWARFSectionMap final : public DWARFSection { RelocAddrMap Relocs; @@ -1941,8 +1957,3 @@ return Addr; } -void DWARFContext::dumpWarning(Error Warning) { - handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { - WithColor::warning() << Info.message() << '\n'; - }); -}