]> granicus.if.org Git - llvm/commitdiff
[DebugInfo] - Fix for lld DWARF parsing of base address selection entries in range...
authorGeorge Rimar <grimar@accesssoftek.com>
Mon, 4 Sep 2017 10:30:39 +0000 (10:30 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Mon, 4 Sep 2017 10:30:39 +0000 (10:30 +0000)
It solves issue of wrong section index evaluating for ranges when
base address is used.

Based on David Blaikie's patch D36097.

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

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

include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
include/llvm/DebugInfo/DWARF/DWARFUnit.h
lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
lib/DebugInfo/DWARF/DWARFUnit.cpp
test/DebugInfo/Inputs/dwarfdump-ranges-baseaddr-exe.elf-x86-64 [new file with mode: 0644]
test/DebugInfo/X86/dwarfdump-ranges-baseaddr-exe.s [new file with mode: 0644]
test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s [new file with mode: 0644]

index bcba14b1630d1e24a78187b510a2b8986fa598c4..421b6a4b561eba6ff10a88f0544df22687a9e1fe 100644 (file)
@@ -18,6 +18,7 @@
 
 namespace llvm {
 
+struct BaseAddress;
 class raw_ostream;
 
 struct DWARFAddressRange {
@@ -85,7 +86,8 @@ public:
   /// getAbsoluteRanges - Returns absolute address ranges defined by this range
   /// list. Has to be passed base address of the compile unit referencing this
   /// range list.
-  DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const;
+  DWARFAddressRangesVector
+  getAbsoluteRanges(llvm::Optional<BaseAddress> BaseAddr) const;
 };
 
 } // end namespace llvm
index c39fc4c974436a59bb586b3fbfb16e830efc2b88..6e85e71e5b34ca219962aede36e937af648967b4 100644 (file)
@@ -110,6 +110,12 @@ private:
   }
 };
 
+/// Represents base address of the CU.
+struct BaseAddress {
+  uint64_t Address;
+  uint64_t SectionIndex;
+};
+
 class DWARFUnit {
   DWARFContext &Context;
   /// Section containing this DWARFUnit.
@@ -135,7 +141,7 @@ class DWARFUnit {
   uint32_t Length;
   const DWARFAbbreviationDeclarationSet *Abbrevs;
   uint8_t UnitType;
-  uint64_t BaseAddr;
+  llvm::Optional<BaseAddress> BaseAddr;
   /// The compile unit debug information entry items.
   std::vector<DWARFDebugInfoEntry> DieArray;
 
@@ -259,11 +265,9 @@ public:
     llvm_unreachable("Invalid UnitType.");
   }
 
-  uint64_t getBaseAddress() const { return BaseAddr; }
+  llvm::Optional<BaseAddress> getBaseAddress() const { return BaseAddr; }
 
-  void setBaseAddress(uint64_t base_addr) {
-    BaseAddr = base_addr;
-  }
+  void setBaseAddress(BaseAddress BaseAddr) { this->BaseAddr = BaseAddr; }
 
   DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
     extractDIEsIfNeeded(ExtractUnitDIEOnly);
index a40635568cdddcb1695ee52c9de335907669ecee..861dd313fb095d48a0e9cb38fcb1745dc7ef3e73 100644 (file)
@@ -14,6 +14,8 @@ using namespace llvm;
 
 uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
                                                uint64_t *SecNdx) const {
+  if (SecNdx)
+    *SecNdx = -1ULL;
   if (!Section)
     return getUnsigned(Off, Size);
   Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off);
index aa1f17934b5969e7788848c59dc0621a08b8010c..62bd5af4e649924a3820e2e0edcce6db786408bf 100644 (file)
@@ -63,16 +63,29 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const {
   OS << format("%08x <End of list>\n", Offset);
 }
 
-DWARFAddressRangesVector
-DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const {
+DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
+    llvm::Optional<BaseAddress> BaseAddr) const {
   DWARFAddressRangesVector Res;
   for (const RangeListEntry &RLE : Entries) {
     if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
-      BaseAddress = RLE.EndAddress;
-    } else {
-      Res.push_back({BaseAddress + RLE.StartAddress,
-                     BaseAddress + RLE.EndAddress, RLE.SectionIndex});
+      BaseAddr = {RLE.EndAddress, RLE.SectionIndex};
+      continue;
     }
+
+    DWARFAddressRange E;
+    E.LowPC = RLE.StartAddress;
+    E.HighPC = RLE.EndAddress;
+    E.SectionIndex = RLE.SectionIndex;
+    // Base address of a range list entry is determined by the closest preceding
+    // base address selection entry in the same range list. It defaults to the
+    // base address of the compilation unit if there is no such entry.
+    if (BaseAddr) {
+      E.LowPC += BaseAddr->Address;
+      E.HighPC += BaseAddr->Address;
+      if (E.SectionIndex == -1ULL)
+        E.SectionIndex = BaseAddr->SectionIndex;
+    }
+    Res.push_back(E);
   }
   return Res;
 }
