]> granicus.if.org Git - llvm/commitdiff
Recommit "[ELF] - Add ability for DWARFContextInMemory to exit early when any error...
authorGeorge Rimar <grimar@accesssoftek.com>
Wed, 28 Jun 2017 08:21:19 +0000 (08:21 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Wed, 28 Jun 2017 08:21:19 +0000 (08:21 +0000)
With fix in include folder character case:
#include "llvm/Codegen/AsmPrinter.h" -> #include "llvm/CodeGen/AsmPrinter.h"

Original commit message:

Change introduces error reporting policy for DWARFContextInMemory.
New callback provided by client is able to handle error on it's
side and return Halt or Continue.

That allows to either keep current behavior when parser prints all errors
but continues parsing object or implement something very different, like
stop parsing on a first error and report an error in a client style.

Differential revision: https://reviews.llvm.org/D34328

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306517 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/DebugInfo/DWARF/DWARFContext.h
lib/DebugInfo/DWARF/DWARFContext.cpp
unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
unittests/DebugInfo/DWARF/DwarfGenerator.h

index 4bf34d52bcba9bd63410879ac578aa723e34028f..8850104db2972981c8f95d12910d4830b8707bf0 100644 (file)
@@ -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,
index 3814794617503163211bd9a6a9e67bd0aad18db3..fdd191e0cbfef0fb56b887f46b1eb7e23bef6996 100644 (file)
@@ -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};
index bf004d6ffc235ca35da27b26a553d5b34a63082b..7f6492ee6d1270517e26cef810319f5c62f58bf6 100644 (file)
 #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
index 76665e5193e83606b295ff97a10c1ad03828d5bd..dd7e8709638d8440236f39c8ce6704c6c9ec0d6e 100644 (file)
@@ -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; }