[Lldb-commits] [lldb] [llvm] [DO NOT MERGE][DebugInfo] Implement debug_names's IDX_parent attribute (PR #75365)

Felipe de Azevedo Piovezan via lldb-commits lldb-commits at lists.llvm.org
Tue Jan 2 05:15:36 PST 2024


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

>From 1fafdee241e98c469a3a06e29d4a375bd8af1ca0 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Mon, 11 Dec 2023 12:42:40 -0300
Subject: [PATCH 1/9] [lldb][[DWARFDeclContext] Add function to extract
 qualified names as vector

---
 .../SymbolFile/DWARF/DWARFDeclContext.cpp     |   6 +
 .../SymbolFile/DWARF/DWARFDeclContext.h       |   5 +
 .../SymbolFile/DWARF/DWARFDIETest.cpp         | 109 ++++++++++++++++++
 3 files changed, 120 insertions(+)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
index 44421c0eda3eec..3cdb47d50bbfc0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
@@ -55,6 +55,12 @@ const char *DWARFDeclContext::GetQualifiedName() const {
   return m_qualified_name.c_str();
 }
 
+llvm::SmallVector<llvm::StringRef>
+DWARFDeclContext::GetQualifiedNameAsVector() const {
+  return llvm::to_vector_of<llvm::StringRef>(
+      llvm::map_range(m_entries, GetName));
+}
+
 bool DWARFDeclContext::operator==(const DWARFDeclContext &rhs) const {
   if (m_entries.size() != rhs.m_entries.size())
     return false;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index a20a862d340296..40ebb72c91d8f0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -68,6 +68,11 @@ class DWARFDeclContext {
 
   const char *GetQualifiedName() const;
 
+  /// Returns a vector of string, one string per entry in the fully qualified
+  /// name. For example, for the name `A::B::C`, this methods returns `{"A",
+  /// "B", "C"}`
+  llvm::SmallVector<llvm::StringRef> GetQualifiedNameAsVector() const;
+
   // Same as GetQualifiedName, but the life time of the returned string will
   // be that of the LLDB session.
   ConstString GetQualifiedNameAsConstString() const {
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
index 8497855b2f3db5..5672270ee31f89 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
@@ -7,8 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
 #include "TestingSupport/Symbol/YAMLModuleTester.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -104,3 +106,110 @@ TEST(DWARFDIETest, ChildIteration) {
   DWARFDIE no_children_die(unit, die_child0);
   EXPECT_TRUE(no_children_die.children().empty());
 }
+
+TEST(DWARFDIETest, DeclContext) {
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_386
+DWARF:
+  debug_str:
+    - 'mynamespace'
+    - 'mystruct'
+    - 'mytype'
+  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_structure_type
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+        - Code:            0x00000003
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+        - Code:            0x00000004
+          Tag:             DW_TAG_namespace
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+  debug_info:
+    - Version:         4
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x00000001 # compile_unit
+          Values:
+            - Value:           0x000000000000000C
+        - AbbrCode:        0x00000004 # namespace
+          Values:
+            - Value:           0x0000000000000000 # DW_ATE_strp
+        - AbbrCode:        0x00000002 # structure_type
+          Values:
+            - Value:           0x000000000000000c # DW_ATE_strp
+        - AbbrCode:        0x00000003 # base_type
+          Values:
+            - Value:           0x0000000000000015 # DW_ATE_strp
+        - AbbrCode:        0x00000000
+)";
+
+  YAMLModuleTester t(yamldata);
+  DWARFUnit *unit = t.GetDwarfUnit();
+  ASSERT_TRUE(unit != nullptr);
+  auto &ctx = unit->GetSymbolFileDWARF();
+
+  auto top_level_die = unit->DIE();
+  {
+    ASSERT_TRUE(top_level_die);
+    auto top_level_ctx = ctx.GetDWARFDeclContext(top_level_die);
+    auto top_level_name = llvm::StringRef(top_level_ctx.GetQualifiedName());
+    ASSERT_EQ(top_level_name, "");
+  }
+
+  auto namespace_die = top_level_die.GetFirstChild();
+  {
+    ASSERT_TRUE(namespace_die);
+    auto namespace_ctx = ctx.GetDWARFDeclContext(namespace_die);
+    auto namespace_name = llvm::StringRef(namespace_ctx.GetQualifiedName());
+    ASSERT_EQ(namespace_name, "::mynamespace");
+    auto namespace_names = namespace_ctx.GetQualifiedNameAsVector();
+    ASSERT_EQ(namespace_names.size(), 1u);
+    ASSERT_EQ(namespace_names.front(), "mynamespace");
+  }
+
+  auto struct_die = namespace_die.GetFirstChild();
+  {
+    ASSERT_TRUE(struct_die);
+    auto struct_ctx = ctx.GetDWARFDeclContext(struct_die);
+    auto struct_name = llvm::StringRef(struct_ctx.GetQualifiedName());
+    ASSERT_EQ(struct_name, "mynamespace::mystruct");
+    auto struct_names = struct_ctx.GetQualifiedNameAsVector();
+    ASSERT_EQ(struct_names.size(), 2u);
+    ASSERT_EQ(struct_names[0], "mystruct");
+    ASSERT_EQ(struct_names[1], "mynamespace");
+  }
+  auto simple_type_die = struct_die.GetFirstChild();
+  {
+    ASSERT_TRUE(simple_type_die);
+    auto simple_type_ctx = ctx.GetDWARFDeclContext(simple_type_die);
+    auto simple_type_name = llvm::StringRef(simple_type_ctx.GetQualifiedName());
+    ASSERT_EQ(simple_type_name, "mynamespace::mystruct::mytype");
+    auto simple_type_names = simple_type_ctx.GetQualifiedNameAsVector();
+    ASSERT_EQ(simple_type_names.size(), 3u);
+    ASSERT_EQ(simple_type_names[0], "mytype");
+    ASSERT_EQ(simple_type_names[1], "mystruct");
+    ASSERT_EQ(simple_type_names[2], "mynamespace");
+  }
+}

>From 7a382cd2ad261808c3aa014590a9120d7900cfa1 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Wed, 6 Dec 2023 11:26:18 -0800
Subject: [PATCH 2/9] [llvm][DebugNames] Implement DW_IDX_parent entries

---
 llvm/include/llvm/CodeGen/AccelTable.h        | 24 ++++++++---
 llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp    | 43 ++++++++++++++++---
 llvm/lib/DWARFLinker/DWARFLinker.cpp          |  8 ++++
 .../DWARFLinkerParallel/DWARFLinkerImpl.cpp   |  3 +-
 .../lib/DWARFLinkerParallel/DWARFLinkerUnit.h |  3 ++
 5 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/AccelTable.h b/llvm/include/llvm/CodeGen/AccelTable.h
index 6eb09f32f9f951..725b434868d21e 100644
--- a/llvm/include/llvm/CodeGen/AccelTable.h
+++ b/llvm/include/llvm/CodeGen/AccelTable.h
@@ -261,9 +261,12 @@ class DWARF5AccelTableData : public AccelTableData {
 
   DWARF5AccelTableData(const DIE &Die, const uint32_t UnitID,
                        const bool IsTU = false);
-  DWARF5AccelTableData(const uint64_t DieOffset, const unsigned DieTag,
-                       const unsigned UnitID, const bool IsTU = false)
-      : OffsetVal(DieOffset), DieTag(DieTag), UnitID(UnitID), IsTU(IsTU) {}
+  DWARF5AccelTableData(const uint64_t DieOffset,
+                       const std::optional<uint64_t> ParentOffset,
+                       const unsigned DieTag, const unsigned UnitID,
+                       const bool IsTU = false)
+      : OffsetVal(DieOffset), ParentOffset(ParentOffset), DieTag(DieTag),
+        UnitID(UnitID), IsTU(IsTU) {}
 
 #ifndef NDEBUG
   void print(raw_ostream &OS) const override;
@@ -278,14 +281,24 @@ class DWARF5AccelTableData : public AccelTableData {
   bool isTU() const { return IsTU; }
   void normalizeDIEToOffset() {
     assert(!isNormalized() && "Accessing offset after normalizing.");
-    OffsetVal = std::get<const DIE *>(OffsetVal)->getOffset();
+    const DIE *Entry = std::get<const DIE *>(OffsetVal);
+    ParentOffset = Entry->getParent() ? Entry->getParent()->getOffset()
+                                      : std::optional<uint64_t>();
+    OffsetVal = Entry->getOffset();
   }
   bool isNormalized() const {
     return std::holds_alternative<uint64_t>(OffsetVal);
   }
 
+  std::optional<uint64_t> getParentDieOffset() const {
+    assert(std::holds_alternative<uint64_t>(OffsetVal) &&
+           "Accessing DIE Offset before normalizing.");
+    return ParentOffset;
+  }
+
 protected:
   std::variant<const DIE *, uint64_t> OffsetVal;
+  std::optional<uint64_t> ParentOffset;
   uint32_t DieTag : 16;
   uint32_t UnitID : 15;
   uint32_t IsTU : 1;
@@ -334,7 +347,8 @@ class DWARF5AccelTable : public AccelTable<DWARF5AccelTableData> {
     for (auto &Entry : Table.getEntries()) {
       for (AccelTableData *Value : Entry.second.Values) {
         DWARF5AccelTableData *Data = static_cast<DWARF5AccelTableData *>(Value);
-        addName(Entry.second.Name, Data->getDieOffset(), Data->getDieTag(),
+        addName(Entry.second.Name, Data->getDieOffset(),
+                Data->getParentDieOffset(), Data->getDieTag(),
                 Data->getUnitID(), true);
       }
     }
diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
index 30ea7eef3a12ba..f96971680a621c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -224,6 +224,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
   MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
   // Indicates if this module is built with Split Dwarf enabled.
   bool IsSplitDwarf = false;
+  DenseMap<uint64_t, MCSymbol *> DieOffsetToAccelEntrySymbol;
+  llvm::DenseSet<MCSymbol *> EmittedAccelEntrySymbols;
 
   void populateAbbrevsMap();
 
@@ -232,8 +234,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
   void emitBuckets() const;
   void emitStringOffsets() const;
   void emitAbbrevs() const;
-  void emitEntry(const DataT &Entry) const;
-  void emitData() const;
+  void emitEntry(const DataT &Entry);
+  void emitData();
 
 public:
   Dwarf5AccelTableWriter(
@@ -414,6 +416,7 @@ static uint32_t constructAbbreviationTag(
   if (EntryRet)
     AbbrvTag |= 1 << EntryRet->Encoding.Index;
   AbbrvTag |= 1 << dwarf::DW_IDX_die_offset;
+  AbbrvTag |= 1 << dwarf::DW_IDX_parent;
   AbbrvTag |= Tag << LowerBitSize;
   return AbbrvTag;
 }
@@ -427,10 +430,11 @@ void Dwarf5AccelTableWriter<DataT>::populateAbbrevsMap() {
         unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
         uint32_t AbbrvTag = constructAbbreviationTag(Tag, EntryRet);
         if (Abbreviations.count(AbbrvTag) == 0) {
-          SmallVector<DWARF5AccelTableData::AttributeEncoding, 2> UA;
+          SmallVector<DWARF5AccelTableData::AttributeEncoding, 3> UA;
           if (EntryRet)
             UA.push_back(EntryRet->Encoding);
           UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
+          UA.push_back({dwarf::DW_IDX_parent, dwarf::DW_FORM_ref4});
           Abbreviations.try_emplace(AbbrvTag, UA);
         }
       }
@@ -507,7 +511,7 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
 }
 
 template <typename DataT>
-void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
+void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) {
   std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
       getIndexForEntry(Entry);
   uint32_t AbbrvTag = constructAbbreviationTag(Entry.getDieTag(), EntryRet);
@@ -516,6 +520,18 @@ void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
          "Why wasn't this abbrev generated?");
   assert(getTagFromAbbreviationTag(AbbrevIt->first) == Entry.getDieTag() &&
          "Invalid Tag");
+
+  // Create a label for this Entry, if not yet created by a IDX_parent
+  // reference to the same underlying DIE.
+  MCSymbol *&EntrySymbol = DieOffsetToAccelEntrySymbol[Entry.getDieOffset()];
+  if (EntrySymbol == nullptr)
+    EntrySymbol = Asm->createTempSymbol("symbol");
+
+  // Emit the label for this Entry, if a label hasn't yet been emitted for some
+  // other Entry of the same underlying DIE (a DIE may have multiple Entries).
+  if (EmittedAccelEntrySymbols.insert(EntrySymbol).second)
+    Asm->OutStreamer->emitLabel(EntrySymbol);
+
   Asm->emitULEB128(AbbrevIt->first, "Abbreviation code");
 
   for (const auto &AttrEnc : AbbrevIt->second) {
@@ -531,13 +547,25 @@ void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
       assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
       Asm->emitInt32(Entry.getDieOffset());
       break;
+    case dwarf::DW_IDX_parent: {
+      // If a DIE is being placed on the table, its parent is always non-null
+      // (top-level DIEs are not placed in the table), though the parent may not
+      // be indexed. Bad input is handled like a parent that is not indexed,
+      // i.e., with an offset that is not in the table.
+      uint64_t ParentOffset = Entry.getParentDieOffset().value_or(-1);
+      MCSymbol *&ParentSymbol = DieOffsetToAccelEntrySymbol[ParentOffset];
+      if (ParentSymbol == nullptr)
+        ParentSymbol = Asm->createTempSymbol("symbol");
+      Asm->emitLabelDifference(ParentSymbol, EntryPool, 4);
+      break;
+    }
     default:
       llvm_unreachable("Unexpected index attribute!");
     }
   }
 }
 
-template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
+template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() {
   Asm->OutStreamer->emitLabel(EntryPool);
   for (auto &Bucket : Contents.getBuckets()) {
     for (auto *Hash : Bucket) {
@@ -549,6 +577,11 @@ template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
       Asm->emitInt8(0);
     }
   }
+  // Any labels not yet emitted refer to DIEs that are not present in the
+  // accelerator table. Point them to end of the table.
+  for (MCSymbol *Symbol : make_second_range(DieOffsetToAccelEntrySymbol))
+    if (EmittedAccelEntrySymbols.insert(Symbol).second)
+      Asm->OutStreamer->emitLabel(Symbol);
 }
 
 template <typename DataT>
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index 10967123a562e7..3900902ac07eda 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -2253,14 +2253,22 @@ void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
       TheDwarfEmitter->emitPubTypesForUnit(Unit);
     } break;
     case AccelTableKind::DebugNames: {
+      auto ParentOffsetOrNull = [](const DIE *Die) -> std::optional<uint64_t> {
+        if (const DIE *Parent = Die->getParent())
+          return Die->getParent()->getOffset();
+        return std::nullopt;
+      };
       for (const auto &Namespace : Unit.getNamespaces())
         DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(),
+                           ParentOffsetOrNull(Namespace.Die),
                            Namespace.Die->getTag(), Unit.getUniqueID());
       for (const auto &Pubname : Unit.getPubnames())
         DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(),
+                           ParentOffsetOrNull(Pubname.Die),
                            Pubname.Die->getTag(), Unit.getUniqueID());
       for (const auto &Pubtype : Unit.getPubtypes())
         DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(),
+                           ParentOffsetOrNull(Pubtype.Die),
                            Pubtype.Die->getTag(), Unit.getUniqueID());
     } break;
     }
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp b/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp
index c49b9ef0cdf989..2f514b6140f4aa 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp
@@ -1376,7 +1376,8 @@ void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
       case DwarfUnit::AccelType::Namespace:
       case DwarfUnit::AccelType::Type: {
         DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
-                            Info.OutOffset, Info.Tag, CU->getUniqueID());
+                            Info.OutOffset, Info.ParentOutOffset, Info.Tag,
+                            CU->getUniqueID());
       } break;
 
       default:
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h b/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h
index 9640a8ee711eb0..4ca1920208761c 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h
@@ -125,6 +125,9 @@ class DwarfUnit : public OutputSections {
     /// Output offset of the DIE this entry describes.
     uint64_t OutOffset;
 
+    /// Output offset of the parent of the DIE this entry describes.
+    std::optional<uint64_t> ParentOutOffset;
+
     /// Hash of the fully qualified name.
     uint32_t QualifiedNameHash = 0;
 

>From d0a2150a5b374006933a4b872fdc85211c9d2967 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 3/9] [llvm][DebugNames] Implement Entry::GetParentEntry query