index 5b0b3f65f6c30639cba6578479dbee25ef438805..813960ca95d783e5ebcf45f0c66a8ee2449462d6 100644 (file)
@@ -160,7 +160,7 @@ void DWARFUnit::clear() {
   Length = 0;
   Abbrevs = nullptr;
   FormParams = DWARFFormParams({0, 0, DWARF32});
-  BaseAddr = 0;
+  BaseAddr.reset();
   RangeSectionBase = 0;
   AddrOffsetSectionBase = 0;
   clearDIEs(false);
@@ -242,9 +242,10 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
   // If CU DIE was just parsed, copy several attribute values from it.
   if (!HasCUDie) {
     DWARFDie UnitDie = getUnitDIE();
-    auto BaseAddr = toAddress(UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}));
-    if (BaseAddr)
-      setBaseAddress(*BaseAddr);
+    Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc});
+    if (Optional<uint64_t> Addr = toAddress(PC))
+        setBaseAddress({*Addr, PC->getSectionIndex()});
+
     if (!isDWO) {
       assert(AddrOffsetSectionBase == 0);
       assert(RangeSectionBase == 0);
diff --git a/test/DebugInfo/Inputs/dwarfdump-ranges-baseaddr-exe.elf-x86-64 b/test/DebugInfo/Inputs/dwarfdump-ranges-baseaddr-exe.elf-x86-64
new file mode 100644 (file)
index 0000000..ab9960b
Binary files /dev/null and b/test/DebugInfo/Inputs/dwarfdump-ranges-baseaddr-exe.elf-x86-64 differ
diff --git a/test/DebugInfo/X86/dwarfdump-ranges-baseaddr-exe.s b/test/DebugInfo/X86/dwarfdump-ranges-baseaddr-exe.s
new file mode 100644 (file)
index 0000000..64f7009
--- /dev/null
@@ -0,0 +1,13 @@
+# RUN: llvm-dwarfdump %S/../Inputs/dwarfdump-ranges-baseaddr-exe.elf-x86-64 \
+# RUN:  | FileCheck %s
+
+## Executable binary for test produced from object built in 
+## dwarfdump-ranges-baseaddr.s testcase.
+
+# CHECK: .debug_info contents:
+# CHECK: 0x0000000b: DW_TAG_compile_unit [1]
+# CHECK:             DW_AT_low_pc [DW_FORM_addr]       (0x0000000000400078)
+# CHECK-NEXT:        DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
+# CHECK-NEXT:    [0x0000000000400078 - 0x0000000000400079)
+# CHECK-NEXT:    [0x000000000040007b - 0x000000000040007e)
+# CHECK-NEXT:    [0x000000000040007f - 0x0000000000400080))
diff --git a/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s b/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s
new file mode 100644 (file)
index 0000000..2377679
--- /dev/null
@@ -0,0 +1,82 @@
+# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t
+# RUN: llvm-dwarfdump %t | FileCheck %s
+
+# CHECK: .debug_info contents:
+# CHECK: 0x0000000b: DW_TAG_compile_unit [1]
+# CHECK:             DW_AT_low_pc [DW_FORM_addr]       (0x0000000000000000)
+# CHECK-NEXT:        DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
+# CHECK-NEXT:    [0x0000000000000000 - 0x0000000000000001) ".text"
+# CHECK-NEXT:    [0x0000000000000003 - 0x0000000000000006) ".text"
+# CHECK-NEXT:    [0x0000000000000001 - 0x0000000000000002) ".text.foo1")
+
+.text
+.globl foo
+.type foo,@function
+foo: 
+.Lfunc_begin0:
+  nop
+.Ltmp0:
+  nop
+  nop
+.Ltmp1:
+  nop
+  nop
+  nop
+.Ltmp2:
+
+.section .text.foo1,"ax",@progbits
+.Ltmp3:
+ nop
+.Ltmp4: 
+ nop
+.Ltmp5:
+
+.section .debug_abbrev,"",@progbits
+.byte 1                       # Abbreviation Code
+.byte 17                      # DW_TAG_compile_unit
+.byte 0                       # DW_CHILDREN_no
+.byte 37                      # DW_AT_producer
+.byte 14                      # DW_FORM_strp
+.byte 19                      # DW_AT_language
+.byte 5                       # DW_FORM_data2
+.byte 3                       # DW_AT_name
+.byte 14                      # DW_FORM_strp
+.byte 16                      # DW_AT_stmt_list
+.byte 23                      # DW_FORM_sec_offset
+.byte 27                      # DW_AT_comp_dir
+.byte 14                      # DW_FORM_strp
+.byte 17                      # DW_AT_low_pc
+.byte 1                       # DW_FORM_addr
+.byte 85                      # DW_AT_ranges
+.byte 23                      # DW_FORM_sec_offset
+.byte 0                       # EOM(1)
+.byte 0                       # EOM(2)
+.byte 0                       # EOM(3)
+
+.section .debug_info,"",@progbits
+.Lcu_begin0:
+.long 38                      # Length of Unit
+.short 4                      # DWARF version number
+.long .debug_abbrev           # Offset Into Abbrev. Section
+.byte 8                       # Address Size (in bytes)
+.byte 1                       # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+.long 0                       # DW_AT_producer
+.short 4                      # DW_AT_language
+.long 0                       # DW_AT_name
+.long 0                       # DW_AT_stmt_list
+.long 0                       # DW_AT_comp_dir
+.quad .Lfunc_begin0           # DW_AT_low_pc
+.long .Ldebug_ranges0         # DW_AT_ranges
+
+.section .debug_ranges,"",@progbits
+.Ldebug_ranges0:
+ .quad .Lfunc_begin0-.Lfunc_begin0
+ .quad .Ltmp0-.Lfunc_begin0
+ .quad .Ltmp1-.Lfunc_begin0
+ .quad .Ltmp2-.Lfunc_begin0
+ .quad 0xFFFFFFFFFFFFFFFF
+ .quad .text.foo1
+ .quad .Ltmp4-.text.foo1
+ .quad .Ltmp5-.text.foo1
+ .quad 0
+ .quad 0