Index: lit/Breakpoint/Inputs/debug_rnglistx_rlex.yaml =================================================================== --- lit/Breakpoint/Inputs/debug_rnglistx_rlex.yaml +++ lit/Breakpoint/Inputs/debug_rnglistx_rlex.yaml @@ -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: Index: lit/Breakpoint/debug_rnglistx_rlex.test =================================================================== --- lit/Breakpoint/debug_rnglistx_rlex.test +++ lit/Breakpoint/debug_rnglistx_rlex.test @@ -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 Index: source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -157,6 +157,7 @@ // 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ ((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; Index: source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h +++ source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h @@ -22,15 +22,17 @@ 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 @@ 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, Index: source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -128,6 +128,11 @@ 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 &rangeList) { @@ -166,9 +171,27 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 rangeList; @@ -241,3 +289,7 @@ listOffset = offset; } } + +uint64_t DWARFDebugRngLists::GetOffset(size_t Index) const { + return Offsets[Index]; +} Index: source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -248,6 +248,7 @@ 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 @@ // 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 @@ 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: Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -309,6 +309,8 @@ 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);