[llvm] r306512 - [ELF] - Add ability for DWARFContextInMemory to exit early when any error happen.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 27 23:57:20 PDT 2017


Author: grimar
Date: Tue Jun 27 23:57:20 2017
New Revision: 306512

URL: http://llvm.org/viewvc/llvm-project?rev=306512&view=rev
Log:
[ELF] - Add ability for DWARFContextInMemory to exit early when any error happen.

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

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

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h?rev=306512&r1=306511&r2=306512&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h Tue Jun 27 23:57:20 2017
@@ -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 DWAR
   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,

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=306512&r1=306511&r2=306512&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Tue Jun 27 23:57:20 2017
@@ -870,13 +870,13 @@ static Expected<SymInfo> getSymbolInfo(c
 
     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::maybeDecompr
   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::DWARFContextInMemo
       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::DWARFContextInMemo
 
       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::DWARFContextInMemo
       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};

Modified: llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp?rev=306512&r1=306511&r2=306512&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp Tue Jun 27 23:57:20 2017
@@ -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, TestDwarfVerifyCUDo
                             "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

Modified: llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h?rev=306512&r1=306511&r2=306512&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h Tue Jun 27 23:57:20 2017
@@ -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; }
 




More information about the llvm-commits mailing list