namespace llvm {
+struct BaseAddress;
class raw_ostream;
struct DWARFAddressRange {
/// 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
}
};
+/// Represents base address of the CU.
+struct BaseAddress {
+ uint64_t Address;
+ uint64_t SectionIndex;
+};
+
class DWARFUnit {
DWARFContext &Context;
/// Section containing this 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;
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);
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);
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;
}
Length = 0;
Abbrevs = nullptr;
FormParams = DWARFFormParams({0, 0, DWARF32});
- BaseAddr = 0;
+ BaseAddr.reset();
RangeSectionBase = 0;
AddrOffsetSectionBase = 0;
clearDIEs(false);
// 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);
--- /dev/null
+# 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))
--- /dev/null
+# 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