DWARFDebugLoclists: Make it possible to read relocated addresses
Summary: Handling relocations was not needed when the loclists section was a DWO-only thing. But since DWARF5, it is possible to use it in regular objects too, and the standard permits embedding addresses into the section directly. These addresses need to be relocated in unlinked files. Reviewers: JDevlieghere, dblaikie, probinson Subscribers: aprantl, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D68271
This commit is contained in:
parent
0d14656b9d
commit
b4c5b8f3f5
|
@ -105,16 +105,17 @@ private:
|
|||
bool IsLittleEndian;
|
||||
|
||||
public:
|
||||
void parse(DataExtractor data, uint64_t Offset, uint64_t EndOffset, uint16_t Version);
|
||||
void parse(const DWARFDataExtractor &data, uint64_t Offset,
|
||||
uint64_t EndOffset, uint16_t Version);
|
||||
void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo,
|
||||
DIDumpOptions DumpOpts, Optional<uint64_t> Offset) const;
|
||||
|
||||
/// Return the location list at the given offset or nullptr.
|
||||
LocationList const *getLocationListAtOffset(uint64_t Offset) const;
|
||||
|
||||
static Expected<LocationList> parseOneLocationList(const DataExtractor &Data,
|
||||
uint64_t *Offset,
|
||||
unsigned Version);
|
||||
static Expected<LocationList>
|
||||
parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset,
|
||||
unsigned Version);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -299,12 +299,11 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
|
|||
}
|
||||
|
||||
Header.dump(OS, DumpOpts);
|
||||
DataExtractor LocData(Data.getData(),
|
||||
Data.isLittleEndian(), Header.getAddrSize());
|
||||
|
||||
DWARFDebugLoclists Loclists;
|
||||
uint64_t EndOffset = Header.length() + Header.getHeaderOffset();
|
||||
Loclists.parse(LocData, Offset, EndOffset, Header.getVersion());
|
||||
Data.setAddressSize(Header.getAddrSize());
|
||||
Loclists.parse(Data, Offset, EndOffset, Header.getVersion());
|
||||
Loclists.dump(OS, 0, MRI, DumpOpts, DumpOffset);
|
||||
Offset = EndOffset;
|
||||
}
|
||||
|
@ -733,7 +732,8 @@ const DWARFDebugLoclists *DWARFContext::getDebugLocDWO() {
|
|||
// Assume all compile units have the same address byte size.
|
||||
// FIXME: We don't need AddressSize for split DWARF since relocatable
|
||||
// addresses cannot appear there. At the moment DWARFExpression requires it.
|
||||
DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 4);
|
||||
DWARFDataExtractor LocData(*DObj, DObj->getLocDWOSection(), isLittleEndian(),
|
||||
4);
|
||||
// Use version 4. DWO does not support the DWARF v5 .debug_loclists yet and
|
||||
// that means we are parsing the new style .debug_loc (pre-standatized version
|
||||
// of the .debug_loclists).
|
||||
|
|
|
@ -140,7 +140,7 @@ void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
|
|||
}
|
||||
|
||||
Expected<DWARFDebugLoclists::LocationList>
|
||||
DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data,
|
||||
DWARFDebugLoclists::parseOneLocationList(const DWARFDataExtractor &Data,
|
||||
uint64_t *Offset, unsigned Version) {
|
||||
LocationList LL;
|
||||
LL.Offset = *Offset;
|
||||
|
@ -165,7 +165,7 @@ DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data,
|
|||
E.Value1 = Data.getULEB128(C);
|
||||
break;
|
||||
case dwarf::DW_LLE_start_length:
|
||||
E.Value0 = Data.getAddress(C);
|
||||
E.Value0 = Data.getRelocatedAddress(C);
|
||||
E.Value1 = Data.getULEB128(C);
|
||||
break;
|
||||
case dwarf::DW_LLE_offset_pair:
|
||||
|
@ -173,7 +173,7 @@ DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data,
|
|||
E.Value1 = Data.getULEB128(C);
|
||||
break;
|
||||
case dwarf::DW_LLE_base_address:
|
||||
E.Value0 = Data.getAddress(C);
|
||||
E.Value0 = Data.getRelocatedAddress(C);
|
||||
break;
|
||||
default:
|
||||
cantFail(C.takeError());
|
||||
|
@ -200,7 +200,8 @@ DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data,
|
|||
return LL;
|
||||
}
|
||||
|
||||
void DWARFDebugLoclists::parse(DataExtractor data, uint64_t Offset, uint64_t EndOffset, uint16_t Version) {
|
||||
void DWARFDebugLoclists::parse(const DWARFDataExtractor &data, uint64_t Offset,
|
||||
uint64_t EndOffset, uint16_t Version) {
|
||||
IsLittleEndian = data.isLittleEndian();
|
||||
AddressSize = data.getAddressSize();
|
||||
|
||||
|
|
|
@ -119,13 +119,14 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
|
|||
}
|
||||
|
||||
bool UseLocLists = !U->isDWOUnit();
|
||||
StringRef LoclistsSectionData =
|
||||
UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData();
|
||||
|
||||
if (!LoclistsSectionData.empty()) {
|
||||
DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(),
|
||||
Obj.getAddressSize());
|
||||
auto Data =
|
||||
UseLocLists
|
||||
? DWARFDataExtractor(Obj, Obj.getLoclistsSection(),
|
||||
Ctx.isLittleEndian(), Obj.getAddressSize())
|
||||
: DWARFDataExtractor(U->getLocSectionData(), Ctx.isLittleEndian(),
|
||||
Obj.getAddressSize());
|
||||
|
||||
if (!Data.getData().empty()) {
|
||||
// Old-style location list were used in DWARF v4 (.debug_loc.dwo section).
|
||||
// Modern locations list (.debug_loclists) are used starting from v5.
|
||||
// Ideally we should take the version from the .debug_loclists section
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t
|
||||
# RUN: llvm-dwarfdump %t | FileCheck %s
|
||||
|
||||
|
||||
# CHECK: DW_AT_location (0x0000000c
|
||||
# CHECK-NEXT: Addr idx 0 (w/ length 1): DW_OP_reg0 RAX
|
||||
# CHECK-NEXT: [0x0000000000000001, 0x0000000000000002): DW_OP_reg1 RDX
|
||||
# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg2 RCX
|
||||
# CHECK-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg3 RBX
|
||||
# CHECK-NEXT: Addr idx 57005 (w/ length 1): DW_OP_reg4 RSI)
|
||||
|
||||
|
||||
.text
|
||||
f: # @f
|
||||
.Lf0:
|
||||
nop
|
||||
.Lf1:
|
||||
nop
|
||||
.Lf2:
|
||||
nop
|
||||
.Lf3:
|
||||
nop
|
||||
.Lf4:
|
||||
.Lfend:
|
||||
# -- End function
|
||||
.section .debug_loclists,"",@progbits
|
||||
.long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 # Length
|
||||
.Ldebug_loclist_table_start0:
|
||||
.short 5 # Version
|
||||
.byte 8 # Address size
|
||||
.byte 0 # Segment selector size
|
||||
.long 0 # Offset entry count
|
||||
.Lloclists_table_base0:
|
||||
.Ldebug_loc0:
|
||||
.byte 3 # DW_LLE_startx_length
|
||||
.uleb128 0 # start idx
|
||||
.uleb128 .Lf1-.Lf0 # length
|
||||
.byte 1 # Loc expr size
|
||||
.byte 80 # super-register DW_OP_reg0
|
||||
.byte 4 # DW_LLE_offset_pair
|
||||
.uleb128 .Lf1-.Lf0 # starting offset
|
||||
.uleb128 .Lf2-.Lf0 # ending offset
|
||||
.byte 1 # Loc expr size
|
||||
.byte 81 # super-register DW_OP_reg1
|
||||
.byte 8 # DW_LLE_start_length
|
||||
.quad .Lf2 # starting offset
|
||||
.uleb128 .Lf3-.Lf2 # length
|
||||
.byte 1 # Loc expr size
|
||||
.byte 82 # super-register DW_OP_reg2
|
||||
.byte 6 # DW_LLE_base_address
|
||||
.quad .Lf3 # base address
|
||||
.byte 4 # DW_LLE_offset_pair
|
||||
.uleb128 .Lf3-.Lf3 # starting offset
|
||||
.uleb128 .Lf4-.Lf3 # ending offset
|
||||
.byte 1 # Loc expr size
|
||||
.byte 83 # super-register DW_OP_reg3
|
||||
.byte 3 # DW_LLE_startx_length
|
||||
.uleb128 0xdead # start idx
|
||||
.uleb128 .Lf1-.Lf0 # length
|
||||
.byte 1 # Loc expr size
|
||||
.byte 84 # super-register DW_OP_reg4
|
||||
.byte 0 # DW_LLE_end_of_list
|
||||
.Ldebug_loclist_table_end0:
|
||||
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.byte 1 # Abbreviation Code
|
||||
.byte 17 # DW_TAG_compile_unit
|
||||
.byte 1 # DW_CHILDREN_yes
|
||||
.byte 115 # DW_AT_addr_base
|
||||
.byte 23 # DW_FORM_sec_offset
|
||||
.ascii "\214\001" # DW_AT_loclists_base
|
||||
.byte 23 # DW_FORM_sec_offset
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 2 # Abbreviation Code
|
||||
.byte 46 # DW_TAG_subprogram
|
||||
.byte 1 # DW_CHILDREN_yes
|
||||
.byte 17 # DW_AT_low_pc
|
||||
.byte 27 # DW_FORM_addrx
|
||||
.byte 18 # DW_AT_high_pc
|
||||
.byte 6 # DW_FORM_data4
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 3 # Abbreviation Code
|
||||
.byte 5 # DW_TAG_formal_parameter
|
||||
.byte 0 # DW_CHILDREN_no
|
||||
.byte 2 # DW_AT_location
|
||||
.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 .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
|
||||
.Ldebug_info_start0:
|
||||
.short 5 # DWARF version number
|
||||
.byte 1 # DWARF Unit Type
|
||||
.byte 8 # Address Size (in bytes)
|
||||
.long .debug_abbrev # Offset Into Abbrev. Section
|
||||
.byte 1 # Abbrev [1] 0xc:0x3c DW_TAG_compile_unit
|
||||
.long .Laddr_table_base0 # DW_AT_addr_base
|
||||
.long .Lloclists_table_base0 # DW_AT_loclists_base
|
||||
.byte 2 # Abbrev [2] 0x27:0x1c DW_TAG_subprogram
|
||||
.byte 0 # DW_AT_low_pc
|
||||
.long .Lfend-.Lf0 # DW_AT_high_pc
|
||||
.byte 3 # Abbrev [3] 0x36:0xc DW_TAG_formal_parameter
|
||||
.long .Ldebug_loc0 # DW_AT_location
|
||||
.byte 0 # End Of Children Mark
|
||||
.byte 0 # End Of Children Mark
|
||||
.Ldebug_info_end0:
|
||||
|
||||
.section .debug_addr,"",@progbits
|
||||
.long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
|
||||
.Ldebug_addr_start0:
|
||||
.short 5 # DWARF version number
|
||||
.byte 8 # Address size
|
||||
.byte 0 # Segment selector size
|
||||
.Laddr_table_base0:
|
||||
.quad .Lf0
|
||||
.Ldebug_addr_end0:
|
Loading…
Reference in New Issue