diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h --- a/llvm/include/llvm/DebugInfo/DIContext.h +++ b/llvm/include/llvm/DebugInfo/DIContext.h @@ -204,6 +204,9 @@ Opts.ParentRecurseDepth = 0; return Opts; } + + std::function RecoverableErrorHandler = nullptr; + std::function WarningHandler = nullptr; }; class DIContext { 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 @@ -131,9 +131,10 @@ } static void dumpDWARFv5StringOffsetsSection( - raw_ostream &OS, StringRef SectionName, const DWARFObject &Obj, - const DWARFSection &StringOffsetsSection, StringRef StringSection, - DWARFContext::unit_iterator_range Units, bool LittleEndian) { + raw_ostream &OS, DIDumpOptions &DumpOpts, StringRef SectionName, + const DWARFObject &Obj, const DWARFSection &StringOffsetsSection, + StringRef StringSection, DWARFContext::unit_iterator_range Units, + bool LittleEndian) { 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; + DumpOpts.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,7 +205,8 @@ // 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, +static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions &DumpOpts, + StringRef SectionName, const DWARFObject &Obj, const DWARFSection &StringOffsetsSection, StringRef StringSection, @@ -214,8 +216,9 @@ // 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); + dumpDWARFv5StringOffsetsSection(OS, DumpOpts, SectionName, Obj, + StringOffsetsSection, StringSection, Units, + LittleEndian); else { DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0); uint64_t offset = 0; @@ -241,15 +244,15 @@ // Dump the .debug_addr section. static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, - DIDumpOptions DumpOpts, uint16_t Version, + DIDumpOptions &DumpOpts, uint16_t Version, uint8_t AddrSize) { 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'; + DumpOpts.WarningHandler)) { + DumpOpts.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) { 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'; + DumpOpts.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,7 +289,7 @@ } } -static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, +static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions &DumpOpts, DWARFDataExtractor Data, const MCRegisterInfo *MRI, const DWARFObject &Obj, @@ -296,7 +299,7 @@ while (Data.isValidOffset(Offset)) { DWARFListTableHeader Header(".debug_loclists", "locations"); if (Error E = Header.extract(Data, &Offset)) { - WithColor::error() << toString(std::move(E)) << '\n'; + DumpOpts.RecoverableErrorHandler(std::move(E)); return; } @@ -324,6 +327,12 @@ raw_ostream &OS, DIDumpOptions DumpOpts, std::array, DIDT_ID_Count> DumpOffsets) { + if (!DumpOpts.RecoverableErrorHandler) + DumpOpts.RecoverableErrorHandler = RecoverableErrorHandler; + + if (!DumpOpts.WarningHandler) + DumpOpts.WarningHandler = WarningHandler; + uint64_t DumpType = DumpOpts.DumpType; StringRef Extension = sys::path::extension(DObj->getFileName()); @@ -456,7 +465,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); @@ -464,20 +473,20 @@ } auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser, - DIDumpOptions DumpOpts, + DIDumpOptions &DumpOpts, Optional DumpOffset) { while (!Parser.done()) { if (DumpOffset && Parser.getOffset() != *DumpOffset) { - Parser.skip(dumpWarning, dumpWarning); + Parser.skip(DumpOpts.WarningHandler, DumpOpts.WarningHandler); continue; } OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset()) << "]\n"; if (DumpOpts.Verbose) { - Parser.parseNext(dumpWarning, dumpWarning, &OS); + Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS); } else { DWARFDebugLine::LineTable LineTable = - Parser.parseNext(dumpWarning, dumpWarning); + Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler); LineTable.dump(OS, DumpOpts); } } @@ -561,7 +570,7 @@ DWARFDebugRangeList rangeList; while (rangesData.isValidOffset(offset)) { if (Error E = rangeList.extract(rangesData, &offset)) { - WithColor::error() << toString(std::move(E)) << '\n'; + DumpOpts.RecoverableErrorHandler(std::move(E)); break; } rangeList.dump(OS); @@ -614,13 +623,13 @@ if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets, DObj->getStrOffsetsSection().Data)) - dumpStringOffsetsSection(OS, "debug_str_offsets", *DObj, + dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(), DObj->getStrSection(), normal_units(), isLittleEndian(), getMaxVersion()); if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets, DObj->getStrOffsetsDWOSection().Data)) - dumpStringOffsetsSection(OS, "debug_str_offsets.dwo", *DObj, + dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj, DObj->getStrOffsetsDWOSection(), DObj->getStrDWOSection(), dwo_units(), isLittleEndian(), getMaxDWOVersion()); @@ -871,9 +880,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 +1434,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 +1958,3 @@ return Addr; } -void DWARFContext::dumpWarning(Error Warning) { - handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { - WithColor::warning() << Info.message() << '\n'; - }); -}