/// 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
return LLDB_INVALID_ADDRESS;
}
-/// Return the location list parser for the given format.
-static std::unique_ptr<llvm::DWARFLocationTable>
-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::DWARFDebugLoc>(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::DWARFDebugLoclists>(
- llvm_data, format == DWARFExpression::LocLists ? 5 : 4);
- }
- llvm_unreachable("Invalid LocationListFormat!");
-}
-
// DWARFExpression constructor
DWARFExpression::DWARFExpression()
: m_module_wp(), m_data(), m_dwarf_cu(nullptr),
if (IsLocationList()) {
// We have a location list
lldb::offset_t offset = 0;
- std::unique_ptr<llvm::DWARFLocationTable> loctable_up = GetLocationTable(
- m_dwarf_cu->GetSymbolFileDWARF().GetLocationListFormat(), m_data);
- if (!loctable_up)
- return;
+ std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
+ m_dwarf_cu->GetLocationTable(m_data);
llvm::MCRegisterInfo *MRI = abi ? &abi->GetMCRegisterInfo() : nullptr;
addr_t addr) const {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- std::unique_ptr<llvm::DWARFLocationTable> loctable_up = GetLocationTable(
- m_dwarf_cu->GetSymbolFileDWARF().GetLocationListFormat(), m_data);
- if (!loctable_up)
- return llvm::None;
+ std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
+ m_dwarf_cu->GetLocationTable(m_data);
llvm::Optional<DataExtractor> result;
uint64_t offset = 0;
auto lookup_addr =
*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);
s.PutCString("( ");
- SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
-
// Check to see if we have any special attribute formatters
switch (attr) {
case DW_AT_stmt_list:
// 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;
}
}
+std::unique_ptr<llvm::DWARFLocationTable>
+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::DWARFDebugLoclists>(llvm_data, GetVersion());
+ return std::make_unique<llvm::DWARFDebugLoc>(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;
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<llvm::DWARFLocationTable>
+ 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,
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);
}
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);
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;
#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"
DWARFDebugRanges *GetDebugRanges();
- const lldb_private::DWARFDataExtractor &DebugLocData();
-
static bool SupportedVersion(uint16_t version);
DWARFDIE
virtual lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu);
- virtual lldb_private::DWARFExpression::LocationListFormat
- GetLocationListFormat() const;
-
lldb::ModuleSP GetExternalModule(lldb_private::ConstString name);
typedef std::map<lldb_private::ConstString, lldb::ModuleSP>
return m_base_dwarf_cu.GetSymbolFileDWARF();
}
-DWARFExpression::LocationListFormat
-SymbolFileDWARFDwo::GetLocationListFormat() const {
- return m_base_dwarf_cu.GetVersion() >= 5
- ? DWARFExpression::LocLists
- : DWARFExpression::SplitDwarfLocationList;
-}
-
llvm::Expected<TypeSystem &>
SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) {
return GetBaseSymbolFile().GetTypeSystemForLanguage(language);
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;
--- /dev/null
+# 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: