[Lldb-commits] [llvm] [lldb] [DoNotMerge] DW_IDX_parent full implementation (PR #77121)

Felipe de Azevedo Piovezan via lldb-commits lldb-commits at lists.llvm.org
Fri Jan 19 11:32:56 PST 2024


https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/77121

>From 6d5fec644004c4c1ad84ef29761306651f22fcf7 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 7 Dec 2023 11:24:39 -0800
Subject: [PATCH 1/3] [llvm][DebugNames] Implement Entry::GetParentEntry query

---
 .../DebugInfo/DWARF/DWARFAcceleratorTable.h     | 17 +++++++++++++++++
 .../DebugInfo/DWARF/DWARFAcceleratorTable.cpp   | 15 +++++++++++++++
 llvm/test/CodeGen/X86/dwarf-headers.o           |  0
 3 files changed, 32 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/dwarf-headers.o

diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index b89536bc0c7230c..de743216677938b 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -460,6 +460,16 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
     /// Returns the Offset of the DIE within the containing CU or TU.
     std::optional<uint64_t> getDIEUnitOffset() const;
 
+    /// Returns true if this Entry has information about its parent DIE (i.e. if
+    /// it has an IDX_parent attribute)
+    bool hasParentInformation() const;
+
+    /// Returns the Entry corresponding to the parent of the DIE represented by
+    /// `this` Entry. If the parent is not in the table, nullopt is returned.
+    /// Precondition: hasParentInformation() == true.
+    /// An error is returned for ill-formed tables.
+    Expected<std::optional<DWARFDebugNames::Entry>> getParentDIEEntry() const;
+
     /// Return the Abbreviation that can be used to interpret the raw values of
     /// this Accelerator Entry.
     const Abbrev &getAbbrev() const { return *Abbr; }
@@ -609,6 +619,13 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
 
     Expected<Entry> getEntry(uint64_t *Offset) const;
 
+    // Returns the Entry at the relative `Offset` from the start of the Entry
+    // pool.
+    Expected<Entry> getEntryAtRelativeOffset(uint64_t Offset) const {
+      auto OffsetFromSection = Offset + this->EntriesBase;
+      return getEntry(&OffsetFromSection);
+    }
+
     /// Look up all entries in this Name Index matching \c Key.
     iterator_range<ValueIterator> equal_range(StringRef Key) const;
 
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 0f9c8ef485d456e..d09c5e541a9cc9a 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -611,6 +611,10 @@ DWARFDebugNames::Entry::lookup(dwarf::Index Index) const {
   return std::nullopt;
 }
 
+bool DWARFDebugNames::Entry::hasParentInformation() const {
+  return lookup(dwarf::DW_IDX_parent).has_value();
+}
+
 std::optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
   if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
     return Off->getAsReferenceUVal();
@@ -650,6 +654,17 @@ std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUIndex() const {
   return std::nullopt;
 }
 
+Expected<std::optional<DWARFDebugNames::Entry>>
+DWARFDebugNames::Entry::getParentDIEEntry() const {
+  // The offset of the accelerator table entry for the parent.
+  std::optional<DWARFFormValue> ParentEntryOff = lookup(dwarf::DW_IDX_parent);
+  assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");
+
+  if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)
+    return std::nullopt;
+  return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());
+}
+
 void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const {
   W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
   W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
diff --git a/llvm/test/CodeGen/X86/dwarf-headers.o b/llvm/test/CodeGen/X86/dwarf-headers.o
new file mode 100644
index 000000000000000..e69de29bb2d1d64

>From d0dea8281695c7174901215fe5bfbf79270985ce Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 7 Dec 2023 11:26:52 -0800
Subject: [PATCH 2/3] [lldb][DWARFUnit] Implement PeekDIEName query

This allows us to query the AT_Name of a DIE without parsing the entire CU.

Part of the ongoing effort to support IDX_Parent in accelerator tables [1].

[1]: https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/44
---
 .../SymbolFile/DWARF/DWARFDebugInfo.cpp       |  6 ++
 .../Plugins/SymbolFile/DWARF/DWARFDebugInfo.h |  5 ++
 .../SymbolFile/DWARF/DWARFFormValue.cpp       | 24 +++---
 .../Plugins/SymbolFile/DWARF/DWARFFormValue.h |  6 ++
 .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp    | 24 ++++++
 .../Plugins/SymbolFile/DWARF/DWARFUnit.h      |  5 ++
 .../SymbolFile/DWARF/DWARFDIETest.cpp         | 83 +++++++++++++++++++
 7 files changed, 143 insertions(+), 10 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 553b6a4c551d205..340b9acf80d023b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -191,3 +191,9 @@ DWARFDebugInfo::GetDIE(const DIERef &die_ref) {
     return cu->GetNonSkeletonUnit().GetDIE(die_ref.die_offset());
   return DWARFDIE(); // Not found
 }
+
+llvm::StringRef DWARFDebugInfo::PeekDIEName(const DIERef &die_ref) {
+  if (DWARFUnit *cu = GetUnit(die_ref))
+    return cu->GetNonSkeletonUnit().PeekDIEName(die_ref.die_offset());
+  return llvm::StringRef();
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index d5e48f312ea0e98..a8b5abc3beed2d0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -43,6 +43,11 @@ class DWARFDebugInfo {
   bool ContainsTypeUnits();
   DWARFDIE GetDIE(const DIERef &die_ref);
 
+  /// Returns the AT_Name of this DIE, if it exists, without parsing the entire
+  /// compile unit. An empty is string is returned upon error or if the
+  /// attribute is not present.
+  llvm::StringRef PeekDIEName(const DIERef &die_ref);
+
   enum {
     eDumpFlag_Verbose = (1 << 0),  // Verbose dumping
     eDumpFlag_ShowForm = (1 << 1), // Show the DW_form type
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 0a7029a55c047bb..e1f73f1997e3692 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -18,8 +18,6 @@
 #include "DWARFFormValue.h"
 #include "DWARFUnit.h"
 
-class DWARFUnit;
-
 using namespace lldb_private;
 using namespace lldb_private::dwarf;
 using namespace lldb_private::plugin::dwarf;
@@ -502,7 +500,8 @@ dw_addr_t DWARFFormValue::Address() const {
       &offset, index_size);
 }
 
-DWARFDIE DWARFFormValue::Reference() const {
+std::pair<DWARFUnit *, uint64_t>
+DWARFFormValue::ReferencedUnitAndOffset() const {
   uint64_t value = m_value.value.uval;
   switch (m_form) {
   case DW_FORM_ref1:
@@ -516,9 +515,9 @@ DWARFDIE DWARFFormValue::Reference() const {
     if (!m_unit->ContainsDIEOffset(value)) {
       m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
           "DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value);
-      return {};
+      return {nullptr, 0};
     }
-    return const_cast<DWARFUnit *>(m_unit)->GetDIE(value);
+    return {const_cast<DWARFUnit *>(m_unit), value};
 
   case DW_FORM_ref_addr: {
     DWARFUnit *ref_cu =
@@ -527,24 +526,29 @@ DWARFDIE DWARFFormValue::Reference() const {
     if (!ref_cu) {
       m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
           "DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value);
-      return {};
+      return {nullptr, 0};
     }
-    return ref_cu->GetDIE(value);
+    return {ref_cu, value};
   }
 
   case DW_FORM_ref_sig8: {
     DWARFTypeUnit *tu =
         m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value);
     if (!tu)
-      return {};
-    return tu->GetDIE(tu->GetTypeOffset());
+      return {nullptr, 0};
+    return {tu, tu->GetTypeOffset()};
   }
 
   default:
-    return {};
+    return {nullptr, 0};
   }
 }
 
+DWARFDIE DWARFFormValue::Reference() const {
+  auto [unit, offset] = ReferencedUnitAndOffset();
+  return unit ? unit->GetDIE(offset) : DWARFDIE();
+}
+
 uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
   uint64_t value = m_value.value.uval;
   switch (m_form) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index 445749a6aac3ac7..fdd5b3c278a4e80 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -60,6 +60,12 @@ class DWARFFormValue {
                                              const DWARFUnit *u);
   std::optional<uint8_t> GetFixedSize() const;
   DWARFDIE Reference() const;
+
+  /// If this is a reference to another DIE, return the corresponding DWARFUnit
+  /// and DIE offset such that Unit->GetDIE(offset) produces the desired DIE.
+  /// Otherwise, a nullptr and unspecified offset are returned.
+  std::pair<DWARFUnit *, uint64_t> ReferencedUnitAndOffset() const;
+
   uint64_t Reference(dw_offset_t offset) const;
   bool Boolean() const { return m_value.value.uval != 0; }
   uint64_t Unsigned() const { return m_value.value.uval; }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 0e2f4d45543bb53..7a40361cdede7a7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -663,6 +663,30 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) {
   return DWARFDIE(); // Not found
 }
 
+llvm::StringRef DWARFUnit::PeekDIEName(dw_offset_t die_offset) {
+  DWARFDebugInfoEntry die;
+  if (!die.Extract(GetData(), this, &die_offset))
+    return llvm::StringRef();
+
+  // Does die contain a DW_AT_Name?
+  if (const char *name =
+          die.GetAttributeValueAsString(this, DW_AT_name, nullptr))
+    return name;
+
+  // Does its DW_AT_specification or DW_AT_abstract_origin contain an AT_Name?
+  for (auto attr : {DW_AT_specification, DW_AT_abstract_origin}) {
+    DWARFFormValue form_value;
+    if (!die.GetAttributeValue(this, attr, form_value))
+      continue;
+    auto [unit, offset] = form_value.ReferencedUnitAndOffset();
+    if (unit)
+      if (auto name = unit->PeekDIEName(offset); !name.empty())
+        return name;
+  }
+
+  return llvm::StringRef();
+}
+
 DWARFUnit &DWARFUnit::GetNonSkeletonUnit() {
   ExtractUnitDIEIfNeeded();
   if (m_dwo)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 3f528e913d8cfab..bc225a52e1d0309 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -187,6 +187,11 @@ class DWARFUnit : public UserID {
 
   DWARFDIE GetDIE(dw_offset_t die_offset);
 
+  /// Returns the AT_Name of the DIE at `die_offset`, if it exists, without
+  /// parsing the entire compile unit. An empty is string is returned upon
+  /// error or if the attribute is not present.
+  llvm::StringRef PeekDIEName(dw_offset_t die_offset);
+
   DWARFUnit &GetNonSkeletonUnit();
 
   static uint8_t GetAddressByteSize(const DWARFUnit *cu);
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
index 8497855b2f3db59..bcb211815f9f351 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
 #include "TestingSupport/Symbol/YAMLModuleTester.h"
 #include "llvm/ADT/STLExtras.h"
 #include "gmock/gmock.h"
@@ -104,3 +105,85 @@ TEST(DWARFDIETest, ChildIteration) {
   DWARFDIE no_children_die(unit, die_child0);
   EXPECT_TRUE(no_children_die.children().empty());
 }
+
+TEST(DWARFDIETest, PeekName) {
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_386
+DWARF:
+  debug_str:
+    - 'NameType1'
+    - 'NameType2'
+  debug_abbrev:
+    - Table:
+        - Code:            0x00000001
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+        - Code:            0x00000002
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+        - Code:            0x00000003
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_abstract_origin
+              Form:            DW_FORM_ref1
+        - Code:            0x00000004
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_specification
+              Form:            DW_FORM_ref1
+  debug_info:
+    - Version:         4
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x00000001
+          Values:
+            - Value:           0x000000000000000C
+        - AbbrCode:        0x00000002
+          Values:
+            - Value:           0x0000000000000000 # Name = NameType1
+        - AbbrCode:        0x00000002
+          Values:
+            - Value:           0x000000000000000a # Name = NameType2
+        - AbbrCode:        0x00000003
+          Values:
+            - Value:           0x000000000000000e # Ref abstract origin to NameType1 DIE.
+        - AbbrCode:        0x00000004
+          Values:
+            - Value:           0x0000000000000013 # Ref specification to NameType2 DIE.
+        - AbbrCode:        0x00000000
+)";
+
+  YAMLModuleTester t(yamldata);
+  auto *symbol_file =
+      llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
+  auto &debug_info = symbol_file->DebugInfo();
+
+  DIERef first_die(std::nullopt, DIERef::Section::DebugInfo,
+                   11 /*FirstDIEOffset*/);
+  EXPECT_EQ(debug_info.PeekDIEName(first_die), "");
+
+  DIERef second_die(std::nullopt, DIERef::Section::DebugInfo, 14);
+  EXPECT_EQ(debug_info.PeekDIEName(second_die), "NameType1");
+
+  DIERef third_die(std::nullopt, DIERef::Section::DebugInfo, 19);
+  EXPECT_EQ(debug_info.PeekDIEName(third_die), "NameType2");
+
+  DIERef fourth_die(std::nullopt, DIERef::Section::DebugInfo, 24);
+  EXPECT_EQ(debug_info.PeekDIEName(fourth_die), "NameType1");
+
+  DIERef fifth_die(std::nullopt, DIERef::Section::DebugInfo, 26);
+  EXPECT_EQ(debug_info.PeekDIEName(fifth_die), "NameType2");
+}

>From 52dc223f049adaa605c6be6267eedb6539dafd0c Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 4 Jan 2024 12:56:25 -0300
Subject: [PATCH 3/3] [lldb][DWARFIndex] Use IDX_parent to implement
 GetFullyQualifiedType query

This commit changes DebugNamesDWARFIndex so that it now overrides
`GetFullyQualifiedType` and attempts to use DW_IDX_parent, when available, to
speed up such queries. When this type of information is not available, the
base-class implementation is used.
---
 .../SymbolFile/DWARF/DebugNamesDWARFIndex.cpp | 98 +++++++++++++++++++
 .../SymbolFile/DWARF/DebugNamesDWARFIndex.h   |  9 ++
 2 files changed, 107 insertions(+)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
index b718f98340a70bf..e7b2a4b59f3f024 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -13,6 +13,7 @@
 #include "lldb/Core/Module.h"
 #include "lldb/Utility/RegularExpression.h"
 #include "lldb/Utility/Stream.h"
+#include "llvm/ADT/Sequence.h"
 #include <optional>
 
 using namespace lldb_private;
@@ -218,6 +219,103 @@ void DebugNamesDWARFIndex::GetCompleteObjCClass(
   m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
 }
 
+namespace {
+using Entry = llvm::DWARFDebugNames::Entry;
+
+// If `entry` and all of its parents have an `IDX_parent`, use that information
+// to build and return a list of at most `max_parents` parent Entries.
+// `entry` itself is not included in the list.
+// If any parent does not have an `IDX_parent`, nullopt is returned.
+static std::optional<llvm::SmallVector<Entry, 4>>
+getParentChain(Entry entry, uint32_t max_parents) {
+  llvm::SmallVector<Entry, 4> parent_entries;
+
+  do {
+    if (!entry.hasParentInformation())
+      return std::nullopt;
+
+    llvm::Expected<std::optional<Entry>> parent = entry.getParentDIEEntry();
+    if (!parent) { // Bad data.
+      consumeError(parent.takeError());
+      return std::nullopt;
+    }
+
+    // Last parent in the chain
+    if (!parent->has_value())
+      break;
+
+    parent_entries.push_back(**parent);
+    entry = **parent;
+  } while (parent_entries.size() < max_parents);
+
+  return parent_entries;
+}
+} // namespace
+
+void DebugNamesDWARFIndex::GetFullyQualifiedType(
+    const DWARFDeclContext &context,
+    llvm::function_ref<bool(DWARFDIE die)> callback) {
+
+  // Fallback: use the base class implementation.
+  auto fallback_impl = [&](const DebugNames::Entry &entry) {
+    return ProcessEntry(entry, [&](DWARFDIE die) {
+      return GetFullyQualifiedTypeImpl(context, die, callback);
+    });
+  };
+
+  if (context.GetSize() == 0)
+    return;
+  llvm::StringRef leaf_name = context[0].name;
+  auto parent_names = llvm::to_vector_of<llvm::StringRef>(
+      llvm::map_range(llvm::seq<int>(1, context.GetSize()),
+                      [&](int idx) { return context[idx].name; }));
+
+  for (const DebugNames::Entry &entry :
+       m_debug_names_up->equal_range(leaf_name)) {
+    if (!isType(entry.tag()))
+      continue;
+
+    // Grab at most one extra parent, extra parents are not useful to test
+    // equality.
+    auto parent_chain = getParentChain(entry, parent_names.size() + 1);
+
+    if (!parent_chain) {
+      if (!fallback_impl(entry))
+        return;
+      continue;
+    }
+
+    if (CheckParentChain(parent_names, *parent_chain) &&
+        (!ProcessEntry(entry, callback)))
+      return;
+  }
+}
+
+bool DebugNamesDWARFIndex::CheckParentChain(
+    llvm::ArrayRef<llvm::StringRef> expected_parent_names,
+    llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
+
+  if (parent_entries.size() != expected_parent_names.size())
+    return false;
+
+  auto CompareEntryATName = [this](llvm::StringRef expected_name,
+                                   const DebugNames::Entry &entry) {
+    auto maybe_dieoffset = entry.getDIEUnitOffset();
+    if (!maybe_dieoffset)
+      return false;
+    auto die_ref = ToDIERef(entry);
+    if (!die_ref)
+      return false;
+    return expected_name == m_debug_info.PeekDIEName(*die_ref);
+  };
+
+  for (auto [expected_parent_name, parent_entry] :
+       llvm::zip_equal(expected_parent_names, parent_entries))
+    if (!CompareEntryATName(expected_parent_name, parent_entry))
+      return false;
+  return true;
+}
+
 void DebugNamesDWARFIndex::GetTypes(
     ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
   for (const DebugNames::Entry &entry :
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
index cca0913c4124c91..15eff7a26596333 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
@@ -14,6 +14,7 @@
 #include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
 #include "lldb/Utility/ConstString.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
 #include <optional>
 
@@ -42,6 +43,11 @@ class DebugNamesDWARFIndex : public DWARFIndex {
   void GetCompleteObjCClass(
       ConstString class_name, bool must_be_implementation,
       llvm::function_ref<bool(DWARFDIE die)> callback) override;
+
+  /// Uses DWARF5's IDX_parent fields, when available, to speed up this query.
+  void GetFullyQualifiedType(
+      const DWARFDeclContext &context,
+      llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetTypes(ConstString name,
                 llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetTypes(const DWARFDeclContext &context,
@@ -83,6 +89,9 @@ class DebugNamesDWARFIndex : public DWARFIndex {
   bool ProcessEntry(const DebugNames::Entry &entry,
                     llvm::function_ref<bool(DWARFDIE die)> callback);
 
+  bool CheckParentChain(llvm::ArrayRef<llvm::StringRef> parent_names,
+                        llvm::ArrayRef<DebugNames::Entry> parent_entries) const;
+
   static void MaybeLogLookupError(llvm::Error error,
                                   const DebugNames::NameIndex &ni,
                                   llvm::StringRef name);



More information about the lldb-commits mailing list