This adds a basic support of the .debug_rnglists section.
Only the DW_RLE_start_length and DW_RLE_end_of_list entries are supported.
Differential revision: https://reviews.llvm.org/D52981
llvm-svn: 344119
eSectionTypeDWARFDebugNames, // DWARF v5 .debug_names
eSectionTypeOther,
eSectionTypeDWARFDebugLineStr, // DWARF v5 .debug_line_str
+ eSectionTypeDWARFDebugRngLists, // DWARF v5 .debug_rnglists
};
FLAGS_ENUM(EmulateInstructionOptions){
--- /dev/null
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000400440
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000400440
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C0C005400048C7C15005400048C7C730054000E8B7FFFFFFF4660F1F44000055B820204000483D202040004889E57417B8000000004885C0740D5DBF20204000FFE00F1F4400005DC3660F1F440000BE20204000554881EE202040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF20204000FFE00F1F005DC3660F1F440000803D391B0000007517554889E5E87EFFFFFFC605271B0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89900F1F840000000000554889E5B8010000005DC30F1F440000554889E54883EC10C745FC00000000E8DCFFFFFF4883C4105DC3660F1F440000415741564189FF415541544C8D25A618000055488D2DA6180000534989F64989D54C29E54883EC0848C1FD03E86FFEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 200000000500000000000000230000002C0000005D00000065000000690000006D000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 636C616E672076657273696F6E20382E302E3020287472756E6B203334333438372900746573742E637070002F686F6D652F756D622F74657374735F323031382F313033726E676C697374732F6C6C64622F63726561746574657374005F5A337A656476007A656400696E74006D61696E00
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 011101252513050325721710171B251101551774170000022E001101120640186E2503253A0B3B0B49133F190000032E0011011206401803253A0B3B0B49133F19000004240003253E0B0B0B000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 580000000500010800000000010004000108000000000000000200000000000000000C0000000C0000000220054000000000000B000000015603040101570000000330054000000000001A0000000156060105570000000405050400
+ - Name: .debug_rnglists
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 1D00000005000800000000000720054000000000000B0730054000000000001A00
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 82000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E023100000000F7B7492A97F18E69F7EC76B19E9024873100000000F7B7492A97F18E69F7EC76B19E90248700090220054000000000000105020A4B020700010100090230054000000000001605090AE5050206580206000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F74657374735F323031382F313033726E676C697374732F6C6C64622F6372656174657465737400746573742E63707000
+Symbols:
+...
--- /dev/null
+# RUN: yaml2obj %p/Inputs/debug_rnglist_basic.yaml > %ttest
+# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
+
+# The following code and invocation were used to produce yaml file,
+# which was manually reduced after that.
+# clang -O0 -gdwarf-5 test.cpp -o test -fuse-ld=lld -ffunction-sections
+#
+# //test.cpp:
+# int zed() {
+# return 1;
+# }
+#
+# int main() {
+# return zed();
+# }
+#
+# clang and LLD versions were 8.0.0 (trunk 343487)
+#
+# Output file contains .debug_rnglists section with basic entries:
+# DW_RLE_start_length and DW_RLE_end_of_list.
+# If LLDB would not be able to parse the section and entries correctly,
+# then reported location would be incorrect.
+
+b main
+# CHECK-LABEL: b main
+# CHECK: Address: {{.*}}`main + 15 at test.cpp:6:9
+
+b zed
+# CHECK-LABEL: b zed
+# CHECK: Address: {{.*}}`zed() + 4 at test.cpp:2:2
return "dwarf-pubtypes";
case eSectionTypeDWARFDebugRanges:
return "dwarf-ranges";
+ case eSectionTypeDWARFDebugRngLists:
+ return "dwarf-rnglists";
case eSectionTypeDWARFDebugStr:
return "dwarf-str";
case eSectionTypeDWARFDebugStrOffsets:
static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
+ static ConstString g_sect_name_dwarf_debug_rnglists(".debug_rnglists");
static ConstString g_sect_name_dwarf_debug_str(".debug_str");
static ConstString g_sect_name_dwarf_debug_str_offsets(
".debug_str_offsets");
sect_type = eSectionTypeDWARFDebugPubTypes;
else if (name == g_sect_name_dwarf_debug_ranges)
sect_type = eSectionTypeDWARFDebugRanges;
+ else if (name == g_sect_name_dwarf_debug_rnglists)
+ sect_type = eSectionTypeDWARFDebugRngLists;
else if (name == g_sect_name_dwarf_debug_str)
sect_type = eSectionTypeDWARFDebugStr;
else if (name == g_sect_name_dwarf_debug_types)
case eSectionTypeDWARFDebugPubNames:
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
+ case eSectionTypeDWARFDebugRngLists:
case eSectionTypeDWARFDebugStr:
case eSectionTypeDWARFDebugStrOffsets:
case eSectionTypeDWARFDebugTypes:
if (section_name == g_sect_name_dwarf_debug_pubtypes)
return eSectionTypeDWARFDebugPubTypes;
if (section_name == g_sect_name_dwarf_debug_ranges)
- return eSectionTypeDWARFDebugRanges;
+ return eSectionTypeDWARFDebugRanges;
if (section_name == g_sect_name_dwarf_debug_str)
return eSectionTypeDWARFDebugStr;
if (section_name == g_sect_name_dwarf_debug_types)
dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET,
check_specification_or_abstract_origin);
if (debug_ranges_offset != DW_INVALID_OFFSET) {
- DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
-
- debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges);
+ if (DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges())
+ debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset,
+ ranges);
ranges.Slide(cu->GetBaseAddress());
} else if (check_hi_lo_pc) {
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
}
return false;
}
+
+bool DWARFDebugRngLists::ExtractRangeList(const DWARFDataExtractor &data,
+ uint8_t addrSize,
+ lldb::offset_t *offset_ptr,
+ DWARFRangeList &rangeList) {
+ rangeList.Clear();
+
+ bool error = false;
+ while (!error) {
+ switch (data.GetU8(offset_ptr)) {
+ case DW_RLE_end_of_list:
+ return true;
+
+ case DW_RLE_start_length: {
+ dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
+ dw_addr_t len = data.GetULEB128(offset_ptr);
+ rangeList.Append(DWARFRangeList::Entry(begin, len));
+ break;
+ }
+
+ default:
+ // Next encodings are not yet supported:
+ // DW_RLE_base_addressx, DW_RLE_startx_endx, DW_RLE_startx_length,
+ // DW_RLE_offset_pair, DW_RLE_base_address, DW_RLE_start_end
+ lldbassert(0 && "unknown range list entry encoding");
+ error = true;
+ }
+ }
+
+ return false;
+}
+
+void DWARFDebugRngLists::Extract(SymbolFileDWARF *dwarf2Data) {
+ const DWARFDataExtractor &data = dwarf2Data->get_debug_rnglists_data();
+ lldb::offset_t offset = 0;
+
+ uint64_t length = data.GetU32(&offset);
+ bool isDwarf64 = false;
+ if (length == 0xffffffff) {
+ length = data.GetU64(&offset);
+ isDwarf64 = true;
+ }
+ lldb::offset_t end = offset + length;
+
+ // Check version.
+ if (data.GetU16(&offset) < 5)
+ return;
+
+ uint8_t addrSize = data.GetU8(&offset);
+
+ // We do not support non-zero segment selector size.
+ if (data.GetU8(&offset) != 0) {
+ lldbassert(0 && "not implemented");
+ return;
+ }
+
+ uint32_t offsetsAmount = data.GetU32(&offset);
+ for (uint32_t i = 0; i < offsetsAmount; ++i)
+ Offsets.push_back(data.GetPointer(&offset));
+
+ lldb::offset_t listOffset = offset;
+ DWARFRangeList rangeList;
+ while (offset < end && ExtractRangeList(data, addrSize, &offset, rangeList)) {
+ rangeList.Sort();
+ m_range_map[listOffset] = rangeList;
+ listOffset = offset;
+ }
+}
class DWARFDebugRanges {
public:
DWARFDebugRanges();
- ~DWARFDebugRanges();
- void Extract(SymbolFileDWARF *dwarf2Data);
+ virtual ~DWARFDebugRanges();
+ virtual void Extract(SymbolFileDWARF *dwarf2Data);
+
static void Dump(lldb_private::Stream &s,
const lldb_private::DWARFDataExtractor &debug_ranges_data,
lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr);
range_map m_range_map;
};
+// DWARF v5 .debug_rnglists section.
+class DWARFDebugRngLists : public DWARFDebugRanges {
+public:
+ void Extract(SymbolFileDWARF *dwarf2Data) override;
+
+protected:
+ bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data,
+ uint8_t addrSize, lldb::offset_t *offset_ptr,
+ DWARFRangeList &list);
+
+ std::vector<uint64_t> Offsets;
+};
+
#endif // SymbolFileDWARF_DWARFDebugRanges_h_
m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(),
m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(),
m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(),
- m_data_debug_ranges(), m_data_debug_str(), m_data_apple_names(),
- m_data_apple_types(), m_data_apple_namespaces(), m_abbr(), m_info(),
- m_line(), m_fetched_external_modules(false),
+ m_data_debug_ranges(), m_data_debug_rnglists(), m_data_debug_str(),
+ m_data_apple_names(), m_data_apple_types(), m_data_apple_namespaces(),
+ m_abbr(), m_info(), m_line(), m_fetched_external_modules(false),
m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(),
m_unique_ast_type_map() {}
m_data_debug_ranges);
}
+const DWARFDataExtractor &SymbolFileDWARF::get_debug_rnglists_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugRngLists,
+ m_data_debug_rnglists);
+}
+
const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_data() {
return GetCachedSectionData(eSectionTypeDWARFDebugStr, m_data_debug_str);
}
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
static_cast<void *>(this));
- if (get_debug_ranges_data().GetByteSize() > 0) {
+
+ if (get_debug_ranges_data().GetByteSize() > 0)
m_ranges.reset(new DWARFDebugRanges());
- if (m_ranges.get())
- m_ranges->Extract(this);
- }
+ else if (get_debug_rnglists_data().GetByteSize() > 0)
+ m_ranges.reset(new DWARFDebugRngLists());
+
+ if (m_ranges.get())
+ m_ranges->Extract(this);
}
return m_ranges.get();
}
class DWARFDebugInfoEntry;
class DWARFDebugLine;
class DWARFDebugRanges;
+class DWARFDebugRngLists;
class DWARFDeclContext;
class DWARFDIECollection;
class DWARFFormValue;
const lldb_private::DWARFDataExtractor &get_debug_macro_data();
const lldb_private::DWARFDataExtractor &get_debug_loc_data();
const lldb_private::DWARFDataExtractor &get_debug_ranges_data();
+ const lldb_private::DWARFDataExtractor &get_debug_rnglists_data();
const lldb_private::DWARFDataExtractor &get_debug_str_data();
const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data();
const lldb_private::DWARFDataExtractor &get_debug_types_data();
DWARFDataSegment m_data_debug_macro;
DWARFDataSegment m_data_debug_loc;
DWARFDataSegment m_data_debug_ranges;
+ DWARFDataSegment m_data_debug_rnglists;
DWARFDataSegment m_data_debug_str;
DWARFDataSegment m_data_debug_str_offsets;
DWARFDataSegment m_data_debug_types;
case eSectionTypeDWARFDebugPubNames:
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
+ case eSectionTypeDWARFDebugRngLists:
case eSectionTypeDWARFDebugStr:
case eSectionTypeDWARFDebugStrOffsets:
case eSectionTypeDWARFDebugTypes: