From 2f95c8bccb73cb4d292a2c4e3704887da3414394 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Mon, 4 Sep 2017 10:30:39 +0000 Subject: [PATCH] [DebugInfo] - Fix for lld DWARF parsing of base address selection entries in range lists. 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 llvm-svn: 312477 --- .../DebugInfo/DWARF/DWARFDebugRangeList.h | 4 +- llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 14 +-- .../DebugInfo/DWARF/DWARFDataExtractor.cpp | 2 + .../DebugInfo/DWARF/DWARFDebugRangeList.cpp | 25 ++++-- llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 9 +- .../dwarfdump-ranges-baseaddr-exe.elf-x86-64 | Bin 0 -> 1128 bytes .../X86/dwarfdump-ranges-baseaddr-exe.s | 13 +++ .../DebugInfo/X86/dwarfdump-ranges-baseaddr.s | 82 ++++++++++++++++++ 8 files changed, 133 insertions(+), 16 deletions(-) create mode 100644 llvm/test/DebugInfo/Inputs/dwarfdump-ranges-baseaddr-exe.elf-x86-64 create mode 100644 llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr-exe.s create mode 100644 llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h index bcba14b1630d1..421b6a4b561eb 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -18,6 +18,7 @@ namespace llvm { +struct BaseAddress; class raw_ostream; struct DWARFAddressRange { @@ -85,7 +86,8 @@ class DWARFDebugRangeList { /// 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 BaseAddr) const; }; } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index c39fc4c974436..6e85e71e5b34c 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -110,6 +110,12 @@ class DWARFUnitSection final : public SmallVector, 1>, } }; +/// 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 BaseAddr; /// The compile unit debug information entry items. std::vector DieArray; @@ -259,11 +265,9 @@ class DWARFUnit { llvm_unreachable("Invalid UnitType."); } - uint64_t getBaseAddress() const { return BaseAddr; } + llvm::Optional 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); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp index a40635568cddd..861dd313fb095 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -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 Rel = Obj->find(*Section, *Off); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp index aa1f17934b596..62bd5af4e6499 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -63,16 +63,29 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const { OS << format("%08x \n", Offset); } -DWARFAddressRangesVector -DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const { +DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( + llvm::Optional 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; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 5b0b3f65f6c30..813960ca95d78 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -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 PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); + if (Optional Addr = toAddress(PC)) + setBaseAddress({*Addr, PC->getSectionIndex()}); + if (!isDWO) { assert(AddrOffsetSectionBase == 0); assert(RangeSectionBase == 0); diff --git a/llvm/test/DebugInfo/Inputs/dwarfdump-ranges-baseaddr-exe.elf-x86-64 b/llvm/test/DebugInfo/Inputs/dwarfdump-ranges-baseaddr-exe.elf-x86-64 new file mode 100644 index 0000000000000000000000000000000000000000..ab9960bd30cca6e9d4a5d0ec1bed5a04eb459cf5 GIT binary patch literal 1128 zcmbVL!AiqG5S=7O`O>-fQF?1$Fz9Needk<>Uayq*Knk2qU&_{3e6Iu5!5$JB8^=L;Ts*&SrN1O0?+{0D1vh~u=b z<60$^f>~KYoM(wj5Q+?7TE9N2Bt=wJiwlWV-YA%6dHOt$AB$NjagwH0{vxbOig{l5 zI{zOTV;Ox5xmme~hL`hD@>nqghXU=#>U+{N}nXMEXC=_oR12V;g@%`^%ye?OILd{=X1< BL8<@% literal 0 HcmV?d00001 diff --git a/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr-exe.s b/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr-exe.s new file mode 100644 index 0000000000000..64f7009c8f5e9 --- /dev/null +++ b/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr-exe.s @@ -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/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s b/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s new file mode 100644 index 0000000000000..23776799e79d9 --- /dev/null +++ b/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s @@ -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