summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h14
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFContext.cpp30
-rw-r--r--llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp47
-rw-r--r--llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h1
4 files changed, 81 insertions, 11 deletions
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 4bf34d52bcb..8850104db29 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -289,6 +289,11 @@ private:
DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
};
+/// Used as a return value for a error callback passed to DWARF context.
+/// Callback should return Halt if client application wants to stop
+/// object parsing, or should return Continue otherwise.
+enum class ErrorPolicy { Halt, Continue };
+
/// DWARFContextInMemory is the simplest possible implementation of a
/// DWARFContext. It assumes all content is available in memory and stores
/// pointers to it.
@@ -346,9 +351,14 @@ class DWARFContextInMemory : public DWARFContext {
Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
StringRef &Data);
+ /// 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);
+
public:
- DWARFContextInMemory(const object::ObjectFile &Obj,
- const LoadedObjectInfo *L = nullptr);
+ DWARFContextInMemory(
+ const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
+ function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler);
DWARFContextInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
uint8_t AddrSize,
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 38147946175..fdd191e0cbf 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -870,13 +870,13 @@ static Expected<SymInfo> getSymbolInfo(const object::ObjectFile &Obj,
Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
if (!SymAddrOrErr)
- return createError("error: failed to compute symbol address: ",
+ return createError("failed to compute symbol address: ",
SymAddrOrErr.takeError());
// Also remember what section this symbol is in for later
auto SectOrErr = Sym->getSection();
if (!SectOrErr)
- return createError("error: failed to get symbol section: ",
+ return createError("failed to get symbol section: ",
SectOrErr.takeError());
RSec = *SectOrErr;
@@ -937,8 +937,14 @@ Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec,
return Error::success();
}
-DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
- const LoadedObjectInfo *L)
+ErrorPolicy DWARFContextInMemory::defaultErrorHandler(Error E) {
+ errs() << "error: " + toString(std::move(E)) << '\n';
+ return ErrorPolicy::Continue;
+}
+
+DWARFContextInMemory::DWARFContextInMemory(
+ const object::ObjectFile &Obj, const LoadedObjectInfo *L,
+ function_ref<ErrorPolicy(Error)> HandleError)
: FileName(Obj.getFileName()), IsLittleEndian(Obj.isLittleEndian()),
AddressSize(Obj.getBytesInAddress()) {
for (const SectionRef &Section : Obj.sections()) {
@@ -961,9 +967,10 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
Section.getContents(data);
if (auto Err = maybeDecompress(Section, name, data)) {
- errs() << "error: failed to decompress '" + name + "', " +
- toString(std::move(Err))
- << '\n';
+ ErrorPolicy EP = HandleError(
+ createError("failed to decompress '" + name + "', ", std::move(Err)));
+ if (EP == ErrorPolicy::Halt)
+ return;
continue;
}
@@ -1055,7 +1062,8 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
Expected<SymInfo> SymInfoOrErr = getSymbolInfo(Obj, Reloc, L, AddrCache);
if (!SymInfoOrErr) {
- errs() << toString(SymInfoOrErr.takeError()) << '\n';
+ if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt)
+ return;
continue;
}
@@ -1064,7 +1072,11 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
if (V.error()) {
SmallString<32> Name;
Reloc.getTypeName(Name);
- errs() << "error: failed to compute relocation: " << Name << "\n";
+ ErrorPolicy EP = HandleError(
+ createError("failed to compute relocation: " + name + ", ",
+ errorCodeToError(object_error::parse_failed)));
+ if (EP == ErrorPolicy::Halt)
+ return;
continue;
}
RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val};
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
index bf004d6ffc2..7f6492ee6d1 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
@@ -15,10 +15,14 @@
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ObjectYAML/DWARFEmitter.h"
#include "llvm/ObjectYAML/DWARFYAML.h"
@@ -2146,4 +2150,47 @@ TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) {
"offset:");
}
+TEST(DWARFDebugInfo, TestErrorReportingPolicy) {
+ initLLVMIfNeeded();
+ auto ExpectedDG = dwarfgen::Generator::create(Triple("x86_64-pc-linux"),
+ 4 /*DwarfVersion*/);
+ if (HandleExpectedError(ExpectedDG))
+ return;
+ dwarfgen::Generator *DG = ExpectedDG.get().get();
+ AsmPrinter *AP = DG->getAsmPrinter();
+ MCContext *MC = DG->getMCContext();
+
+ // Emit two compressed sections with broken headers.
+ AP->OutStreamer->SwitchSection(
+ MC->getELFSection(".zdebug_foo", 0 /*Type*/, 0 /*Flags*/));
+ AP->OutStreamer->EmitBytes("0");
+ AP->OutStreamer->SwitchSection(
+ MC->getELFSection(".zdebug_bar", 0 /*Type*/, 0 /*Flags*/));
+ AP->OutStreamer->EmitBytes("0");
+
+ MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
+ auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
+ EXPECT_TRUE((bool)Obj);
+
+ // Case 1: error handler handles all errors. That allows
+ // DWARFContextInMemory
+ // to parse whole file and find both two errors we know about.
+ int Errors = 0;
+ DWARFContextInMemory Ctx1(*Obj.get(), nullptr, [&](Error E) {
+ ++Errors;
+ consumeError(std::move(E));
+ return ErrorPolicy::Continue;
+ });
+ EXPECT_TRUE(Errors == 2);
+
+ // Case 2: error handler stops parsing of object after first error.
+ Errors = 0;
+ DWARFContextInMemory Ctx2(*Obj.get(), nullptr, [&](Error E) {
+ ++Errors;
+ consumeError(std::move(E));
+ return ErrorPolicy::Halt;
+ });
+ EXPECT_TRUE(Errors == 1);
+}
+
} // end anonymous namespace
diff --git a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h
index 76665e5193e..dd7e8709638 100644
--- a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h
+++ b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h
@@ -215,6 +215,7 @@ public:
BumpPtrAllocator &getAllocator() { return Allocator; }
AsmPrinter *getAsmPrinter() const { return Asm.get(); }
+ MCContext *getMCContext() const { return MC.get(); }
DIEAbbrevSet &getAbbrevSet() { return Abbreviations; }
DwarfStringPool &getStringPool() { return *StringPool; }
OpenPOWER on IntegriCloud