Fix DWARFDataExtractor::getRelocatedValue near EOF
authorPavel Labath <pavel@labath.sk>
Tue, 14 Apr 2020 15:06:04 +0000 (17:06 +0200)
committerPavel Labath <pavel@labath.sk>
Wed, 15 Apr 2020 10:47:57 +0000 (12:47 +0200)
Summary:
If we have an (invalid) relocation which relocates bytes which partially
lie outside the range of the relocated section, the getRelocatedValue
would return confusing results. It would first read zero (because that's
what the underlying DataExtractor api does for out-of-bounds reads), and
then relocate that zero anyway.

A more appropriate behavior is to return zero straight away. This is
what this patch does.

Reviewers: dblaikie, jhenderson

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D78113

llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp

index 18b86b2..886fe1d 100644 (file)
@@ -50,9 +50,11 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off,
     *SecNdx = object::SectionedAddress::UndefSection;
   if (!Section)
     return getUnsigned(Off, Size, Err);
+
+  ErrorAsOutParameter ErrAsOut(Err);
   Optional<RelocAddrEntry> E = Obj->find(*Section, *Off);
   uint64_t A = getUnsigned(Off, Size, Err);
-  if (!E)
+  if (!E || (Err && *Err))
     return A;
   if (SecNdx)
     *SecNdx = E->SectionIndex;
index 6528cd0..46af260 100644 (file)
@@ -7,6 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gtest/gtest.h"
 
@@ -14,6 +17,54 @@ using namespace llvm;
 
 namespace {
 
+TEST(DWARFDataExtractorTest, getRelocatedValue) {
+  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:  '000000000000'
+  - Name:     .rel.debug_line
+    Type:     SHT_REL
+    Info:     .debug_line
+    Relocations:
+      - Offset:   0
+        Symbol:   f
+        Type:     R_386_32
+      - 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, [](const Twine &Err) { errs() << Err; });
+  ASSERT_TRUE(Obj);
+  std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);
+  const DWARFObject &DObj = Ctx->getDWARFObj();
+  ASSERT_EQ(6u, DObj.getLineSection().Data.size());
+
+  DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),
+                          Obj->getBytesInAddress());
+  DataExtractor::Cursor C(0);
+  EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));
+  EXPECT_EQ(0u, Data.getRelocatedAddress(C));
+  EXPECT_THAT_ERROR(C.takeError(),
+                    FailedWithMessage("unexpected end of data at offset 0x4"));
+}
+
 TEST(DWARFDataExtractorTest, getInitialLength) {
   auto GetWithError = [](ArrayRef<uint8_t> Bytes)
       -> Expected<std::tuple<uint64_t, dwarf::DwarfFormat, uint64_t>> {