---
 .../llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h     | 12 ++++++++++++
 llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp   | 10 ++++++++++
 llvm/test/CodeGen/X86/dwarf-headers.o                |  0
 3 files changed, 22 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 b89536bc0c7230..0fabe98210f423 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -460,6 +460,11 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
     /// Returns the Offset of the DIE within the containing CU or TU.
     std::optional<uint64_t> getDIEUnitOffset() const;
 
+    /// Returns the Entry corresponding to the parent of the DIE represented by
+    /// `this` Entry. If the parent DIE is not indexed by this table, or if this
+    /// table does not track parents through IDX_parent, an error is returned.
+    Expected<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 +614,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 0f9c8ef485d456..b0f9953d46ee85 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -650,6 +650,16 @@ std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUIndex() const {
   return std::nullopt;
 }
 
+Expected<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);
+  if (!ParentEntryOff)
+    return createStringError(errc::illegal_byte_sequence,
+                             "Incorrectly terminated entry list.");
+  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 00000000000000..e69de29bb2d1d6

>From b922242102039abd394738687fe193c3c796db3e 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 4/9] [lldb][DWARFUnit] Implement PeekDIEName query

This allows us to not parse the entire DIE.
---
 lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | 7 +++++++
 lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h   | 5 +++++
 lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp      | 8 ++++++++
 lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h        | 5 +++++
 4 files changed, 25 insertions(+)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 553b6a4c551d20..775b7a2e73f512 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -191,3 +191,10 @@ 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 d5e48f312ea0e9..a8b5abc3beed2d 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/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 0e2f4d45543bb5..7db279ed37d04a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -663,6 +663,14 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) {
   return DWARFDIE(); // Not found
 }
 
