forked from OSchip/llvm-project
[LLDB] - Add support for DW_FORM_rnglistx and relative DW_RLE_* entries.
This adds support for DW_RLE_base_addressx, DW_RLE_startx_endx, DW_RLE_startx_length, DW_FORM_rnglistx. Differential revision: https://reviews.llvm.org/D53929 llvm-svn: 345958
This commit is contained in:
parent
15da7684db
commit
5497f6580e
|
@ -0,0 +1,57 @@
|
|||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Entry: 0x0000000000201000
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
Address: 0x0000000000201000
|
||||
AddressAlign: 0x0000000000000010
|
||||
Content: 31ED4989D15E4889E24883E4F0505449C7C08011200048C7C11011200048C7C700112000E897010000F4CCCCCCCCCCCC55B810202000483D102020004889E57417B8000000004885C0740D5DBF10202000FFE00F1F4400005DC3660F1F440000BE10202000554881EE102020004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF10202000FFE00F1F005DC3660F1F440000803D592F0000007517554889E5E87EFFFFFFC605472F0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89CCCCCCCCCCCCCCCCCCC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC31C0C3CCCCCCCCCCCCCCCCCCCCCCCCCC415741564189FF415541544C8D25E61E000055488D2DE61E0000534989F64989D54C29E54883EC0848C1FD03E8430000004885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
|
||||
- Name: .debug_str_offsets
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 28000000050000003000000067000000000000002800000076000000240000006F0000007400000022000000
|
||||
- Name: .debug_str
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_MERGE, SHF_STRINGS ]
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 2F686F6D652F756D622F74657374735F323031382F3131345F726E676C69737473007900696E74005F5A336261726900636C616E672076657273696F6E20382E302E3020287472756E6B203334353639392920286C6C766D2F7472756E6B203334353530362900746573742E6363006D61696E00780062617200
|
||||
- Name: .debug_loclists
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: '15000000050008000000000003000301005503020101005000'
|
||||
- Name: .debug_abbrev
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 011101252513050325721710171B2573171101552374178C01170000022E01111B120640187A196E2503253A0B3B0B49133F190000030500021703253A0B3B0B49130000042E01111B120640187A1903253A0B3B0B49133F1900000534001C0D03253A0B3B0B4913000006240003253E0B0B0B000000
|
||||
- Name: .debug_info
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 6600000005000108000000000100040001080000000000000002080000000000000000000000000C0000000C00000002000400000001570304010365000000030C0000000701036500000000040106000000015706010765000000050108010865000000000605050400
|
||||
- Name: .debug_rnglists
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: '1300000005000800010000000400000003000403010600'
|
||||
- Name: .debug_macinfo
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: '00'
|
||||
- Name: .debug_addr
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 1C00000005000800E010200000000000F010200000000000E310200000000000
|
||||
- Name: .debug_line
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 82000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E022200000000FC42F1EAF1396417A8FBE442FBADC7032200000000FC42F1EAF1396417A8FBE442FBADC703000902E01020000000000014050B0A130504063C0201000101000902F0102000000000001805030A140206000101
|
||||
- Name: .debug_line_str
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_MERGE, SHF_STRINGS ]
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 2F686F6D652F756D622F74657374735F323031382F3131345F726E676C6973747300746573742E636300
|
||||
Symbols:
|
|
@ -0,0 +1,28 @@
|
|||
# RUN: yaml2obj %p/Inputs/debug_rnglistx_rlex.yaml > %ttest
|
||||
# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
|
||||
|
||||
# The following code and invocation were used.
|
||||
# clang -gdwarf-5 test.cc -o test_v5 -fuse-ld=lld -fno-rtti -O2 -ffunction-sections
|
||||
# Then output was converted to yaml and reduced.
|
||||
#
|
||||
# int bar(int x) {
|
||||
# return ++x;
|
||||
# }
|
||||
#
|
||||
# int main() {
|
||||
# int y = 1;
|
||||
# return bar(y);
|
||||
# }
|
||||
#
|
||||
# clang and LLD versions were 8.0.0 (trunk 345699)
|
||||
#
|
||||
# Output file contains DW_FORM_rnglistx and DW_RLE_startx_length.
|
||||
|
||||
b bar
|
||||
b main
|
||||
|
||||
# CHECK-LABEL: b bar
|
||||
# CHECK: Address: {{.*}}`bar(int) at test.cc:4:11
|
||||
|
||||
# CHECK-LABEL: b main
|
||||
# CHECK: Address: {{.*}}`main at test.cc:9:3
|
|
@ -157,6 +157,7 @@ bool DWARFDebugInfoEntry::FastExtract(
|
|||
|
||||
// signed or unsigned LEB 128 values
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_rnglistx:
|
||||
case DW_FORM_sdata:
|
||||
case DW_FORM_udata:
|
||||
case DW_FORM_ref_udata:
|
||||
|
@ -387,6 +388,13 @@ void DWARFDebugInfoEntry::DumpAncestry(SymbolFileDWARF *dwarf2Data,
|
|||
Dump(dwarf2Data, cu, s, recurse_depth);
|
||||
}
|
||||
|
||||
static dw_offset_t GetRangesOffset(const DWARFDebugRangesBase *debug_ranges,
|
||||
DWARFFormValue &form_value) {
|
||||
if (form_value.Form() == DW_FORM_rnglistx)
|
||||
return debug_ranges->GetOffset(form_value.Unsigned());
|
||||
return form_value.Unsigned();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// GetDIENamesAndRanges
|
||||
//
|
||||
|
@ -464,7 +472,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
|
|||
case DW_AT_ranges: {
|
||||
const DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges();
|
||||
if (debug_ranges)
|
||||
debug_ranges->FindRanges(cu, form_value.Unsigned(), ranges);
|
||||
debug_ranges->FindRanges(cu, GetRangesOffset(debug_ranges, form_value), ranges);
|
||||
else
|
||||
cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError(
|
||||
"{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64
|
||||
|
@ -748,11 +756,13 @@ void DWARFDebugInfoEntry::DumpAttribute(
|
|||
} break;
|
||||
|
||||
case DW_AT_ranges: {
|
||||
lldb::offset_t ranges_offset = form_value.Unsigned();
|
||||
if (!dwarf2Data)
|
||||
break;
|
||||
lldb::offset_t ranges_offset =
|
||||
GetRangesOffset(dwarf2Data->DebugRanges(), form_value);
|
||||
dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
|
||||
if (dwarf2Data)
|
||||
DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(),
|
||||
&ranges_offset, base_addr);
|
||||
DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(),
|
||||
&ranges_offset, base_addr);
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
@ -1062,12 +1072,11 @@ size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
|
|||
bool check_specification_or_abstract_origin) const {
|
||||
ranges.Clear();
|
||||
|
||||
dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(
|
||||
dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET,
|
||||
check_specification_or_abstract_origin);
|
||||
if (debug_ranges_offset != DW_INVALID_OFFSET) {
|
||||
DWARFFormValue form_value;
|
||||
if (GetAttributeValue(dwarf2Data, cu, DW_AT_ranges, form_value)) {
|
||||
if (DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges())
|
||||
debug_ranges->FindRanges(cu, debug_ranges_offset, ranges);
|
||||
debug_ranges->FindRanges(cu, GetRangesOffset(debug_ranges, form_value),
|
||||
ranges);
|
||||
} else if (check_hi_lo_pc) {
|
||||
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
|
||||
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
|
||||
|
@ -1718,12 +1727,12 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
|
|||
((function_die != NULL) || (block_die != NULL));
|
||||
}
|
||||
} else {
|
||||
dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(
|
||||
dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
|
||||
if (debug_ranges_offset != DW_INVALID_OFFSET) {
|
||||
DWARFFormValue form_value;
|
||||
if (GetAttributeValue(dwarf2Data, cu, DW_AT_ranges, form_value)) {
|
||||
DWARFRangeList ranges;
|
||||
DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges();
|
||||
debug_ranges->FindRanges(cu, debug_ranges_offset, ranges);
|
||||
debug_ranges->FindRanges(
|
||||
cu, GetRangesOffset(debug_ranges, form_value), ranges);
|
||||
|
||||
if (ranges.FindEntryThatContains(address)) {
|
||||
found_address = true;
|
||||
|
|
|
@ -128,6 +128,11 @@ bool DWARFDebugRanges::FindRanges(const DWARFUnit *cu,
|
|||
return false;
|
||||
}
|
||||
|
||||
uint64_t DWARFDebugRanges::GetOffset(size_t Index) const {
|
||||
lldbassert(false && "DW_FORM_rnglistx is not present before DWARF5");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DWARFDebugRngLists::ExtractRangeList(
|
||||
const DWARFDataExtractor &data, uint8_t addrSize,
|
||||
lldb::offset_t *offset_ptr, std::vector<RngListEntry> &rangeList) {
|
||||
|
@ -166,9 +171,27 @@ bool DWARFDebugRngLists::ExtractRangeList(
|
|||
break;
|
||||
}
|
||||
|
||||
case DW_RLE_base_addressx: {
|
||||
dw_addr_t base = data.GetULEB128(offset_ptr);
|
||||
rangeList.push_back({DW_RLE_base_addressx, base, 0});
|
||||
break;
|
||||
}
|
||||
|
||||
case DW_RLE_startx_endx: {
|
||||
dw_addr_t start = data.GetULEB128(offset_ptr);
|
||||
dw_addr_t end = data.GetULEB128(offset_ptr);
|
||||
rangeList.push_back({DW_RLE_startx_endx, start, end});
|
||||
break;
|
||||
}
|
||||
|
||||
case DW_RLE_startx_length: {
|
||||
dw_addr_t start = data.GetULEB128(offset_ptr);
|
||||
dw_addr_t length = data.GetULEB128(offset_ptr);
|
||||
rangeList.push_back({DW_RLE_startx_length, start, length});
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Next encodings are not yet supported:
|
||||
// DW_RLE_base_addressx, DW_RLE_startx_endx, DW_RLE_startx_length.
|
||||
lldbassert(0 && "unknown range list entry encoding");
|
||||
error = true;
|
||||
}
|
||||
|
@ -177,6 +200,15 @@ bool DWARFDebugRngLists::ExtractRangeList(
|
|||
return false;
|
||||
}
|
||||
|
||||
static uint64_t ReadAddressFromDebugAddrSection(const DWARFUnit *cu,
|
||||
uint32_t index) {
|
||||
uint32_t index_size = cu->GetAddressByteSize();
|
||||
dw_offset_t addr_base = cu->GetAddrBase();
|
||||
lldb::offset_t offset = addr_base + index * index_size;
|
||||
return cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset,
|
||||
index_size);
|
||||
}
|
||||
|
||||
bool DWARFDebugRngLists::FindRanges(const DWARFUnit *cu,
|
||||
dw_offset_t debug_ranges_offset,
|
||||
DWARFRangeList &range_list) const {
|
||||
|
@ -200,6 +232,21 @@ bool DWARFDebugRngLists::FindRanges(const DWARFUnit *cu,
|
|||
range_list.Append(
|
||||
DWARFRangeList::Entry(BaseAddr + E.value0, E.value1 - E.value0));
|
||||
break;
|
||||
case DW_RLE_base_addressx: {
|
||||
BaseAddr = ReadAddressFromDebugAddrSection(cu, E.value0);
|
||||
break;
|
||||
}
|
||||
case DW_RLE_startx_endx: {
|
||||
dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
|
||||
dw_addr_t end = ReadAddressFromDebugAddrSection(cu, E.value1);
|
||||
range_list.Append(DWARFRangeList::Entry(start, end - start));
|
||||
break;
|
||||
}
|
||||
case DW_RLE_startx_length: {
|
||||
dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
|
||||
range_list.Append(DWARFRangeList::Entry(start, E.value1));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
llvm_unreachable("unexpected encoding");
|
||||
}
|
||||
|
@ -214,7 +261,8 @@ void DWARFDebugRngLists::Extract(SymbolFileDWARF *dwarf2Data) {
|
|||
lldb::offset_t offset = 0;
|
||||
|
||||
uint64_t length = data.GetU32(&offset);
|
||||
if (length == 0xffffffff)
|
||||
bool isDwarf64 = (length == 0xffffffff);
|
||||
if (isDwarf64)
|
||||
length = data.GetU64(&offset);
|
||||
lldb::offset_t end = offset + length;
|
||||
|
||||
|
@ -232,7 +280,7 @@ void DWARFDebugRngLists::Extract(SymbolFileDWARF *dwarf2Data) {
|
|||
|
||||
uint32_t offsetsAmount = data.GetU32(&offset);
|
||||
for (uint32_t i = 0; i < offsetsAmount; ++i)
|
||||
Offsets.push_back(data.GetPointer(&offset));
|
||||
Offsets.push_back(data.GetMaxU64(&offset, isDwarf64 ? 8 : 4));
|
||||
|
||||
lldb::offset_t listOffset = offset;
|
||||
std::vector<RngListEntry> rangeList;
|
||||
|
@ -241,3 +289,7 @@ void DWARFDebugRngLists::Extract(SymbolFileDWARF *dwarf2Data) {
|
|||
listOffset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t DWARFDebugRngLists::GetOffset(size_t Index) const {
|
||||
return Offsets[Index];
|
||||
}
|
||||
|
|
|
@ -22,15 +22,17 @@ public:
|
|||
virtual void Extract(SymbolFileDWARF *dwarf2Data) = 0;
|
||||
virtual bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
|
||||
DWARFRangeList &range_list) const = 0;
|
||||
virtual uint64_t GetOffset(size_t Index) const = 0;
|
||||
};
|
||||
|
||||
class DWARFDebugRanges final : public DWARFDebugRangesBase {
|
||||
public:
|
||||
DWARFDebugRanges();
|
||||
|
||||
virtual void Extract(SymbolFileDWARF *dwarf2Data) override;
|
||||
virtual bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
|
||||
DWARFRangeList &range_list) const override;
|
||||
void Extract(SymbolFileDWARF *dwarf2Data) override;
|
||||
bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
|
||||
DWARFRangeList &range_list) const override;
|
||||
uint64_t GetOffset(size_t Index) const override;
|
||||
|
||||
static void Dump(lldb_private::Stream &s,
|
||||
const lldb_private::DWARFDataExtractor &debug_ranges_data,
|
||||
|
@ -58,6 +60,7 @@ public:
|
|||
void Extract(SymbolFileDWARF *dwarf2Data) override;
|
||||
bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
|
||||
DWARFRangeList &range_list) const override;
|
||||
uint64_t GetOffset(size_t Index) const override;
|
||||
|
||||
protected:
|
||||
bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data,
|
||||
|
|
|
@ -248,6 +248,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
|
|||
m_value.value.uval = data.GetU64(offset_ptr);
|
||||
break;
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_rnglistx:
|
||||
case DW_FORM_strx:
|
||||
case DW_FORM_udata:
|
||||
case DW_FORM_ref_udata:
|
||||
|
@ -393,6 +394,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
|
|||
|
||||
// signed or unsigned LEB 128 values
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_rnglistx:
|
||||
case DW_FORM_sdata:
|
||||
case DW_FORM_udata:
|
||||
case DW_FORM_ref_udata:
|
||||
|
@ -777,6 +779,7 @@ bool DWARFFormValue::FormIsSupported(dw_form_t form) {
|
|||
switch (form) {
|
||||
case DW_FORM_addr:
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_rnglistx:
|
||||
case DW_FORM_block2:
|
||||
case DW_FORM_block4:
|
||||
case DW_FORM_data2:
|
||||
|
|
|
@ -309,6 +309,8 @@ void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const {
|
|||
void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
|
||||
SetAddrBase(
|
||||
cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_addr_base, 0));
|
||||
SetRangesBase(cu_die.GetAttributeValueAsUnsigned(m_dwarf, this,
|
||||
DW_AT_rnglists_base, 0));
|
||||
|
||||
uint64_t base_addr = cu_die.GetAttributeValueAsAddress(
|
||||
m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
|
||||
|
|
Loading…
Reference in New Issue