diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -34,15 +34,6 @@ /// location expression or a location list and interprets it. class DWARFExpression { public: - enum LocationListFormat : uint8_t { - NonLocationList, // Not a location list - RegularLocationList, // Location list format used in non-split dwarf files - SplitDwarfLocationList, // Location list format used in pre-DWARF v5 split - // dwarf files (.debug_loc.dwo) - LocLists, // Location list format used in DWARF v5 - // (.debug_loclists/.debug_loclists.dwo). - }; - DWARFExpression(); /// Constructor diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -54,29 +54,6 @@ return LLDB_INVALID_ADDRESS; } -/// Return the location list parser for the given format. -static std::unique_ptr -GetLocationTable(DWARFExpression::LocationListFormat format, const DataExtractor &data) { - llvm::DWARFDataExtractor llvm_data( - toStringRef(data.GetData()), - data.GetByteOrder() == lldb::eByteOrderLittle, data.GetAddressByteSize()); - - switch (format) { - case DWARFExpression::NonLocationList: - return nullptr; - // DWARF<=4 .debug_loc - case DWARFExpression::RegularLocationList: - return std::make_unique(llvm_data); - // Non-standard DWARF 4 extension (fission) .debug_loc.dwo - case DWARFExpression::SplitDwarfLocationList: - // DWARF 5 .debug_loclists(.dwo) - case DWARFExpression::LocLists: - return std::make_unique( - llvm_data, format == DWARFExpression::LocLists ? 5 : 4); - } - llvm_unreachable("Invalid LocationListFormat!"); -} - // DWARFExpression constructor DWARFExpression::DWARFExpression() : m_module_wp(), m_data(), m_dwarf_cu(nullptr), @@ -157,10 +134,8 @@ if (IsLocationList()) { // We have a location list lldb::offset_t offset = 0; - std::unique_ptr loctable_up = GetLocationTable( - m_dwarf_cu->GetSymbolFileDWARF().GetLocationListFormat(), m_data); - if (!loctable_up) - return; + std::unique_ptr loctable_up = + m_dwarf_cu->GetLocationTable(m_data); llvm::MCRegisterInfo *MRI = abi ? &abi->GetMCRegisterInfo() : nullptr; @@ -2812,10 +2787,8 @@ addr_t addr) const { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); - std::unique_ptr loctable_up = GetLocationTable( - m_dwarf_cu->GetSymbolFileDWARF().GetLocationListFormat(), m_data); - if (!loctable_up) - return llvm::None; + std::unique_ptr loctable_up = + m_dwarf_cu->GetLocationTable(m_data); llvm::Optional result; uint64_t offset = 0; auto lookup_addr = diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -344,7 +344,7 @@ *frame_base = DWARFExpression( module, DataExtractor(data, block_offset, block_length), cu); } else { - DataExtractor data = dwarf.DebugLocData(); + DataExtractor data = cu->GetLocationData(); const dw_offset_t offset = form_value.Unsigned(); if (data.ValidOffset(offset)) { data = DataExtractor(data, offset, data.GetByteSize() - offset); @@ -478,8 +478,6 @@ s.PutCString("( "); - SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF(); - // Check to see if we have any special attribute formatters switch (attr) { case DW_AT_stmt_list: @@ -509,7 +507,7 @@ // We have a location list offset as the value that is the offset into // the .debug_loc section that describes the value over it's lifetime uint64_t debug_loc_offset = form_value.Unsigned(); - DWARFExpression::PrintDWARFLocationList(s, cu, dwarf.DebugLocData(), + DWARFExpression::PrintDWARFLocationList(s, cu, cu->GetLocationData(), debug_loc_offset); } } break; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -243,6 +243,13 @@ return *Offset + m_loclists_base; } + /// Return the location table for parsing the given location list data. The + /// format is chosen according to the unit type. Never returns null. + std::unique_ptr + GetLocationTable(const lldb_private::DataExtractor &data) const; + + const lldb_private::DWARFDataExtractor &GetLocationData() const; + protected: DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -462,6 +462,22 @@ } } +std::unique_ptr +DWARFUnit::GetLocationTable(const DataExtractor &data) const { + llvm::DWARFDataExtractor llvm_data( + toStringRef(data.GetData()), + data.GetByteOrder() == lldb::eByteOrderLittle, data.GetAddressByteSize()); + + if (m_is_dwo || GetVersion() >= 5) + return std::make_unique(llvm_data, GetVersion()); + return std::make_unique(llvm_data); +} + +const DWARFDataExtractor &DWARFUnit::GetLocationData() const { + return GetVersion() >= 5 ? GetSymbolFileDWARF().get_debug_loclists_data() + : GetSymbolFileDWARF().get_debug_loc_data(); +} + void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { m_ranges_base = ranges_base; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -21,7 +21,6 @@ #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Core/dwarf.h" -#include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolFile.h" @@ -236,8 +235,6 @@ DWARFDebugRanges *GetDebugRanges(); - const lldb_private::DWARFDataExtractor &DebugLocData(); - static bool SupportedVersion(uint16_t version); DWARFDIE @@ -260,9 +257,6 @@ virtual lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu); - virtual lldb_private::DWARFExpression::LocationListFormat - GetLocationListFormat() const; - lldb::ModuleSP GetExternalModule(lldb_private::ConstString name); typedef std::map diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -597,13 +597,6 @@ m_objfile_sp->ReadSectionData(section_sp.get(), data); } -const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() { - const DWARFDataExtractor &debugLocData = get_debug_loc_data(); - if (debugLocData.GetByteSize() > 0) - return debugLocData; - return get_debug_loclists_data(); -} - const DWARFDataExtractor &SymbolFileDWARF::get_debug_loc_data() { return GetCachedSectionData(eSectionTypeDWARFDebugLoc, m_data_debug_loc); } @@ -3361,7 +3354,7 @@ module, DataExtractor(data, block_offset, block_length), die.GetCU()); } else { - DataExtractor data = DebugLocData(); + DataExtractor data = die.GetCU()->GetLocationData(); dw_offset_t offset = form_value.Unsigned(); if (form_value.Form() == DW_FORM_loclistx) offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1); @@ -3978,13 +3971,6 @@ return m_debug_map_symfile; } -DWARFExpression::LocationListFormat -SymbolFileDWARF::GetLocationListFormat() const { - if (m_data_debug_loclists.m_data.GetByteSize() > 0) - return DWARFExpression::LocLists; - return DWARFExpression::RegularLocationList; -} - SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() { llvm::call_once(m_dwp_symfile_once_flag, [this]() { ModuleSpec module_spec; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -35,9 +35,6 @@ DWARFUnit * GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override; - lldb_private::DWARFExpression::LocationListFormat - GetLocationListFormat() const override; - size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, DIEArray &method_die_offsets) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -137,13 +137,6 @@ return m_base_dwarf_cu.GetSymbolFileDWARF(); } -DWARFExpression::LocationListFormat -SymbolFileDWARFDwo::GetLocationListFormat() const { - return m_base_dwarf_cu.GetVersion() >= 5 - ? DWARFExpression::LocLists - : DWARFExpression::SplitDwarfLocationList; -} - llvm::Expected SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) { return GetBaseSymbolFile().GetTypeSystemForLanguage(language); diff --git a/lldb/test/Shell/SymbolFile/DWARF/debug_loc_and_loclists.s b/lldb/test/Shell/SymbolFile/DWARF/debug_loc_and_loclists.s new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/debug_loc_and_loclists.s @@ -0,0 +1,154 @@ +# Test that we can handle DWARF 4 and 5 location lists in the same object file +# (but different compile units). + +# REQUIRES: x86 + +# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t +# RUN: %lldb %t -o "image lookup -v -s loc" -o "image lookup -v -s loclists" \ +# RUN: -o exit | FileCheck %s + + +# CHECK-LABEL: image lookup -v -s loc +# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg5 RDI, + +# CHECK-LABEL: image lookup -v -s loclists +# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = DW_OP_reg0 RAX, + + +loc: + nop +.Lloc_end: + +loclists: + nop +.Lloclists_end: + + .section .debug_loc,"",@progbits +.Lloc_list: + .quad loc-loc + .quad .Lloc_end-loc + .short 1 + .byte 85 # super-register DW_OP_reg5 + .quad 0 + .quad 0 + + .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_list: + .byte 4 # DW_LLE_offset_pair + .uleb128 loclists-loclists + .uleb128 .Lloclists_end-loclists + .uleb128 1 + .byte 80 # super-register DW_OP_reg0 + .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 37 # DW_AT_producer + .byte 8 # DW_FORM_string + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .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 8 # DW_FORM_string + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .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 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits + .long .Lloc_cu_end-.Lloc_cu_start # Length of Unit +.Lloc_cu_start: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x50 DW_TAG_compile_unit + .asciz "Hand-written DWARF" # DW_AT_producer + .short 12 # DW_AT_language + .quad loc # DW_AT_low_pc + .long .Lloc_end-loc # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x29 DW_TAG_subprogram + .quad loc # DW_AT_low_pc + .long .Lloc_end-loc # DW_AT_high_pc + .asciz "loc" # DW_AT_name + .long .Lint # DW_AT_type + .byte 3 # Abbrev [3] DW_TAG_formal_parameter + .long .Lloc_list # DW_AT_location + .asciz "x0" # DW_AT_name + .long .Lint # DW_AT_type + .byte 0 # End Of Children Mark +.Lint: + .byte 4 # Abbrev [4] 0x53:0x7 DW_TAG_base_type + .asciz "int" # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Lloc_cu_end: + + .long .Lloclists_cu_end-.Lloclists_cu_start # Length of Unit +.Lloclists_cu_start: + .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] 0xb:0x50 DW_TAG_compile_unit + .asciz "Hand-written DWARF" # DW_AT_producer + .short 12 # DW_AT_language + .quad loclists # DW_AT_low_pc + .long .Lloclists_end-loclists # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x29 DW_TAG_subprogram + .quad loclists # DW_AT_low_pc + .long .Lloclists_end-loclists # DW_AT_high_pc + .asciz "loclists" # DW_AT_name + .long .Lint # DW_AT_type + .byte 3 # Abbrev [3] DW_TAG_formal_parameter + .long .Lloclists_list # DW_AT_location + .asciz "x1" # DW_AT_name + .long .Lint # DW_AT_type + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Lloclists_cu_end: