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,11 @@ std::unique_ptr RegInfo; + std::function RecoverableErrorHandler = [](Error E) { + defaultErrorHandler(std::move(E)); + }; + 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. @@ -295,10 +300,10 @@ const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U); /// Get a pointer to a parsed line table corresponding to a compile unit. - /// Report any recoverable parsing problems using the callback. + /// Report any recoverable parsing problems using the error handler. Expected getLineTableForUnit(DWARFUnit *U, - function_ref RecoverableErrorCallback); + function_ref RecoverableErrorHandler); DataExtractor getStringExtractor() const { return DataExtractor(DObj->getStrSection(), false, 0); @@ -343,9 +348,26 @@ const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); } + void setRecoverableErrorHandler(std::function Handler) { + assert(Handler); + RecoverableErrorHandler = Handler; + }; + std::function getRecoverableErrorHandler() { + return RecoverableErrorHandler; + } + void setWarningHandler(std::function Handler) { + assert(Handler); + WarningHandler = Handler; + }; + std::function 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 +386,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/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h @@ -25,7 +25,8 @@ private: void clear(); - void extract(DataExtractor DebugArangesData); + void extract(DataExtractor DebugArangesData, + function_ref RecoverableErrorHandler); /// Call appendRange multiple times and then call construct. void appendRange(uint64_t CUOffset, uint64_t LowPC, uint64_t HighPC); diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -130,7 +130,7 @@ void clear(); void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; Error parse(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, - function_ref RecoverableErrorCallback, + function_ref RecoverableErrorHandler, const DWARFContext &Ctx, const DWARFUnit *U = nullptr); }; @@ -275,7 +275,7 @@ /// Parse prologue and all rows. Error parse(DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, const DWARFContext &Ctx, const DWARFUnit *U, - function_ref RecoverableErrorCallback, + function_ref RecoverableErrorHandler, raw_ostream *OS = nullptr); using RowVector = std::vector; @@ -304,7 +304,7 @@ Expected getOrParseLineTable(DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx, const DWARFUnit *U, - function_ref RecoverableErrorCallback); + function_ref RecoverableErrorHandler); /// Helper to allow for parsing of an entire .debug_line section in sequence. class SectionParser { @@ -317,29 +317,27 @@ tu_range TUs); /// Get the next line table from the section. Report any issues via the - /// callbacks. + /// handlers. /// - /// \param RecoverableErrorCallback - any issues that don't prevent further - /// parsing of the table will be reported through this callback. - /// \param UnrecoverableErrorCallback - any issues that prevent further - /// parsing of the table will be reported through this callback. + /// \param RecoverableErrorHandler - any issues that don't prevent further + /// parsing of the table will be reported through this handler. + /// \param UnrecoverableErrorHandler - any issues that prevent further + /// parsing of the table will be reported through this handler. /// \param OS - if not null, the parser will print information about the /// table as it parses it. - LineTable - parseNext( - function_ref RecoverableErrorCallback, - function_ref UnrecoverableErrorCallback, - raw_ostream *OS = nullptr); + LineTable parseNext(function_ref RecoverableErrorHandler, + function_ref UnrecoverableErrorHandler, + raw_ostream *OS = nullptr); /// Skip the current line table and go to the following line table (if /// present) immediately. /// - /// \param RecoverableErrorCallback - report any recoverable prologue - /// parsing issues via this callback. - /// \param UnrecoverableErrorCallback - report any unrecoverable prologue - /// parsing issues via this callback. - void skip(function_ref RecoverableErrorCallback, - function_ref UnrecoverableErrorCallback); + /// \param RecoverableErrorHandler - report any recoverable prologue + /// parsing issues via this handler. + /// \param UnrecoverableErrorHandler - report any unrecoverable prologue + /// parsing issues via this handler. + void skip(function_ref RecoverableErrorHandler, + function_ref UnrecoverableErrorHandler); /// Indicates if the parser has parsed as much as possible. /// diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -124,7 +124,8 @@ /// /// \param OS the stream to use for output. /// \param indent the number of characters to indent each line that is output. - void dump(raw_ostream &OS, unsigned indent = 0, + void dump(raw_ostream &OS, function_ref ErrorHandler, + unsigned indent = 0, DIDumpOptions DumpOpts = DIDumpOptions()) const; /// Convenience zero-argument overload for debugging. 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 @@ -357,7 +357,9 @@ DIDumpOptions DumpOpts; DumpOpts.ChildRecurseDepth = 0; DumpOpts.Verbose = Options.Verbose; - DIE.dump(outs(), 8 /* Indent */, DumpOpts); + DIE.dump(outs(), + Unit.getOrigUnit().getContext().getRecoverableErrorHandler(), + 8 /* Indent */, DumpOpts); } return Flags | TF_Keep; @@ -394,7 +396,8 @@ DIDumpOptions DumpOpts; DumpOpts.ChildRecurseDepth = 0; DumpOpts.Verbose = Options.Verbose; - DIE.dump(outs(), 8 /* Indent */, DumpOpts); + DIE.dump(outs(), OrigUnit.getContext().getRecoverableErrorHandler(), + 8 /* Indent */, DumpOpts); } if (DIE.getTag() == dwarf::DW_TAG_label) { @@ -1545,9 +1548,10 @@ if (needToTranslateStrings()) return TheDwarfEmitter->translateLineTable(LineExtractor, StmtOffset); - Error Err = LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf, - &Unit.getOrigUnit(), DWARFContext::dumpWarning); - DWARFContext::dumpWarning(std::move(Err)); + Error Err = + LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf, + &Unit.getOrigUnit(), DWARFContext::defaultWarningHandler); + DWARFContext::defaultWarningHandler(std::move(Err)); // This vector is the output line table. std::vector NewRows; @@ -2266,7 +2270,9 @@ DIDumpOptions DumpOpts; DumpOpts.ChildRecurseDepth = 0; DumpOpts.Verbose = Options.Verbose; - CUDie.dump(outs(), 0, DumpOpts); + CUDie.dump(outs(), + OptContext.DwarfContext->getRecoverableErrorHandler(), 0, + DumpOpts); } if (CUDie && !LLVM_UNLIKELY(Options.Update)) registerModuleReference(CUDie, *CU, OptContext.ObjectFile, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/Support/Format.h" @@ -29,7 +30,7 @@ << ")\n"; if (DWARFDie CUDie = getUnitDIE(false)) - CUDie.dump(OS, 0, DumpOpts); + CUDie.dump(OS, getContext().getRecoverableErrorHandler(), 0, DumpOpts); else OS << "\n\n"; } 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,9 +160,10 @@ // Detect overlapping contributions. if (Offset > ContributionHeader) { - WithColor::error() - << "overlapping contributions to string offsets table in section ." - << SectionName << ".\n"; + RecoverableErrorHandler(createStringError( + errc::invalid_argument, + "overlapping contributions to string offsets table in section .%s.", + SectionName.data())); return; } // Report a gap in the table. @@ -204,18 +206,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 +244,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 (!AddrTable.hasValidLength()) @@ -266,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. @@ -285,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; } @@ -361,7 +365,8 @@ if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo]) for (const auto &U : Units) U->getDIEForOffset(DumpOffset.getValue()) - .dump(OS, 0, DumpOpts.noImplicitRecursion()); + .dump(OS, RecoverableErrorHandler, 0, + DumpOpts.noImplicitRecursion()); else for (const auto &U : Units) U->dump(OS, DumpOpts); @@ -378,7 +383,8 @@ for (const auto &U : Units) if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes]) U->getDIEForOffset(*DumpOffset) - .dump(OS, 0, DumpOpts.noImplicitRecursion()); + .dump(OS, RecoverableErrorHandler, 0, + DumpOpts.noImplicitRecursion()); else U->dump(OS, DumpOpts); }; @@ -402,14 +408,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 = @@ -455,7 +463,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); @@ -467,16 +475,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); } } @@ -548,7 +556,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, @@ -560,7 +569,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); @@ -579,14 +588,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, @@ -613,16 +624,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())) { @@ -870,16 +881,16 @@ 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; } Expected DWARFContext::getLineTableForUnit( - DWARFUnit *U, function_ref RecoverableErrorCallback) { + DWARFUnit *U, function_ref RecoverableErrorHandler) { if (!Line) Line.reset(new DWARFDebugLine); @@ -904,7 +915,7 @@ DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(), U->getAddressByteSize()); return Line->getOrParseLineTable(lineData, stmtOffset, *this, U, - RecoverableErrorCallback); + RecoverableErrorHandler); } void DWARFContext::parseNormalUnits() { @@ -1424,10 +1435,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; @@ -1940,8 +1959,3 @@ return Addr; } -void DWARFContext::dumpWarning(Error Warning) { - handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { - WithColor::warning() << Info.message() << '\n'; - }); -} diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -11,7 +11,6 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" #include "llvm/Support/DataExtractor.h" -#include "llvm/Support/WithColor.h" #include #include #include @@ -20,7 +19,9 @@ using namespace llvm; -void DWARFDebugAranges::extract(DataExtractor DebugArangesData) { +void DWARFDebugAranges::extract( + DataExtractor DebugArangesData, + function_ref RecoverableErrorHandler) { if (!DebugArangesData.isValidOffset(0)) return; uint64_t Offset = 0; @@ -28,7 +29,7 @@ while (DebugArangesData.isValidOffset(Offset)) { if (Error E = Set.extract(DebugArangesData, &Offset)) { - WithColor::error() << toString(std::move(E)) << '\n'; + RecoverableErrorHandler(std::move(E)); return; } uint64_t CUOffset = Set.getCompileUnitDIEOffset(); @@ -49,7 +50,7 @@ // Extract aranges from .debug_aranges section. DataExtractor ArangesData(CTX->getDWARFObj().getArangesSection(), CTX->isLittleEndian(), 0); - extract(ArangesData); + extract(ArangesData, CTX->getRecoverableErrorHandler()); // Generate aranges from DIEs: even if .debug_aranges section is present, // it may describe only a small subset of compilation units, so we need to @@ -59,7 +60,7 @@ if (ParsedCUOffsets.insert(CUOffset).second) { Expected CURanges = CU->collectAddressRanges(); if (!CURanges) - WithColor::error() << toString(CURanges.takeError()) << '\n'; + CTX->getRecoverableErrorHandler()(CURanges.takeError()); else for (const auto &R : *CURanges) appendRange(CUOffset, R.LowPC, R.HighPC); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -17,7 +17,6 @@ #include "llvm/Support/Errc.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -309,7 +308,7 @@ Error DWARFDebugLine::Prologue::parse( const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, - function_ref RecoverableErrorCallback, const DWARFContext &Ctx, + function_ref RecoverableErrorHandler, const DWARFContext &Ctx, const DWARFUnit *U) { const uint64_t PrologueOffset = *OffsetPtr; @@ -365,7 +364,7 @@ if (Error E = parseV5DirFileTables(DebugLineData, OffsetPtr, FormParams, Ctx, U, ContentTypes, IncludeDirectories, FileNames)) { - RecoverableErrorCallback(joinErrors( + RecoverableErrorHandler(joinErrors( createStringError( errc::invalid_argument, "parsing line table prologue at 0x%8.8" PRIx64 @@ -384,7 +383,7 @@ ContentTypes, IncludeDirectories, FileNames); if (*OffsetPtr != EndPrologueOffset) { - RecoverableErrorCallback(createStringError( + RecoverableErrorHandler(createStringError( errc::invalid_argument, "parsing line table prologue at 0x%8.8" PRIx64 " should have ended at 0x%8.8" PRIx64 " but it ended at 0x%8.8" PRIx64, @@ -510,7 +509,7 @@ Expected DWARFDebugLine::getOrParseLineTable( DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx, - const DWARFUnit *U, function_ref RecoverableErrorCallback) { + const DWARFUnit *U, function_ref RecoverableErrorHandler) { if (!DebugLineData.isValidOffset(Offset)) return createStringError(errc::invalid_argument, "offset 0x%8.8" PRIx64 " is not a valid debug line section offset", @@ -521,7 +520,7 @@ LineTable *LT = &Pos.first->second; if (Pos.second) { if (Error Err = - LT->parse(DebugLineData, &Offset, Ctx, U, RecoverableErrorCallback)) + LT->parse(DebugLineData, &Offset, Ctx, U, RecoverableErrorHandler)) return std::move(Err); return LT; } @@ -531,13 +530,13 @@ Error DWARFDebugLine::LineTable::parse( DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, const DWARFContext &Ctx, const DWARFUnit *U, - function_ref RecoverableErrorCallback, raw_ostream *OS) { + function_ref RecoverableErrorHandler, raw_ostream *OS) { const uint64_t DebugLineOffset = *OffsetPtr; clear(); - Error PrologueErr = Prologue.parse(DebugLineData, OffsetPtr, - RecoverableErrorCallback, Ctx, U); + Error PrologueErr = + Prologue.parse(DebugLineData, OffsetPtr, RecoverableErrorHandler, Ctx, U); if (OS) { // The presence of OS signals verbose dumping. @@ -555,7 +554,7 @@ assert(DebugLineData.size() > DebugLineOffset && "prologue parsing should handle invalid offset"); uint64_t BytesRemaining = DebugLineData.size() - DebugLineOffset; - RecoverableErrorCallback( + RecoverableErrorHandler( createStringError(errc::invalid_argument, "line table program with offset 0x%8.8" PRIx64 " has length 0x%8.8" PRIx64 " but only 0x%8.8" PRIx64 @@ -633,7 +632,7 @@ { uint8_t ExtractorAddressSize = DebugLineData.getAddressSize(); if (ExtractorAddressSize != Len - 1 && ExtractorAddressSize != 0) - RecoverableErrorCallback(createStringError( + RecoverableErrorHandler(createStringError( errc::invalid_argument, "mismatching address size at offset 0x%8.8" PRIx64 " expected 0x%2.2" PRIx8 " found 0x%2.2" PRIx64, @@ -711,7 +710,7 @@ // by the table. uint64_t End = ExtOffset + Len; if (*OffsetPtr != End) { - RecoverableErrorCallback(createStringError( + RecoverableErrorHandler(createStringError( errc::illegal_byte_sequence, "unexpected line op length at offset 0x%8.8" PRIx64 " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx64, @@ -918,7 +917,7 @@ } if (!State.Sequence.Empty) - RecoverableErrorCallback(createStringError( + RecoverableErrorHandler(createStringError( errc::illegal_byte_sequence, "last sequence in debug line table at offset 0x%8.8" PRIx64 " is not terminated", @@ -1163,31 +1162,31 @@ } DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext( - function_ref RecoverableErrorCallback, - function_ref UnrecoverableErrorCallback, raw_ostream *OS) { + function_ref RecoverableErrorHandler, + function_ref UnrecoverableErrorHandler, raw_ostream *OS) { assert(DebugLineData.isValidOffset(Offset) && "parsing should have terminated"); DWARFUnit *U = prepareToParse(Offset); uint64_t OldOffset = Offset; LineTable LT; if (Error Err = LT.parse(DebugLineData, &Offset, Context, U, - RecoverableErrorCallback, OS)) - UnrecoverableErrorCallback(std::move(Err)); + RecoverableErrorHandler, OS)) + UnrecoverableErrorHandler(std::move(Err)); moveToNextTable(OldOffset, LT.Prologue); return LT; } void DWARFDebugLine::SectionParser::skip( - function_ref RecoverableErrorCallback, - function_ref UnrecoverableErrorCallback) { + function_ref RecoverableErrorHandler, + function_ref UnrecoverableErrorHandler) { assert(DebugLineData.isValidOffset(Offset) && "parsing should have terminated"); DWARFUnit *U = prepareToParse(Offset); uint64_t OldOffset = Offset; LineTable LT; if (Error Err = LT.Prologue.parse(DebugLineData, &Offset, - RecoverableErrorCallback, Context, U)) - UnrecoverableErrorCallback(std::move(Err)); + RecoverableErrorHandler, Context, U)) + UnrecoverableErrorHandler(std::move(Err)); moveToNextTable(OldOffset, LT.Prologue); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -15,7 +15,6 @@ #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Format.h" -#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include #include diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -232,7 +232,8 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, uint64_t *OffsetPtr, dwarf::Attribute Attr, dwarf::Form Form, unsigned Indent, - DIDumpOptions DumpOpts) { + DIDumpOptions DumpOpts, + function_ref ErrorHandler) { if (!Die.isValid()) return; const char BaseIndent[] = " "; @@ -315,9 +316,11 @@ if (auto RangesOrError = Die.getAddressRanges()) dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(), sizeof(BaseIndent) + Indent + 4, DumpOpts); - else - WithColor::error() << "decoding address ranges: " - << toString(RangesOrError.takeError()) << '\n'; + else { + ErrorHandler(createStringError( + errc::invalid_argument, "decoding address ranges: %s", + toString(RangesOrError.takeError()).c_str())); + } } OS << ")\n"; @@ -554,19 +557,22 @@ } /// Helper to dump a DIE with all of its parents, but no siblings. -static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, - DIDumpOptions DumpOpts, unsigned Depth = 0) { +static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, + function_ref ErrorHandler, + unsigned Indent, DIDumpOptions DumpOpts, + unsigned Depth = 0) { if (!Die) return Indent; if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth) return Indent; - Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1); - Die.dump(OS, Indent, DumpOpts); + Indent = dumpParentChain(Die.getParent(), OS, ErrorHandler, Indent, DumpOpts, + Depth + 1); + Die.dump(OS, ErrorHandler, Indent, DumpOpts); return Indent + 2; } -void DWARFDie::dump(raw_ostream &OS, unsigned Indent, - DIDumpOptions DumpOpts) const { +void DWARFDie::dump(raw_ostream &OS, function_ref ErrorHandler, + unsigned Indent, DIDumpOptions DumpOpts) const { if (!isValid()) return; DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); @@ -576,7 +582,8 @@ DIDumpOptions ParentDumpOpts = DumpOpts; ParentDumpOpts.ShowParents = false; ParentDumpOpts.ShowChildren = false; - Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts); + Indent = + dumpParentChain(getParent(), OS, ErrorHandler, Indent, ParentDumpOpts); } if (debug_info_data.isValidOffset(offset)) { @@ -604,7 +611,7 @@ continue; } dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, - Indent, DumpOpts); + Indent, DumpOpts, ErrorHandler); } DWARFDie child = getFirstChild(); @@ -613,7 +620,7 @@ DIDumpOptions ChildDumpOpts = DumpOpts; ChildDumpOpts.ShowParents = false; while (child) { - child.dump(OS, Indent + 2, ChildDumpOpts); + child.dump(OS, ErrorHandler, Indent + 2, ChildDumpOpts); child = child.getSibling(); } } @@ -627,7 +634,13 @@ } } -LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); } +static void defaultErrorHandler(Error E) { + WithColor::error() << toString(std::move(E)) << '\n'; +} + +LLVM_DUMP_METHOD void DWARFDie::dump() const { + dump(llvm::errs(), defaultErrorHandler, 0); +} DWARFDie DWARFDie::getParent() const { if (isValid()) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" @@ -43,7 +44,7 @@ << ")\n"; if (DWARFDie TU = getUnitDIE(false)) - TU.dump(OS, 0, DumpOpts); + TU.dump(OS, getContext().getRecoverableErrorHandler(), 0, DumpOpts); else OS << "\n\n"; } 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 @@ -21,7 +21,6 @@ #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Path.h" -#include "llvm/Support/WithColor.h" #include #include #include @@ -425,16 +424,19 @@ // Give a little bit of info if we encounter corrupt DWARF (our offset // should always terminate at or before the start of the next compilation // unit header). - if (DIEOffset > NextCUOffset) - WithColor::warning() << format("DWARF compile unit extends beyond its " - "bounds cu 0x%8.8" PRIx64 " " - "at 0x%8.8" PRIx64 "\n", - getOffset(), DIEOffset); + if (DIEOffset > NextCUOffset) { + Context.getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF compile unit extends beyond its " + "bounds cu 0x%8.8" PRIx64 " " + "at 0x%8.8" PRIx64 "\n", + getOffset(), DIEOffset)); + } } void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { if (Error e = tryExtractDIEsIfNeeded(CUDieOnly)) - WithColor::error() << toString(std::move(e)); + Context.getRecoverableErrorHandler()(std::move(e)); } Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { @@ -481,10 +483,11 @@ IsDWO ? determineStringOffsetsTableContributionDWO(DA) : determineStringOffsetsTableContribution(DA); if (!StringOffsetOrError) - return createStringError(errc::invalid_argument, - "invalid reference to or invalid content in " - ".debug_str_offsets[.dwo]: " + - toString(StringOffsetOrError.takeError())); + return createStringError( + errc::invalid_argument, + "invalid reference to or invalid content in " + ".debug_str_offsets[.dwo]: %s", + toString(StringOffsetOrError.takeError()).c_str()); StringOffsetsTableContribution = *StringOffsetOrError; } @@ -506,8 +509,8 @@ RangesDA, RangeSectionBase, Header.getFormat()); if (!TableOrError) return createStringError(errc::invalid_argument, - "parsing a range list table: " + - toString(TableOrError.takeError())); + "parsing a range list table: %s", + toString(TableOrError.takeError()).c_str()); RngListTable = TableOrError.get(); @@ -544,8 +547,8 @@ Offset -= HeaderSize; if (Error E = LoclistTableHeader->extract(Data, &Offset)) return createStringError(errc::invalid_argument, - "parsing a loclist table: " + - toString(std::move(E))); + "parsing a loclist table: %s", + toString(std::move(E)).c_str()); } } @@ -596,9 +599,9 @@ RangesDA, RangeSectionBase, Header.getFormat())) DWO->RngListTable = TableOrError.get(); else - WithColor::error() << "parsing a range list table: " - << toString(TableOrError.takeError()) - << '\n'; + Context.getRecoverableErrorHandler()(createStringError( + errc::invalid_argument, "parsing a range list table: %s", + toString(TableOrError.takeError()).c_str())); if (DWO->RngListTable) DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize(); } else { 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 @@ -218,14 +218,14 @@ for (; Curr.isValid() && !Curr.isSubprogramDIE(); Curr = Die.getParent()) { if (Curr.getTag() == DW_TAG_inlined_subroutine) { error() << "Call site entry nested within inlined subroutine:"; - Curr.dump(OS); + Curr.dump(OS, DCtx.getRecoverableErrorHandler()); return 1; } } if (!Curr.isValid()) { error() << "Call site entry not nested within a valid subprogram:"; - Die.dump(OS); + Die.dump(OS, DCtx.getRecoverableErrorHandler()); return 1; } @@ -236,8 +236,8 @@ DW_AT_GNU_all_tail_call_sites}); if (!CallAttr) { error() << "Subprogram with call site entry has no DW_AT_call attribute:"; - Curr.dump(OS); - Die.dump(OS, /*indent*/ 1); + Curr.dump(OS, DCtx.getRecoverableErrorHandler()); + Die.dump(OS, DCtx.getRecoverableErrorHandler(), /*indent*/ 1); return 1; } @@ -552,7 +552,7 @@ << format("0x%08" PRIx64, CUOffset) << " is invalid (must be less than CU size of " << format("0x%08" PRIx64, CUSize) << "):\n"; - Die.dump(OS, 0, DumpOpts); + Die.dump(OS, DCtx.getRecoverableErrorHandler(), 0, DumpOpts); dump(Die) << '\n'; } else { // Valid reference, but we will verify it points to an actual @@ -1477,6 +1477,6 @@ raw_ostream &DWARFVerifier::note() const { return WithColor::note(OS); } raw_ostream &DWARFVerifier::dump(const DWARFDie &Die, unsigned indent) const { - Die.dump(OS, indent, DumpOpts); + Die.dump(OS, DCtx.getRecoverableErrorHandler(), indent, DumpOpts); return OS; } diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -154,8 +154,12 @@ DumpOpts.ChildRecurseDepth = 0; DumpOpts.Verbose = Options.Verbose; + std::function ErrorHandler = [](Error E) { + WithColor::error() << toString(std::move(E)) << '\n'; + }; + WithColor::note() << " in DIE:\n"; - DIE->dump(errs(), 6 /* Indent */, DumpOpts); + DIE->dump(errs(), ErrorHandler, 6 /* Indent */, DumpOpts); } bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple, diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -283,7 +283,8 @@ /// Print only DIEs that have a certain name. static bool filterByName(const StringSet<> &Names, DWARFDie Die, - StringRef NameRef, raw_ostream &OS) { + StringRef NameRef, raw_ostream &OS, + function_ref ErrorHandler) { std::string Name = (IgnoreCase && !UseRegex) ? NameRef.lower() : NameRef.str(); if (UseRegex) { @@ -296,13 +297,13 @@ exit(1); } if (RE.match(Name)) { - Die.dump(OS, 0, getDumpOpts()); + Die.dump(OS, ErrorHandler, 0, getDumpOpts()); return true; } } } else if (Names.count(Name)) { // Match full text. - Die.dump(OS, 0, getDumpOpts()); + Die.dump(OS, ErrorHandler, 0, getDumpOpts()); return true; } return false; @@ -310,16 +311,16 @@ /// Print only DIEs that have a certain name. static void filterByName(const StringSet<> &Names, - DWARFContext::unit_iterator_range CUs, - raw_ostream &OS) { + DWARFContext::unit_iterator_range CUs, raw_ostream &OS, + function_ref ErrorHandler) { for (const auto &CU : CUs) for (const auto &Entry : CU->dies()) { DWARFDie Die = {CU.get(), &Entry}; if (const char *Name = Die.getName(DINameKind::ShortName)) - if (filterByName(Names, Die, Name, OS)) + if (filterByName(Names, Die, Name, OS, ErrorHandler)) continue; if (const char *Name = Die.getName(DINameKind::LinkageName)) - filterByName(Names, Die, Name, OS); + filterByName(Names, Die, Name, OS, ErrorHandler); } } @@ -376,7 +377,7 @@ Dies.erase(std::unique(Dies.begin(), Dies.end()), Dies.end()); for (DWARFDie Die : Dies) - Die.dump(OS, 0, getDumpOpts()); + Die.dump(OS, DICtx.getRecoverableErrorHandler(), 0, getDumpOpts()); } /// Handle the --lookup option and dump the DIEs and line info for the given @@ -396,9 +397,11 @@ DumpOpts.ChildRecurseDepth = 0; DIEsForAddr.CompileUnit->dump(OS, DumpOpts); if (DIEsForAddr.FunctionDIE) { - DIEsForAddr.FunctionDIE.dump(OS, 2, DumpOpts); + DIEsForAddr.FunctionDIE.dump(OS, DICtx.getRecoverableErrorHandler(), 2, + DumpOpts); if (DIEsForAddr.BlockDIE) - DIEsForAddr.BlockDIE.dump(OS, 4, DumpOpts); + DIEsForAddr.BlockDIE.dump(OS, DICtx.getRecoverableErrorHandler(), 4, + DumpOpts); } // TODO: it is neccessary to set proper SectionIndex here. @@ -431,8 +434,10 @@ for (auto name : Name) Names.insert((IgnoreCase && !UseRegex) ? StringRef(name).lower() : name); - filterByName(Names, DICtx.normal_units(), OS); - filterByName(Names, DICtx.dwo_units(), OS); + filterByName(Names, DICtx.normal_units(), OS, + DICtx.getRecoverableErrorHandler()); + filterByName(Names, DICtx.dwo_units(), OS, + DICtx.getRecoverableErrorHandler()); return true; }