Index: lldb/trunk/lit/SymbolFile/DWARF/debug_ranges-missing-section.s =================================================================== --- lldb/trunk/lit/SymbolFile/DWARF/debug_ranges-missing-section.s +++ lldb/trunk/lit/SymbolFile/DWARF/debug_ranges-missing-section.s @@ -0,0 +1,78 @@ +# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t +# RUN: %lldb %t -o "image lookup -v -s lookup_ranges" -o exit 2>&1 | FileCheck %s + +# CHECK: DIE has DW_AT_ranges(0x47) attribute, but range extraction failed (No debug_ranges section), +# CHECK: Function: id = {0x7fffffff0000001c}, name = "ranges", range = [0x0000000000000000-0x0000000000000004) +# CHECK: Blocks: id = {0x7fffffff0000001c}, range = [0x00000000-0x00000004) + + .text + .p2align 12 + .globl ranges + .type ranges,@function +ranges: # @ranges + nop +lookup_ranges: + nop + nop + nop +.Lranges_end: + .size ranges, .Lranges_end-ranges + # -- End function + .section .debug_str,"MS",@progbits,1 +.Lproducer: + .asciz "Hand-written DWARF" +.Lranges: + .asciz "ranges" + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .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 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 11 # DW_TAG_lexical_block + .byte 0 # DW_CHILDREN_no + .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 .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x7b DW_TAG_compile_unit + .long .Lproducer # DW_AT_producer + .quad ranges # DW_AT_low_pc + .long .Lranges_end-ranges # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x4d DW_TAG_subprogram + .quad ranges # DW_AT_low_pc + .long .Lranges_end-ranges # DW_AT_high_pc + .long .Lranges # DW_AT_name + .byte 5 # Abbrev [5] 0x61:0x15 DW_TAG_lexical_block + .long 0x47 # DW_AT_ranges + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end0: Index: lldb/trunk/lit/SymbolFile/DWARF/debug_ranges_and_rnglists.test =================================================================== --- lldb/trunk/lit/SymbolFile/DWARF/debug_ranges_and_rnglists.test +++ lldb/trunk/lit/SymbolFile/DWARF/debug_ranges_and_rnglists.test @@ -1,5 +1,4 @@ # REQUIRES: lld -# XFAIL: * # RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %S/debug_ranges.s > %t-ranges.o # RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %S/debug_rnglists.s > %t-rnglists.o Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -360,11 +360,22 @@ return false; } -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(); +static DWARFRangeList GetRangesOrReportError(const DWARFUnit &unit, + const DWARFDebugInfoEntry &die, + const DWARFFormValue &value) { + llvm::Expected expected_ranges = + (value.Form() == DW_FORM_rnglistx) + ? unit.FindRnglistFromIndex(value.Unsigned()) + : unit.FindRnglistFromOffset(value.Unsigned()); + if (expected_ranges) + return std::move(*expected_ranges); + unit.GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 ") attribute, but " + "range extraction failed (%s), please file a bug " + "and attach the file at the start of this error message", + die.GetOffset(), value.Unsigned(), + toString(expected_ranges.takeError()).c_str()); + return DWARFRangeList(); } // GetDIENamesAndRanges @@ -437,17 +448,9 @@ } break; - case DW_AT_ranges: { - const DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges(); - if (debug_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 - ") attribute yet DWARF has no .debug_ranges, please file a bug " - "and attach the file at the start of this error message", - m_offset, form_value.Unsigned()); - } break; + case DW_AT_ranges: + ranges = GetRangesOrReportError(*cu, *this, form_value); + break; case DW_AT_name: if (name == nullptr) @@ -703,14 +706,6 @@ s.PutCString(" )"); } break; - case DW_AT_ranges: { - lldb::offset_t ranges_offset = - GetRangesOffset(dwarf2Data->DebugRanges(), form_value); - dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; - DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(), - &ranges_offset, base_addr); - } break; - default: break; } @@ -962,13 +957,9 @@ bool check_specification_or_abstract_origin) const { ranges.Clear(); - SymbolFileDWARF *dwarf2Data = cu->GetSymbolFileDWARF(); - DWARFFormValue form_value; if (GetAttributeValue(cu, DW_AT_ranges, form_value)) { - if (DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges()) - debug_ranges->FindRanges(cu, GetRangesOffset(debug_ranges, form_value), - ranges); + ranges = GetRangesOrReportError(*cu, *this, form_value); } else if (check_hi_lo_pc) { dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; @@ -1413,45 +1404,38 @@ ((function_die != nullptr) || (block_die != nullptr)); } } else { - DWARFFormValue form_value; - if (GetAttributeValue(cu, DW_AT_ranges, form_value)) { - DWARFRangeList ranges; - SymbolFileDWARF *dwarf2Data = cu->GetSymbolFileDWARF(); - DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges(); - debug_ranges->FindRanges( - cu, GetRangesOffset(debug_ranges, form_value), ranges); - - if (ranges.FindEntryThatContains(address)) { - found_address = true; - // puts("***MATCH***"); - switch (m_tag) { - case DW_TAG_compile_unit: // File - case DW_TAG_partial_unit: // File + DWARFRangeList ranges; + if (GetAttributeAddressRanges(cu, ranges, /*check_hi_lo_pc*/ false) && + ranges.FindEntryThatContains(address)) { + found_address = true; + // puts("***MATCH***"); + switch (m_tag) { + case DW_TAG_compile_unit: // File + case DW_TAG_partial_unit: // File check_children = ((function_die != nullptr) || (block_die != nullptr)); break; - case DW_TAG_subprogram: // Function - if (function_die) - *function_die = this; - check_children = (block_die != nullptr); - break; - - case DW_TAG_inlined_subroutine: // Inlined Function - case DW_TAG_lexical_block: // Block { } in code - if (block_die) { - *block_die = this; - check_children = true; - } - break; + case DW_TAG_subprogram: // Function + if (function_die) + *function_die = this; + check_children = (block_die != nullptr); + break; - default: + case DW_TAG_inlined_subroutine: // Inlined Function + case DW_TAG_lexical_block: // Block { } in code + if (block_die) { + *block_die = this; check_children = true; - break; } - } else { - check_children = false; + break; + + default: + check_children = true; + break; } + } else { + check_children = false; } } } Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -211,6 +211,15 @@ uint8_t GetUnitType() const { return m_header.GetUnitType(); } + /// Return a list of address ranges resulting from a (possibly encoded) + /// range list starting at a given offset in the appropriate ranges section. + llvm::Expected FindRnglistFromOffset(dw_offset_t offset) const; + + /// Return a list of address ranges retrieved from an encoded range + /// list whose offset is found via a table lookup given an index (DWARF v5 + /// and later). + llvm::Expected FindRnglistFromIndex(uint32_t index) const; + protected: DWARFUnit(SymbolFileDWARF *dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -789,3 +789,32 @@ } llvm_unreachable("invalid UnitType."); } + +llvm::Expected +DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) const { + const DWARFDebugRangesBase *debug_ranges; + llvm::StringRef section; + if (GetVersion() <= 4) { + debug_ranges = m_dwarf->GetDebugRanges(); + section = "debug_ranges"; + } else { + debug_ranges = m_dwarf->GetDebugRngLists(); + section = "debug_rnglists"; + } + if (!debug_ranges) + return llvm::make_error("No " + section + + " section"); + + DWARFRangeList ranges; + debug_ranges->FindRanges(this, offset, ranges); + return ranges; +} + +llvm::Expected +DWARFUnit::FindRnglistFromIndex(uint32_t index) const { + const DWARFDebugRangesBase *debug_rnglists = m_dwarf->GetDebugRngLists(); + if (!debug_rnglists) + return llvm::make_error( + "No debug_rnglists section"); + return FindRnglistFromOffset(debug_rnglists->GetOffset(index)); +} Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -225,9 +225,8 @@ const DWARFDebugInfo *DebugInfo() const; - DWARFDebugRangesBase *DebugRanges(); - - const DWARFDebugRangesBase *DebugRanges() const; + DWARFDebugRangesBase *GetDebugRanges(); + DWARFDebugRangesBase *GetDebugRngLists(); const lldb_private::DWARFDataExtractor &DebugLocData(); @@ -471,6 +470,7 @@ typedef std::unordered_map NameToOffsetMap; NameToOffsetMap m_function_scope_qualified_name_map; std::unique_ptr m_ranges; + std::unique_ptr m_rnglists; UniqueDWARFASTTypeMap m_unique_ast_type_map; DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -359,7 +359,7 @@ m_context(objfile->GetModule()->GetSectionList(), dwo_section_list), m_data_debug_loc(), m_data_debug_ranges(), m_data_debug_rnglists(), m_abbr(), m_info(), m_fetched_external_modules(false), - m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(), + m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_unique_ast_type_map() {} SymbolFileDWARF::~SymbolFileDWARF() {} @@ -619,16 +619,14 @@ return nullptr; } -DWARFDebugRangesBase *SymbolFileDWARF::DebugRanges() { - if (m_ranges == nullptr) { +DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRanges() { + if (!m_ranges) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast(this)); if (get_debug_ranges_data().GetByteSize() > 0) m_ranges.reset(new DWARFDebugRanges()); - else if (get_debug_rnglists_data().GetByteSize() > 0) - m_ranges.reset(new DWARFDebugRngLists()); if (m_ranges) m_ranges->Extract(this); @@ -636,8 +634,19 @@ return m_ranges.get(); } -const DWARFDebugRangesBase *SymbolFileDWARF::DebugRanges() const { - return m_ranges.get(); +DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRngLists() { + if (!m_rnglists) { + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); + Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, + static_cast(this)); + + if (get_debug_rnglists_data().GetByteSize() > 0) + m_rnglists.reset(new DWARFDebugRngLists()); + + if (m_rnglists) + m_rnglists->Extract(this); + } + return m_rnglists.get(); } lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu) { @@ -3222,29 +3231,9 @@ case DW_AT_specification: spec_die = form_value.Reference(); break; - case DW_AT_start_scope: { - if (form_value.Form() == DW_FORM_sec_offset) { - DWARFRangeList dwarf_scope_ranges; - const DWARFDebugRangesBase *debug_ranges = DebugRanges(); - debug_ranges->FindRanges(die.GetCU(), - form_value.Unsigned(), - dwarf_scope_ranges); - } else { - // TODO: Handle the case when DW_AT_start_scope have form - // constant. The - // dwarf spec is a bit ambiguous about what is the expected - // behavior in case the enclosing block have a non coninious - // address range and the DW_AT_start_scope entry have a form - // constant. - GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 - ": DW_AT_start_scope has unsupported form type (0x%x)\n", - die.GetID(), form_value.Form()); - } - - scope_ranges.Sort(); - scope_ranges.CombineConsecutiveRanges(); - } break; + case DW_AT_start_scope: + // TODO: Implement this. + break; case DW_AT_artificial: is_artificial = form_value.Boolean(); break;