https://github.com/labath created https://github.com/llvm/llvm-project/pull/116620
The main difference is that the llvm class (just a std::vector in disguise) is not sorted. It turns out this isn't an issue because the callers either: - ignore the range list; - convert it to a different format (which is then sorted); - or query the minimum value (which is faster than sorting) The last case is something I want to get rid of in a followup as a part of removing the assumption that function's entry point is also its lowest address. >From 08a947e3a8d6a76d7898a1f3390c4f2ac0446702 Mon Sep 17 00:00:00 2001 From: Pavel Labath <pa...@labath.sk> Date: Mon, 18 Nov 2024 14:33:40 +0100 Subject: [PATCH] [lldb/DWARF] s/DWARFRangeList/llvm::DWARFAddressRangeVector The main difference is that the llvm class (just a std::vector in disguise) is not sorted. It turns out this isn't an issue because the callers either: - ignore the range list; - convert it to a different format (which is then sorted); - or query the minimum value (which is faster than sorting) The last case is something I want to get rid of in a followup as a part of removing the assumption that function's entry point is also its lowest address. --- lldb/include/lldb/Core/dwarf.h | 3 - lldb/source/Plugins/SymbolFile/DWARF/DIERef.h | 3 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 3 +- .../SymbolFile/DWARF/DWARFCompileUnit.cpp | 19 ++-- .../Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 43 +++++---- .../Plugins/SymbolFile/DWARF/DWARFDIE.h | 11 ++- .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 95 +++++++++---------- .../SymbolFile/DWARF/DWARFDebugInfoEntry.h | 20 ++-- .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 67 ++++++------- .../Plugins/SymbolFile/DWARF/DWARFUnit.h | 7 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 87 +++++++++-------- 11 files changed, 184 insertions(+), 174 deletions(-) diff --git a/lldb/include/lldb/Core/dwarf.h b/lldb/include/lldb/Core/dwarf.h index e162a090ba7c97..4de5c8f24db02c 100644 --- a/lldb/include/lldb/Core/dwarf.h +++ b/lldb/include/lldb/Core/dwarf.h @@ -9,7 +9,6 @@ #ifndef LLDB_CORE_DWARF_H #define LLDB_CORE_DWARF_H -#include "lldb/Utility/RangeMap.h" #include <cstdint> // Get the DWARF constant definitions from llvm @@ -40,6 +39,4 @@ typedef uint64_t dw_offset_t; // Dwarf Debug Information Entry offset for any #define DW_EH_PE_MASK_ENCODING 0x0F -typedef lldb_private::RangeVector<dw_addr_t, dw_addr_t, 2> DWARFRangeList; - #endif // LLDB_CORE_DWARF_H diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h b/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h index ad443aacb46ecc..69be0aa1280c16 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -10,7 +10,8 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DIEREF_H #include "lldb/Core/dwarf.h" -#include "lldb/Utility/LLDBAssert.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" #include <cassert> #include <optional> diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index d9bdeb560e1220..05d994ae82d8d4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -45,6 +45,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/Demangle/Demangle.h" #include <map> @@ -2353,7 +2354,7 @@ DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) { Function *DWARFASTParserClang::ParseFunctionFromDWARF( CompileUnit &comp_unit, const DWARFDIE &die, AddressRanges func_ranges) { - DWARFRangeList unused_func_ranges; + llvm::DWARFAddressRangesVector unused_func_ranges; const char *name = nullptr; const char *mangled = nullptr; std::optional<int> decl_file; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index ec4c297cf7e164..7f2edbfa95feef 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -8,11 +8,13 @@ #include "DWARFCompileUnit.h" #include "DWARFDebugAranges.h" +#include "LogChannelDWARF.h" #include "SymbolFileDWARFDebugMap.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Utility/Stream.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" using namespace lldb; using namespace lldb_private; @@ -41,14 +43,17 @@ void DWARFCompileUnit::BuildAddressRangeTable( const dw_offset_t cu_offset = GetOffset(); if (die) { - DWARFRangeList ranges = + llvm::Expected<llvm::DWARFAddressRangesVector> ranges = die->GetAttributeAddressRanges(this, /*check_hi_lo_pc=*/true); - for (const DWARFRangeList::Entry &range : ranges) - debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), - range.GetRangeEnd()); - - if (!ranges.IsEmpty()) - return; + if (ranges) { + for (const llvm::DWARFAddressRange &range : *ranges) + debug_aranges->AppendRange(cu_offset, range.LowPC, range.HighPC); + if (!ranges->empty()) + return; + } else { + LLDB_LOG_ERROR(GetLog(DWARFLog::DebugInfo), ranges.takeError(), + "{1:x}: {0}", cu_offset); + } } if (debug_aranges->GetNumRanges() == num_debug_aranges) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 4c9f1d8505f6e6..ac63b50c3ba2d4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -13,10 +13,12 @@ #include "DWARFDebugInfoEntry.h" #include "DWARFDeclContext.h" #include "DWARFUnit.h" +#include "LogChannelDWARF.h" #include "lldb/Symbol/Type.h" #include "llvm/ADT/iterator.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" using namespace lldb_private; using namespace lldb_private::dwarf; @@ -172,21 +174,27 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t address) const { } if (match_addr_range) { - DWARFRangeList ranges = - m_die->GetAttributeAddressRanges(m_cu, /*check_hi_lo_pc=*/true); - if (ranges.FindEntryThatContains(address)) { - check_children = true; - switch (Tag()) { - default: - break; - - case DW_TAG_inlined_subroutine: // Inlined Function - case DW_TAG_lexical_block: // Block { } in code - result = *this; - break; + if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges = + m_die->GetAttributeAddressRanges(m_cu, /*check_hi_lo_pc=*/true)) { + bool addr_in_range = + llvm::any_of(*ranges, [&](const llvm::DWARFAddressRange &r) { + return r.LowPC <= address && address < r.HighPC; + }); + if (addr_in_range) { + switch (Tag()) { + default: + break; + + case DW_TAG_inlined_subroutine: // Inlined Function + case DW_TAG_lexical_block: // Block { } in code + result = *this; + break; + } } + check_children = addr_in_range; } else { - check_children = false; + LLDB_LOG_ERROR(GetLog(DWARFLog::DebugInfo), ranges.takeError(), + "DIE({1:x}): {0}", GetID()); } } @@ -559,10 +567,11 @@ bool DWARFDIE::IsMethod() const { } bool DWARFDIE::GetDIENamesAndRanges( - const char *&name, const char *&mangled, DWARFRangeList &ranges, - std::optional<int> &decl_file, std::optional<int> &decl_line, - std::optional<int> &decl_column, std::optional<int> &call_file, - std::optional<int> &call_line, std::optional<int> &call_column, + const char *&name, const char *&mangled, + llvm::DWARFAddressRangesVector &ranges, std::optional<int> &decl_file, + std::optional<int> &decl_line, std::optional<int> &decl_column, + std::optional<int> &call_file, std::optional<int> &call_line, + std::optional<int> &call_column, lldb_private::DWARFExpressionList *frame_base) const { if (IsValid()) { return m_die->GetDIENamesAndRanges( diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index 077b78eb26d0c3..64421a5f16559b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -12,6 +12,7 @@ #include "DWARFBaseDIE.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" namespace lldb_private::plugin { namespace dwarf { @@ -97,11 +98,11 @@ class DWARFDIE : public DWARFBaseDIE { GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const; bool GetDIENamesAndRanges( - const char *&name, const char *&mangled, DWARFRangeList &ranges, - std::optional<int> &decl_file, std::optional<int> &decl_line, - std::optional<int> &decl_column, std::optional<int> &call_file, - std::optional<int> &call_line, std::optional<int> &call_column, - DWARFExpressionList *frame_base) const; + const char *&name, const char *&mangled, + llvm::DWARFAddressRangesVector &ranges, std::optional<int> &decl_file, + std::optional<int> &decl_line, std::optional<int> &decl_column, + std::optional<int> &call_file, std::optional<int> &call_line, + std::optional<int> &call_column, DWARFExpressionList *frame_base) const; /// The range of all the children of this DIE. llvm::iterator_range<child_iterator> children() const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 4ecb2ed616a128..0575d30d4fc315 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -14,13 +14,15 @@ #include <limits> #include <optional> -#include "llvm/Support/LEB128.h" - +#include "LogChannelDWARF.h" #include "lldb/Core/Module.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Utility/Stream.h" -#include "lldb/Utility/StreamString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/LEB128.h" #include "DWARFCompileUnit.h" #include "DWARFDebugAranges.h" @@ -31,8 +33,6 @@ #include "SymbolFileDWARF.h" #include "SymbolFileDWARFDwo.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" - using namespace lldb_private; using namespace lldb_private::dwarf; using namespace lldb_private::plugin::dwarf; @@ -82,24 +82,11 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, return true; } -static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit, - const DWARFDebugInfoEntry &die, - const DWARFFormValue &value) { - llvm::Expected<DWARFRangeList> 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( - "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but " - "range extraction failed ({3}), please file a bug " - "and attach the file at the start of this error message", - die.GetOffset(), - llvm::dwarf::FormEncodingString(value.Form()).str().c_str(), - value.Unsigned(), toString(expected_ranges.takeError()).c_str()); - return DWARFRangeList(); +static llvm::Expected<llvm::DWARFAddressRangesVector> +GetRanges(DWARFUnit &unit, const DWARFFormValue &value) { + return (value.Form() == DW_FORM_rnglistx) + ? unit.FindRnglistFromIndex(value.Unsigned()) + : unit.FindRnglistFromOffset(value.Unsigned()); } static void ExtractAttrAndFormValue( @@ -117,7 +104,7 @@ static void ExtractAttrAndFormValue( // DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes. bool DWARFDebugInfoEntry::GetDIENamesAndRanges( DWARFUnit *cu, const char *&name, const char *&mangled, - DWARFRangeList &ranges, std::optional<int> &decl_file, + llvm::DWARFAddressRangesVector &ranges, std::optional<int> &decl_file, std::optional<int> &decl_line, std::optional<int> &decl_column, std::optional<int> &call_file, std::optional<int> &call_line, std::optional<int> &call_column, DWARFExpressionList *frame_base) const { @@ -173,7 +160,17 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( break; case DW_AT_ranges: - ranges = GetRangesOrReportError(*cu, *this, form_value); + if (llvm::Expected<llvm::DWARFAddressRangesVector> r = + GetRanges(*cu, form_value)) { + ranges = std::move(*r); + } else { + module->ReportError( + "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but " + "range extraction failed ({3}), please file a bug " + "and attach the file at the start of this error message", + GetOffset(), llvm::dwarf::FormEncodingString(form_value.Form()), + form_value.Unsigned(), fmt_consume(r.takeError())); + } break; case DW_AT_name: @@ -259,22 +256,19 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( } } - if (ranges.IsEmpty()) { - if (lo_pc != LLDB_INVALID_ADDRESS) { - if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc) - ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); - else - ranges.Append(DWARFRangeList::Entry(lo_pc, 0)); - } + if (ranges.empty() && lo_pc != LLDB_INVALID_ADDRESS) { + ranges.emplace_back( + lo_pc, (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc) ? hi_pc : 0); } - if (set_frame_base_loclist_addr) { - dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0); + if (set_frame_base_loclist_addr && !ranges.empty()) { + // TODO: Use the first range instead. + dw_addr_t lowest_range_pc = llvm::min_element(ranges)->LowPC; assert(lowest_range_pc >= cu->GetBaseAddress()); frame_base->SetFuncFileAddress(lowest_range_pc); } - if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) { + if (ranges.empty() || name == nullptr || mangled == nullptr) { for (const DWARFDIE &die : dies) { if (die) { die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges, @@ -283,7 +277,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( } } } - return !ranges.IsEmpty(); + return !ranges.empty(); } // Get all attribute values for a given DIE, including following any @@ -499,24 +493,23 @@ bool DWARFDebugInfoEntry::GetAttributeAddressRange( return false; } -DWARFRangeList DWARFDebugInfoEntry::GetAttributeAddressRanges( +llvm::Expected<llvm::DWARFAddressRangesVector> +DWARFDebugInfoEntry::GetAttributeAddressRanges( DWARFUnit *cu, bool check_hi_lo_pc, bool check_elaborating_dies) const { DWARFFormValue form_value; if (GetAttributeValue(cu, DW_AT_ranges, form_value)) - return GetRangesOrReportError(*cu, *this, form_value); + return GetRanges(*cu, form_value); - DWARFRangeList ranges; if (check_hi_lo_pc) { dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS, - check_elaborating_dies)) { - if (lo_pc < hi_pc) - ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); - } + check_elaborating_dies) && + lo_pc < hi_pc) + return llvm::DWARFAddressRangesVector{{lo_pc, hi_pc}}; } - return ranges; + return llvm::createStringError("DIE has no address range information"); } // GetName @@ -577,13 +570,15 @@ const char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const { /// table instead of the compile unit offset. void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable( DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const { + Log *log = GetLog(DWARFLog::DebugInfo); if (m_tag) { if (m_tag == DW_TAG_subprogram) { - DWARFRangeList ranges = - GetAttributeAddressRanges(cu, /*check_hi_lo_pc=*/true); - for (const auto &r : ranges) { - debug_aranges->AppendRange(GetOffset(), r.GetRangeBase(), - r.GetRangeEnd()); + if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges = + GetAttributeAddressRanges(cu, /*check_hi_lo_pc=*/true)) { + for (const auto &r : *ranges) + debug_aranges->AppendRange(GetOffset(), r.LowPC, r.HighPC); + } else { + LLDB_LOG_ERROR(log, ranges.takeError(), "DIE({1:x}): {0}", GetOffset()); } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 0e50aab3292ae6..de6bbf1d527899 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -10,7 +10,6 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H #include "SymbolFileDWARF.h" -#include "llvm/ADT/SmallVector.h" #include "DWARFAttribute.h" #include "DWARFBaseDIE.h" @@ -20,6 +19,7 @@ #include <vector> #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" namespace lldb_private::plugin { namespace dwarf { @@ -95,7 +95,7 @@ class DWARFDebugInfoEntry { dw_addr_t &hi_pc, uint64_t fail_value, bool check_elaborating_dies = false) const; - DWARFRangeList + llvm::Expected<llvm::DWARFAddressRangesVector> GetAttributeAddressRanges(DWARFUnit *cu, bool check_hi_lo_pc, bool check_elaborating_dies = false) const; @@ -106,15 +106,13 @@ class DWARFDebugInfoEntry { const char *GetPubname(const DWARFUnit *cu) const; - bool GetDIENamesAndRanges(DWARFUnit *cu, const char *&name, - const char *&mangled, DWARFRangeList &rangeList, - std::optional<int> &decl_file, - std::optional<int> &decl_line, - std::optional<int> &decl_column, - std::optional<int> &call_file, - std::optional<int> &call_line, - std::optional<int> &call_column, - DWARFExpressionList *frame_base = nullptr) const; + bool GetDIENamesAndRanges( + DWARFUnit *cu, const char *&name, const char *&mangled, + llvm::DWARFAddressRangesVector &rangeList, std::optional<int> &decl_file, + std::optional<int> &decl_line, std::optional<int> &decl_column, + std::optional<int> &call_file, std::optional<int> &call_line, + std::optional<int> &call_column, + DWARFExpressionList *frame_base = nullptr) const; const llvm::DWARFAbbreviationDeclaration * GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 0c9fd31cbfaefe..07de23f9de2fd6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -1029,9 +1029,8 @@ DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset); } -llvm::Expected<DWARFRangeList> +llvm::Expected<llvm::DWARFAddressRangesVector> DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { - llvm::DWARFAddressRangesVector llvm_ranges; if (GetVersion() <= 4) { llvm::DWARFDataExtractor data = m_dwarf.GetDWARFContext().getOrLoadRangesData().GetAsLLVMDWARF(); @@ -1040,48 +1039,38 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { llvm::DWARFDebugRangeList list; if (llvm::Error e = list.extract(data, &offset)) return e; - llvm_ranges = list.getAbsoluteRanges( + return list.getAbsoluteRanges( llvm::object::SectionedAddress{GetBaseAddress()}); - } else { - if (!GetRnglistTable()) - return llvm::createStringError(std::errc::invalid_argument, - "missing or invalid range list table"); - - llvm::DWARFDataExtractor data = GetRnglistData().GetAsLLVMDWARF(); - - // As DW_AT_rnglists_base may be missing we need to call setAddressSize. - data.setAddressSize(m_header.getAddressByteSize()); - auto range_list_or_error = GetRnglistTable()->findList(data, offset); - if (!range_list_or_error) - return range_list_or_error.takeError(); - - llvm::Expected<llvm::DWARFAddressRangesVector> expected_llvm_ranges = - range_list_or_error->getAbsoluteRanges( - llvm::object::SectionedAddress{GetBaseAddress()}, - GetAddressByteSize(), [&](uint32_t index) { - uint32_t index_size = GetAddressByteSize(); - dw_offset_t addr_base = GetAddrBase(); - lldb::offset_t offset = - addr_base + static_cast<lldb::offset_t>(index) * index_size; - return llvm::object::SectionedAddress{ - m_dwarf.GetDWARFContext().getOrLoadAddrData().GetMaxU64( - &offset, index_size)}; - }); - if (!expected_llvm_ranges) - return expected_llvm_ranges.takeError(); - llvm_ranges = std::move(*expected_llvm_ranges); } - DWARFRangeList ranges; - for (const llvm::DWARFAddressRange &llvm_range : llvm_ranges) { - ranges.Append(DWARFRangeList::Entry(llvm_range.LowPC, - llvm_range.HighPC - llvm_range.LowPC)); - } - ranges.Sort(); - return ranges; + // DWARF >= v5 + if (!GetRnglistTable()) + return llvm::createStringError(std::errc::invalid_argument, + "missing or invalid range list table"); + + llvm::DWARFDataExtractor data = GetRnglistData().GetAsLLVMDWARF(); + + // As DW_AT_rnglists_base may be missing we need to call setAddressSize. + data.setAddressSize(m_header.getAddressByteSize()); + auto range_list_or_error = GetRnglistTable()->findList(data, offset); + if (!range_list_or_error) + return range_list_or_error.takeError(); + + return range_list_or_error->getAbsoluteRanges( + llvm::object::SectionedAddress{GetBaseAddress()}, GetAddressByteSize(), + [&](uint32_t index) { + uint32_t index_size = GetAddressByteSize(); + dw_offset_t addr_base = GetAddrBase(); + lldb::offset_t offset = + addr_base + static_cast<lldb::offset_t>(index) * index_size; + return llvm::object::SectionedAddress{ + m_dwarf.GetDWARFContext().getOrLoadAddrData().GetMaxU64( + &offset, index_size)}; + }); } -llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromIndex(uint32_t index) { +llvm::Expected<llvm::DWARFAddressRangesVector> +DWARFUnit::FindRnglistFromIndex(uint32_t index) { llvm::Expected<uint64_t> maybe_offset = GetRnglistOffset(index); if (!maybe_offset) return maybe_offset.takeError(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 1267e20f087121..0a0019c25836b4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -13,6 +13,7 @@ #include "DWARFDebugInfoEntry.h" #include "lldb/Utility/XcodeSDK.h" #include "lldb/lldb-enumerations.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/Support/RWMutex.h" @@ -213,12 +214,14 @@ class DWARFUnit : public UserID { /// 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<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset); + llvm::Expected<llvm::DWARFAddressRangesVector> + FindRnglistFromOffset(dw_offset_t offset); /// 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<DWARFRangeList> FindRnglistFromIndex(uint32_t index); + llvm::Expected<llvm::DWARFAddressRangesVector> + FindRnglistFromIndex(uint32_t index); /// Return a rangelist's offset based on an index. The index designates /// an entry in the rangelist table's offset array and is supplied by diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 8ce0db4588a46a..fd42279e64b51d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -7,7 +7,8 @@ //===----------------------------------------------------------------------===// #include "SymbolFileDWARF.h" - +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/Support/Casting.h" #include "llvm/Support/FileUtilities.h" @@ -888,13 +889,13 @@ CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, const DWARFDIE &die) { ASSERT_MODULE_LOCK(this); + Log *log = GetLog(LLDBLog::Symbols); if (!die.IsValid()) return nullptr; auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU())); if (auto err = type_system_or_err.takeError()) { - LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), - "Unable to parse function: {0}"); + LLDB_LOG_ERROR(log, std::move(err), "Unable to parse function: {0}"); return nullptr; } auto ts = *type_system_or_err; @@ -906,13 +907,18 @@ Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, AddressRanges ranges; ModuleSP module_sp(die.GetModule()); - for (const auto &range : die.GetDIE()->GetAttributeAddressRanges( - die.GetCU(), /*check_hi_lo_pc=*/true)) { - if (range.base < m_first_code_address) - continue; - if (Address base_addr(range.base, module_sp->GetSectionList()); - base_addr.IsValid() && FixupAddress(base_addr)) - ranges.emplace_back(std::move(base_addr), range.size); + if (llvm::Expected<llvm::DWARFAddressRangesVector> die_ranges = + die.GetDIE()->GetAttributeAddressRanges(die.GetCU(), + /*check_hi_lo_pc=*/true)) { + for (auto &range : *die_ranges) { + if (range.valid() && range.LowPC < m_first_code_address) + continue; + if (Address base_addr(range.LowPC, module_sp->GetSectionList()); + base_addr.IsValid() && FixupAddress(base_addr)) + ranges.emplace_back(std::move(base_addr), range.HighPC - range.LowPC); + } + } else { + LLDB_LOG_ERROR(log, die_ranges.takeError(), "DIE({1:x}): {0}", die.GetID()); } if (ranges.empty()) return nullptr; @@ -1332,7 +1338,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( parent_block->AddChild(block_sp); block = block_sp.get(); } - DWARFRangeList ranges; + llvm::DWARFAddressRangesVector ranges; const char *name = nullptr; const char *mangled_name = nullptr; @@ -1345,38 +1351,37 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( if (die.GetDIENamesAndRanges(name, mangled_name, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column, nullptr)) { - if (tag == DW_TAG_subprogram) { + if (tag == DW_TAG_subprogram) assert(subprogram_low_pc == LLDB_INVALID_ADDRESS); - subprogram_low_pc = ranges.GetMinRangeBase(0); - } else if (tag == DW_TAG_inlined_subroutine) { - // We get called here for inlined subroutines in two ways. The first - // time is when we are making the Function object for this inlined - // concrete instance. Since we're creating a top level block at - // here, the subprogram_low_pc will be LLDB_INVALID_ADDRESS. So we - // need to adjust the containing address. The second time is when we - // are parsing the blocks inside the function that contains the - // inlined concrete instance. Since these will be blocks inside the - // containing "real" function the offset will be for that function. - if (subprogram_low_pc == LLDB_INVALID_ADDRESS) { - subprogram_low_pc = ranges.GetMinRangeBase(0); - } + + // We get called here for inlined subroutines in two ways. The first + // time is when we are making the Function object for this inlined + // concrete instance. Since we're creating a top level block at here, + // the subprogram_low_pc will be LLDB_INVALID_ADDRESS. So we need to + // adjust the containing address. The second time is when we are parsing + // the blocks inside the function that contains the inlined concrete + // instance. Since these will be blocks inside the containing "real" + // function the offset will be for that function. + if (tag == DW_TAG_subprogram || + (tag == DW_TAG_inlined_subroutine && + subprogram_low_pc == LLDB_INVALID_ADDRESS)) { + // TODO: Use the first address range instead. + subprogram_low_pc = llvm::min_element(ranges)->LowPC; } - const size_t num_ranges = ranges.GetSize(); - for (size_t i = 0; i < num_ranges; ++i) { - const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); - const addr_t range_base = range.GetRangeBase(); - if (range_base >= subprogram_low_pc) - block->AddRange(Block::Range(range_base - subprogram_low_pc, - range.GetByteSize())); + for (const llvm::DWARFAddressRange &range : ranges) { + if (!range.valid()) + continue; + if (range.LowPC >= subprogram_low_pc) + block->AddRange(Block::Range(range.LowPC - subprogram_low_pc, + range.HighPC - range.LowPC)); else { GetObjectFile()->GetModule()->ReportError( "{0:x8}: adding range [{1:x16}-{2:x16}) which has a base " "that is less than the function's low PC {3:x16}. Please file " "a bug and attach the file at the " "start of this error message", - block->GetID(), range_base, range.GetRangeEnd(), - subprogram_low_pc); + block->GetID(), range.LowPC, range.HighPC, subprogram_low_pc); } } block->FinalizeRanges(); @@ -3320,10 +3325,16 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { DWARFDIE function_die = GetDIE(sc.function->GetID()); dw_addr_t func_lo_pc = LLDB_INVALID_ADDRESS; - DWARFRangeList ranges = function_die.GetDIE()->GetAttributeAddressRanges( - function_die.GetCU(), /*check_hi_lo_pc=*/true); - if (!ranges.IsEmpty()) - func_lo_pc = ranges.GetMinRangeBase(0); + if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges = + function_die.GetDIE()->GetAttributeAddressRanges( + function_die.GetCU(), /*check_hi_lo_pc=*/true)) { + // TODO: Use the first range element instead. + if (!ranges->empty()) + func_lo_pc = llvm::min_element(*ranges)->LowPC; + } else { + LLDB_LOG_ERROR(GetLog(DWARFLog::DebugInfo), ranges.takeError(), + "DIE({1:x}): {0}", function_die.GetID()); + } if (func_lo_pc != LLDB_INVALID_ADDRESS) { const size_t num_variables = ParseVariablesInFunctionContext(sc, function_die, func_lo_pc); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits