diff options
| author | Pavel Labath <pavel@labath.sk> | 2019-11-22 14:42:28 +0100 |
|---|---|---|
| committer | Pavel Labath <pavel@labath.sk> | 2019-12-11 11:06:17 +0100 |
| commit | c8b74ee264a943aad29fd0864c610ba5504f73a8 (patch) | |
| tree | a3ef2b7e3ac58e1fcd569b1d8a2d8af0ebeb16ca /lldb/source/Plugins/SymbolFile | |
| parent | 46822083ef9f03ceb26db80410e47f23aa9bd7ae (diff) | |
| download | bcm5719-llvm-c8b74ee264a943aad29fd0864c610ba5504f73a8.tar.gz bcm5719-llvm-c8b74ee264a943aad29fd0864c610ba5504f73a8.zip | |
[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
Diffstat (limited to 'lldb/source/Plugins/SymbolFile')
5 files changed, 42 insertions, 3 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index e9fdfe2e479..5612c59059b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -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: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index b45d5fb2ec6..5cab4cef143 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -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: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 072cbc2abc3..77c3b9835cd 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -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; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index fe64222f8f5..81a7fc4ea5a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -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; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 8178ccd272f..658158d94a2 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -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()); |