+llvm::StringRef DWARFUnit::PeekDIEName(dw_offset_t die_offset) {
+  const DWARFDataExtractor &data = GetData();
+  DWARFDebugInfoEntry die;
+  if (!die.Extract(data, this, &die_offset))
+    return llvm::StringRef();
+  return die.GetName(this);
+}
+
 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 3f528e913d8cfa..bc225a52e1d030 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);

>From f0cf444830f8e358e9db4668481dc3c5387422bd Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Wed, 13 Dec 2023 13:57:07 -0300
Subject: [PATCH 5/9] [llvm][DebugNames] Implement supportsIdxParent query

---
 llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h | 8 ++++++++
 llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp        | 5 +++++
 2 files changed, 13 insertions(+)

diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 0fabe98210f423..13ba8269fc3d19 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -557,6 +557,7 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
     uint64_t StringOffsetsBase;
     uint64_t EntryOffsetsBase;
     uint64_t EntriesBase;
+    bool HasIdxParent = false;
 
     void dumpCUs(ScopedPrinter &W) const;
     void dumpLocalTUs(ScopedPrinter &W) const;
@@ -770,6 +771,13 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
   /// Return the Name Index covering the compile unit at CUOffset, or nullptr if
   /// there is no Name Index covering that unit.
   const NameIndex *getCUNameIndex(uint64_t CUOffset);
