forked from OSchip/llvm-project
[lldb/DWARF] Add support for DW_AT_loclists_base&DW_FORM_loclistx
Summary: This adds support for DWARF5 location lists which are specified indirectly, via an index into the debug_loclists offset table. This includes parsing the DW_AT_loclists_base attribute which determines the location of this offset table, and support for new form DW_FORM_loclistx which is used in conjuction with DW_AT_location to refer to the location lists in this way. The code uses the llvm class to parse the offset information, and I've also tried to structure it similarly to how the relevant llvm functionality works. Reviewers: JDevlieghere, aprantl, clayborg Subscribers: lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D71268
This commit is contained in:
parent
46822083ef
commit
c8b74ee264
|
@ -156,6 +156,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
|
|||
|
||||
// signed or unsigned LEB 128 values
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_loclistx:
|
||||
case DW_FORM_rnglistx:
|
||||
case DW_FORM_sdata:
|
||||
case DW_FORM_udata:
|
||||
|
|
|
@ -107,6 +107,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
|
|||
m_value.value.uval = data.GetU64(offset_ptr);
|
||||
break;
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_loclistx:
|
||||
case DW_FORM_rnglistx:
|
||||
case DW_FORM_strx:
|
||||
case DW_FORM_udata:
|
||||
|
@ -305,6 +306,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
|
|||
|
||||
// signed or unsigned LEB 128 values
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_loclistx:
|
||||
case DW_FORM_rnglistx:
|
||||
case DW_FORM_sdata:
|
||||
case DW_FORM_udata:
|
||||
|
@ -699,6 +701,7 @@ bool DWARFFormValue::FormIsSupported(dw_form_t form) {
|
|||
switch (form) {
|
||||
case DW_FORM_addr:
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_loclistx:
|
||||
case DW_FORM_rnglistx:
|
||||
case DW_FORM_block2:
|
||||
case DW_FORM_block4:
|
||||
|
|
|
@ -306,6 +306,9 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
|
|||
if (!attributes.ExtractFormValueAtIndex(i, form_value))
|
||||
continue;
|
||||
switch (attr) {
|
||||
case DW_AT_loclists_base:
|
||||
SetLoclistsBase(form_value.Unsigned());
|
||||
break;
|
||||
case DW_AT_rnglists_base:
|
||||
ranges_base = form_value.Unsigned();
|
||||
SetRangesBase(*ranges_base);
|
||||
|
@ -452,6 +455,23 @@ ParseListTableHeader(const llvm::DWARFDataExtractor &data, uint64_t offset,
|
|||
return Table;
|
||||
}
|
||||
|
||||
void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) {
|
||||
m_loclists_base = loclists_base;
|
||||
|
||||
uint64_t header_size = llvm::DWARFListTableHeader::getHeaderSize(DWARF32);
|
||||
if (loclists_base < header_size)
|
||||
return;
|
||||
|
||||
m_loclist_table_header.emplace(".debug_loclists", "locations");
|
||||
uint64_t offset = loclists_base - header_size;
|
||||
if (llvm::Error E = m_loclist_table_header->extract(
|
||||
m_dwarf.get_debug_loclists_data().GetAsLLVM(), &offset)) {
|
||||
GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
|
||||
"Failed to extract location list table at offset 0x%" PRIx64 ": %s",
|
||||
loclists_base, toString(std::move(E)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) {
|
||||
m_ranges_base = ranges_base;
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ public:
|
|||
dw_addr_t GetRangesBase() const { return m_ranges_base; }
|
||||
dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; }
|
||||
void SetAddrBase(dw_addr_t addr_base);
|
||||
void SetLoclistsBase(dw_addr_t loclists_base);
|
||||
void SetRangesBase(dw_addr_t ranges_base);
|
||||
void SetStrOffsetsBase(dw_offset_t str_offsets_base);
|
||||
virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0;
|
||||
|
@ -234,6 +235,16 @@ public:
|
|||
return llvm::None;
|
||||
}
|
||||
|
||||
llvm::Optional<uint64_t> GetLoclistOffset(uint32_t Index) {
|
||||
if (!m_loclist_table_header)
|
||||
return llvm::None;
|
||||
|
||||
llvm::Optional<uint64_t> Offset = m_loclist_table_header->getOffsetEntry(Index);
|
||||
if (!Offset)
|
||||
return llvm::None;
|
||||
return *Offset + m_loclists_base;
|
||||
}
|
||||
|
||||
protected:
|
||||
DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
|
||||
const DWARFUnitHeader &header,
|
||||
|
@ -292,8 +303,9 @@ protected:
|
|||
lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
|
||||
llvm::Optional<lldb_private::FileSpec> m_comp_dir;
|
||||
llvm::Optional<lldb_private::FileSpec> m_file_spec;
|
||||
dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base
|
||||
dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base
|
||||
dw_addr_t m_addr_base = 0; ///< Value of DW_AT_addr_base.
|
||||
dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base.
|
||||
dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base.
|
||||
|
||||
/// Value of DW_AT_stmt_list.
|
||||
dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;
|
||||
|
@ -301,6 +313,7 @@ protected:
|
|||
dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base.
|
||||
|
||||
llvm::Optional<llvm::DWARFDebugRnglistTable> m_rnglist_table;
|
||||
llvm::Optional<llvm::DWARFListTableHeader> m_loclist_table_header;
|
||||
|
||||
const DIERef::Section m_section;
|
||||
|
||||
|
|
|
@ -3357,7 +3357,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
|||
die.GetCU());
|
||||
} else {
|
||||
DataExtractor data = DebugLocData();
|
||||
const dw_offset_t offset = form_value.Unsigned();
|
||||
dw_offset_t offset = form_value.Unsigned();
|
||||
if (form_value.Form() == DW_FORM_loclistx)
|
||||
offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
|
||||
if (data.ValidOffset(offset)) {
|
||||
data = DataExtractor(data, offset, data.GetByteSize() - offset);
|
||||
location = DWARFExpression(module, data, die.GetCU());
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
# REQUIRES: x86
|
||||
|
||||
# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t
|
||||
# RUN: %lldb %t -o "image lookup -v -s lookup_loclists" -o exit | FileCheck %s
|
||||
|
||||
# CHECK-LABEL: image lookup -v -s lookup_loclists
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg0 RAX,
|
||||
# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = ,
|
||||
|
||||
loclists:
|
||||
nop
|
||||
.Ltmp0:
|
||||
nop
|
||||
lookup_loclists:
|
||||
.Ltmp1:
|
||||
nop
|
||||
.Ltmp2:
|
||||
nop
|
||||
.Ltmp3:
|
||||
nop
|
||||
.Ltmp4:
|
||||
nop
|
||||
.Lloclists_end:
|
||||
|
||||
.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 1 # Offset entry count
|
||||
.Lloclists_table_base:
|
||||
.long .Ldebug_loc0-.Lloclists_table_base
|
||||
.long .Ldebug_loc1-.Lloclists_table_base
|
||||
.Ldebug_loc0:
|
||||
.byte 4 # DW_LLE_offset_pair
|
||||
.uleb128 loclists-loclists
|
||||
.uleb128 .Ltmp2-loclists
|
||||
.uleb128 1 # Expression size
|
||||
.byte 80 # super-register DW_OP_reg0
|
||||
.byte 0 # DW_LLE_end_of_list
|
||||
.Ldebug_loc1:
|
||||
.byte 4 # DW_LLE_offset_pair
|
||||
.uleb128 .Ltmp3-loclists
|
||||
.uleb128 .Ltmp4-loclists
|
||||
.uleb128 1 # Expression size
|
||||
.byte 81 # super-register DW_OP_reg1
|
||||
.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
|
||||
.uleb128 0x8c # DW_AT_loclists_base
|
||||
.byte 0x17 # DW_FORM_sec_offset
|
||||
.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 19 # DW_FORM_ref4
|
||||
.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 0x22 # DW_FORM_loclistx
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 8 # DW_FORM_string
|
||||
.byte 73 # DW_AT_type
|
||||
.byte 19 # DW_FORM_ref4
|
||||
.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
|
||||
.Lcu_begin0:
|
||||
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
|
||||
.Ldebug_info_start0:
|
||||
.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
|
||||
.long .Lloclists_table_base # DW_AT_loclists_base
|
||||
.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
|
||||
.uleb128 0 # DW_AT_location
|
||||
.asciz "x0" # DW_AT_name
|
||||
.long .Lint-.Lcu_begin0 # DW_AT_type
|
||||
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
|
||||
.uleb128 1 # DW_AT_location
|
||||
.asciz "x1" # DW_AT_name
|
||||
.long .Lint-.Lcu_begin0 # 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
|
||||
.Ldebug_info_end0:
|
Loading…
Reference in New Issue