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 @@ -16,6 +16,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -204,6 +205,10 @@ Opts.ParentRecurseDepth = 0; return Opts; } + + std::function RecoverableErrorHandler = + WithColor::defaultErrorHandler; + std::function WarningHandler = WithColor::defaultWarningHandler; }; 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 = WithColor::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,16 @@ 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); + static std::unique_ptr create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, function_ref HandleError = defaultErrorHandler, @@ -364,9 +374,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/Support/WithColor.h b/llvm/include/llvm/Support/WithColor.h --- a/llvm/include/llvm/Support/WithColor.h +++ b/llvm/include/llvm/Support/WithColor.h @@ -11,6 +11,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" namespace llvm { @@ -108,6 +109,9 @@ /// Reset the colors to terminal defaults. Call this when you are done /// outputting colored text, or before program exit. WithColor &resetColor(); + + static void defaultErrorHandler(Error Err); + static void defaultWarningHandler(Error Warning); }; } // end namespace llvm 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 @@ -1548,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)); + 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 @@ -45,7 +45,6 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -131,9 +130,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 +159,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 +204,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 +215,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; @@ -248,8 +250,8 @@ 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()) { @@ -273,7 +275,7 @@ 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. @@ -296,7 +298,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; } @@ -323,7 +325,6 @@ void DWARFContext::dump( raw_ostream &OS, DIDumpOptions DumpOpts, std::array, DIDT_ID_Count> DumpOffsets) { - uint64_t DumpType = DumpOpts.DumpType; StringRef Extension = sys::path::extension(DObj->getFileName()); @@ -456,7 +457,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 +469,16 @@ 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 +562,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 +615,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 +872,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,7 +1426,7 @@ } ErrorPolicy DWARFContext::defaultErrorHandler(Error E) { - WithColor::error() << toString(std::move(E)) << '\n'; + WithColor::defaultErrorHandler(std::move(E)); return ErrorPolicy::Continue; } @@ -1941,8 +1942,3 @@ return Addr; } -void DWARFContext::dumpWarning(Error Warning) { - handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { - WithColor::warning() << Info.message() << '\n'; - }); -} diff --git a/llvm/lib/Support/WithColor.cpp b/llvm/lib/Support/WithColor.cpp --- a/llvm/lib/Support/WithColor.cpp +++ b/llvm/lib/Support/WithColor.cpp @@ -118,3 +118,15 @@ } WithColor::~WithColor() { resetColor(); } + +void WithColor::defaultErrorHandler(Error Err) { + handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) { + WithColor::error() << Info.message() << '\n'; + }); +} + +void WithColor::defaultWarningHandler(Error Warning) { + handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { + WithColor::warning() << Info.message() << '\n'; + }); +}