+
+  /// Returns true if all the NameIndices in this table provide IDX_parent
+  /// capabilities.
+  bool supportsIdxParent() const {
+    return all_of(NameIndices,
+                  [](const NameIndex &Idx) { return Idx.HasIdxParent; });
+  }
 };
 
 /// If `Name` is the name of a templated function that includes template
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index b0f9953d46ee85..ef06cb68665882 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -578,6 +578,10 @@ Error DWARFDebugNames::NameIndex::extract() {
                              "Section too small: cannot read abbreviations.");
 
   EntriesBase = Offset + Hdr.AbbrevTableSize;
+  HasIdxParent = false;
+  auto IsIdxParent = [](auto IdxFormPair) {
+    return IdxFormPair.Index == dwarf::Index::DW_IDX_parent;
+  };
 
   for (;;) {
     auto AbbrevOr = extractAbbrev(&Offset);
@@ -585,6 +589,7 @@ Error DWARFDebugNames::NameIndex::extract() {
       return AbbrevOr.takeError();
     if (isSentinel(*AbbrevOr))
       return Error::success();
+    HasIdxParent |= any_of(AbbrevOr->Attributes, IsIdxParent);
 
     if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
       return createStringError(errc::invalid_argument,

>From 7b077b17005adf1390eb9a4190b73697a1cad775 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 7 Dec 2023 11:27:47 -0800
Subject: [PATCH 6/9] [lldb][DWARFIndex] Implement GetFullyQualifiedType query

Combines:
1. the accelerator table capability of finding parents
2. the DWARFUnit capability of finding the name of a DIE without parsing the
whole CU.
---
 .../Plugins/SymbolFile/DWARF/DWARFIndex.cpp   | 19 +++++++
 .../Plugins/SymbolFile/DWARF/DWARFIndex.h     |  8 +++
 .../SymbolFile/DWARF/DebugNamesDWARFIndex.cpp | 49 +++++++++++++++++++
 .../SymbolFile/DWARF/DebugNamesDWARFIndex.h   |  5 ++
 4 files changed, 81 insertions(+)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
index b1c323b101cef3..bc3477d9e86e56 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "DWARFDeclContext.h"
 #include "Plugins/Language/ObjC/ObjCLanguage.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
@@ -112,3 +113,21 @@ void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const {
       "bad die {0:x16} for '{1}')\n",
       ref.die_offset(), name.str().c_str());
 }
+
+void DWARFIndex::GetFullyQualifiedType(
+    const DWARFDeclContext &context,
+    llvm::function_ref<bool(DWARFDIE die)> callback) {
+  auto qualified_names = context.GetQualifiedNameAsVector();
+  if (qualified_names.empty())
+    return;
+  auto parent_names = llvm::makeArrayRef(qualified_names).drop_front();
+  GetTypes(context, [&](DWARFDIE die) {
+    auto original_die = die;
+    for (auto parent_name : parent_names) {
+      die = die.GetParent();
+      if (!die || die.GetName() != parent_name)
+        return false;
+    }
+    return callback(original_die);
+  });
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
index 9aadeddbb21753..4fd10a634fc57f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
@@ -53,6 +53,14 @@ class DWARFIndex {
                         llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
   virtual void GetTypes(const DWARFDeclContext &context,
                         llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
+
+  /// Finds all DIEs whose fully qualified name matches `context`. A base
+  /// implementation is provided, and it uses the entire CU to check the DIE
+  /// parent hierarchy. Specializations should override this if they are able
+  /// to provide a faster implementation.
+  virtual void
+  GetFullyQualifiedType(const DWARFDeclContext &context,
+                        llvm::function_ref<bool(DWARFDIE die)> callback);
   virtual void
   GetNamespaces(ConstString name,
                 llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
index 7c253553d57b48..5cc60a3ca8dad7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -218,6 +218,55 @@ void DebugNamesDWARFIndex::GetCompleteObjCClass(
   m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
 }
 
+void DebugNamesDWARFIndex::GetFullyQualifiedType(
+    const DWARFDeclContext &context,
+    llvm::function_ref<bool(DWARFDIE die)> callback) {
+  if (!m_debug_names_up->supportsIdxParent())
+    return DWARFIndex::GetFullyQualifiedType(context, callback);
+
+  auto qualified_names = context.GetQualifiedNameAsVector();
+  if (qualified_names.empty())
+    return;
+
+  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);
+  };
+
+  auto parent_names = llvm::makeArrayRef(qualified_names).drop_front();
+  auto CheckParentChain = [&](DebugNames::Entry entry) {
+    for (auto expected_name : parent_names) {
+      auto maybe_parent_entry = entry.getParentDIEEntry();
+      if (!maybe_parent_entry) {
+        consumeError(maybe_parent_entry.takeError());
+        return false;
+      }
+      entry = *maybe_parent_entry;
+      if (!CompareEntryATName(expected_name, entry))
+        return false;
+    }
+    /// All expected names matched. The remaining entry should have no parent
+    /// for a match to occur.
+    auto maybe_parent_entry = entry.getParentDIEEntry();
+    if (maybe_parent_entry)
+      return false;
+    consumeError(maybe_parent_entry.takeError());
+    return true;
+  };
+
+  auto leaf_matches = m_debug_names_up->equal_range(qualified_names.front());
+  for (const DebugNames::Entry &entry : leaf_matches)
+    if (isType(entry.tag()) && CheckParentChain(entry) &&
+        (!ProcessEntry(entry, callback)))
+      return;
+}
+
 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 7ce630a56137d1..72d02ca0064969 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
@@ -42,6 +42,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,

>From fa922cf93bd5efa29f749ecc92e7ddfaeea69851 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Mon, 11 Dec 2023 12:44:39 -0300
Subject: [PATCH 7/9] [lldb][SymbolFileDWARF] Use
 DWARFIndex::GetFullyQualifiedType query

---
 lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 505ea29ca4d4f5..e7dc9115cd80e7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3095,7 +3095,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
     }
 
     const DWARFDeclContext die_dwarf_decl_ctx = GetDWARFDeclContext(die);
-    m_index->GetTypes(die_dwarf_decl_ctx, [&](DWARFDIE type_die) {
+    m_index->GetFullyQualifiedType(die_dwarf_decl_ctx, [&](DWARFDIE type_die) {
       // Make sure type_die's language matches the type system we are
       // looking for. We don't want to find a "Foo" type from Java if we
       // are looking for a "Foo" type for C, C++, ObjC, or ObjC++.
@@ -3122,9 +3122,8 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
         return true;
       }
 
-      DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die);
-
       if (log) {
+        DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die);
         GetObjectFile()->GetModule()->LogMessage(
             log,
             "SymbolFileDWARF::"
@@ -3134,10 +3133,6 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
             type_dwarf_decl_ctx.GetQualifiedName());
       }
 
-      // Make sure the decl contexts match all the way up
-      if (die_dwarf_decl_ctx != type_dwarf_decl_ctx)
-        return true;
-
       Type *resolved_type = ResolveType(type_die, false);
       if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
         return true;

>From 837bc0f476820f9ee5695223420105dedfea8d79 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Tue, 17 Oct 2023 09:27:19 -0700
Subject: [PATCH 8/9] [lldb] Add timer to EvaluateExpression method

---
 lldb/source/Commands/CommandObjectExpression.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 3a2dc11e1e71cc..59ea097fe82378 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -414,6 +414,8 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
                                                  Stream &output_stream,
                                                  Stream &error_stream,
                                                  CommandReturnObject &result) {
+  auto start = std::chrono::steady_clock::now();
+
   // Don't use m_exe_ctx as this might be called asynchronously after the
   // command object DoExecute has finished when doing multi-line expression
   // that use an input reader...
@@ -514,6 +516,9 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
     error_stream.Printf("error: unknown error\n");
   }
 
+  auto end = std::chrono::steady_clock::now();
+  auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
+  error_stream.Printf("Finished expr in: %" PRIu64, duration.count());
   return (success != eExpressionSetupError &&
           success != eExpressionParseError);
 }

>From 0450d05d26418796de24083acb240feec9f058d3 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Tue, 2 Jan 2024 10:14:39 -0300
Subject: [PATCH 9/9] wip_dense_map_of_offsets_per_entry

---
 llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
index f96971680a621c..6714eff3e16708 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -13,6 +13,7 @@
 #include "llvm/CodeGen/AccelTable.h"
 #include "DwarfCompileUnit.h"
 #include "DwarfUnit.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -211,7 +212,7 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
   };
 
   Header Header;
-  DenseMap<uint32_t, SmallVector<DWARF5AccelTableData::AttributeEncoding, 2>>
+  DenseMap<uint32_t, SmallVector<DWARF5AccelTableData::AttributeEncoding, 3>>
       Abbreviations;
   ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits;
   ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits;
@@ -234,7 +235,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
   void emitBuckets() const;
   void emitStringOffsets() const;
   void emitAbbrevs() const;
-  void emitEntry(const DataT &Entry);
+  void emitEntry(const DataT &Entry,
+                 const DenseSet<uint64_t> &OffsetsOfIndexedDIEs);
   void emitData();
 
 public:
@@ -511,7 +513,8 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
 }
 
 template <typename DataT>
