Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -18,6 +18,7 @@ namespace llvm { +struct BaseAddress; class raw_ostream; struct DWARFAddressRange { @@ -85,7 +86,8 @@ /// 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 Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -110,6 +110,12 @@ } }; +/// 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 @@ 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 @@ 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); Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -14,6 +14,8 @@ 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); Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -63,16 +63,29 @@ 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; } Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -160,7 +160,7 @@ Length = 0; Abbrevs = nullptr; FormParams = DWARFFormParams({0, 0, DWARF32}); - BaseAddr = 0; + BaseAddr.reset(); RangeSectionBase = 0; AddrOffsetSectionBase = 0; clearDIEs(false); @@ -242,9 +242,10 @@ // 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); Index: llvm/trunk/test/DebugInfo/X86/dwarfdump-ranges-baseaddr-exe.s =================================================================== --- llvm/trunk/test/DebugInfo/X86/dwarfdump-ranges-baseaddr-exe.s +++ llvm/trunk/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)) Index: llvm/trunk/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s =================================================================== --- llvm/trunk/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s +++ llvm/trunk/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