[PATCH] D77556: [DWARFDataExtractor] Add a "truncating" constructor

Pavel Labath via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 6 08:06:22 PDT 2020


labath created this revision.
labath added reviewers: dblaikie, probinson, jhenderson, ikudrin.
Herald added a subscriber: aprantl.
Herald added a project: LLVM.
labath added a child revision: D77557: [DWARFDebugLine] Use truncating data extractors for prologue parsing.

This constructor allows us to create a new DWARFDataExtractor which will
only present a subrange of an entire debug section. Since debug sections
typically consist of multiple contributions, it is expected that one
will create a new data extractor for each contribution in order to
avoid unexpectedly running off into the next one.

This is very useful for unifying the flows for detecting parse errors.
Without it, the code needs to consider two very different scenarios:

1. If there is another contribution after the current one, the DataExtractor functions will just start reading from there. This is detectable by comparing the current offset against the known end-of-contribution offset.
2. If this is the last contribution, the data extractor will just start returning zeroes (or other default values). This situation can *not* be detected by checking the parsing offset, as this will not be advanced in case of errors.

Using a truncated data extractor simplifies the code (and reduces
cognitive load) by making these two cases behave identically -- a
running off the end of a contribution will _always_ produce an EOF error
(if one uses error-aware parsing methods) or return default values.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77556

Files:
  llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
  llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp


Index: llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp
===================================================================
--- llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp
+++ llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gtest/gtest.h"
 
@@ -95,4 +97,57 @@
             std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12));
 }
 
+TEST(DWARFDataExtractorTest, Truncation) {
+  StringRef Yaml = R"(
+!ELF
+FileHeader:
+  Class:    ELFCLASS32
+  Data:     ELFDATA2LSB
+  Type:     ET_REL
+  Machine:  EM_386
+Sections:
+  - Name:     .text
+    Type:     SHT_PROGBITS
+    Size:     0x80
+  - Name:     .debug_line
+    Type:     SHT_PROGBITS
+    Content:  '616263640000000065666768'
+  - Name:     .rel.debug_line
+    Type:     SHT_REL
+    Info:     .debug_line
+    Relocations:
+      - Offset:   4
+        Symbol:   f
+        Type:     R_386_32
+Symbols:
+  - Name:     f
+    Type:     STT_SECTION
+    Section:  .text
+    Value:    0x42
+)";
+  SmallString<0> Storage;
+  std::unique_ptr<object::ObjectFile> Obj =
+      yaml::yaml2ObjectFile(Storage, Yaml, [](Twine Err) { errs() << Err; });
+  ASSERT_TRUE(Obj);
+  std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);
+  const DWARFObject &DObj = Ctx->getDWARFObj();
+  ASSERT_EQ(12u, DObj.getLineSection().Data.size());
+
+  DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),
+                          Obj->getBytesInAddress());
+  DataExtractor::Cursor C(0);
+  EXPECT_EQ(0x64636261u, Data.getRelocatedAddress(C));
+  EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));
+  EXPECT_EQ(0x68676665u, Data.getRelocatedAddress(C));
+  EXPECT_THAT_ERROR(C.takeError(), Succeeded());
+
+  C = DataExtractor::Cursor{0};
+  DWARFDataExtractor Truncated(Data, 8);
+  EXPECT_EQ(0x64636261u, Truncated.getRelocatedAddress(C));
+  EXPECT_EQ(0x42u, Truncated.getRelocatedAddress(C));
+  EXPECT_EQ(0x0u, Truncated.getRelocatedAddress(C));
+  EXPECT_THAT_ERROR(C.takeError(),
+                    FailedWithMessage("unexpected end of data at offset 0x8"));
+}
+
 } // namespace
Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
===================================================================
--- llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
+++ llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
@@ -39,6 +39,12 @@
             StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()),
             IsLittleEndian, AddressSize) {}
 
+  /// Truncating constructor
+  DWARFDataExtractor(const DWARFDataExtractor &Other, size_t Length)
+      : DataExtractor(Other.getData().substr(0, Length), Other.isLittleEndian(),
+                      Other.getAddressSize()),
+        Obj(Other.Obj), Section(Other.Section) {}
+
   /// Extracts the DWARF "initial length" field, which can either be a 32-bit
   /// value smaller than 0xfffffff0, or the value 0xffffffff followed by a
   /// 64-bit length. Returns the actual length, and the DWARF format which is


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D77556.255345.patch
Type: text/x-patch
Size: 3302 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200406/7d927499/attachment-0001.bin>


More information about the llvm-commits mailing list