-void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) {
+void Dwarf5AccelTableWriter<DataT>::emitEntry(
+    const DataT &Entry, const DenseSet<uint64_t> &OffsetsOfIndexedDIEs) {
   std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
       getIndexForEntry(Entry);
   uint32_t AbbrvTag = constructAbbreviationTag(Entry.getDieTag(), EntryRet);
@@ -566,13 +569,20 @@ void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) {
 }
 
 template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() {
+  DenseSet<uint64_t> OffsetsOfIndexedDIEs;
+  for (auto &Bucket : Contents.getBuckets())
+    for (auto *Hash : Bucket)
+      for (const auto *Value : Hash->Values)
+        OffsetsOfIndexedDIEs.insert(
+            static_cast<const DataT *>(Value)->getDieOffset());
+
   Asm->OutStreamer->emitLabel(EntryPool);
   for (auto &Bucket : Contents.getBuckets()) {
     for (auto *Hash : Bucket) {
       // Remember to emit the label for our offset.
       Asm->OutStreamer->emitLabel(Hash->Sym);
       for (const auto *Value : Hash->Values)
-        emitEntry(*static_cast<const DataT *>(Value));
+        emitEntry(*static_cast<const DataT *>(Value), OffsetsOfIndexedDIEs);
       Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
       Asm->emitInt8(0);
     }



More information about the lldb-commits mailing list