[llvm] [DebugNames] Implement Entry::GetParentEntry query (PR #78760)

Felipe de Azevedo Piovezan via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 24 06:19:43 PST 2024


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

>From f935d8bae34dbc219e11117779dde63eb59ac4a7 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/2] [DebugNames] Implement Entry::GetParentEntry query

This commit introduces a helper function to DWARFAcceleratorTable::Entry which
follows DW_IDX_Parent attributes to returns the corresponding parent Entry in
the table.

It is tested by enhancing dwarfdump so that it now prints:

1. When data is corrupt.
2. When parent information is present, but the parent is not indexed.
3. The parent entry offset, when the parent is present and indexed. This is
printed in terms a real entry offset (the same that gets printed at the start of
each entry: "Entry @ 0x..."), instead of the encoded number in the table (which
is an offset from the start off the Entry list). This makes it easy to visually
inspect the dwarfdump and check what the parent is.
---
 .../DebugInfo/DWARF/DWARFAcceleratorTable.h   | 18 ++++++++
 .../DebugInfo/DWARF/DWARFAcceleratorTable.cpp | 43 ++++++++++++++++++-
 llvm/test/CodeGen/X86/dwarf-headers.o         |  0
 .../DebugInfo/Generic/debug-names-one-cu.ll   |  4 +-
 .../test/DebugInfo/X86/debug-names-dwarf64.ll | 10 ++---
 .../X86/debug-names-parents-same-offset.ll    | 24 ++++++++---
 llvm/test/DebugInfo/X86/debug-names-types.ll  | 20 ++++-----
 .../ARM/accel-imported-declarations.test      |  4 +-
 8 files changed, 97 insertions(+), 26 deletions(-)
 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..57f74d70cf9671c 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; }
@@ -469,6 +479,7 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
     std::optional<DWARFFormValue> lookup(dwarf::Index Index) const;
 
     void dump(ScopedPrinter &W) const;
+    void dumpParentIdx(ScopedPrinter &W, const DWARFFormValue &FormValue) const;
 
     friend class NameIndex;
     friend class ValueIterator;
@@ -609,6 +620,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..03ad5d133caddf4 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,13 +654,48 @@ 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::dumpParentIdx(
+    ScopedPrinter &W, const DWARFFormValue &FormValue) const {
+  Expected<std::optional<Entry>> ParentEntry = getParentDIEEntry();
+  if (!ParentEntry) {
+    W.getOStream() << "<invalid offset data>";
+    consumeError(ParentEntry.takeError());
+    return;
+  }
+
+  if (!ParentEntry->has_value()) {
+    W.getOStream() << "<parent not indexed>";
+    return;
+  }
+
+  auto AbsoluteOffset = NameIdx->EntriesBase + FormValue.getRawUValue();
+  W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);
+}
+
 void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const {
   W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
   W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
   assert(Abbr->Attributes.size() == Values.size());
   for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
-    W.startLine() << formatv("{0}: ", std::get<0>(Tuple).Index);
-    std::get<1>(Tuple).dump(W.getOStream());
+    auto Index = std::get<0>(Tuple).Index;
+    W.startLine() << formatv("{0}: ", Index);
+
+    auto FormValue = std::get<1>(Tuple);
+    if (Index == dwarf::Index::DW_IDX_parent)
+      dumpParentIdx(W, FormValue);
+    else
+      FormValue.dump(W.getOStream());
     W.getOStream() << '\n';
   }
 }
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
diff --git a/llvm/test/DebugInfo/Generic/debug-names-one-cu.ll b/llvm/test/DebugInfo/Generic/debug-names-one-cu.ll
index 92212a24bd153ad..46b753e9e2def8d 100644
--- a/llvm/test/DebugInfo/Generic/debug-names-one-cu.ll
+++ b/llvm/test/DebugInfo/Generic/debug-names-one-cu.ll
@@ -35,7 +35,7 @@
 ; CHECK-NEXT: Abbrev: [[ABBREV]]
 ; CHECK-NEXT: Tag: DW_TAG_variable
 ; CHECK-NEXT: DW_IDX_die_offset: 0x{{[0-9a-f]*}}
-; CHECK-NEXT: DW_IDX_parent: true
+; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT: }
 
 ; CHECK: String: 0x{{[0-9a-f]*}} "foobar"
@@ -43,7 +43,7 @@
 ; CHECK-NEXT: Abbrev: [[ABBREV]]
 ; CHECK-NEXT: Tag: DW_TAG_variable
 ; CHECK-NEXT: DW_IDX_die_offset: 0x{{[0-9a-f]*}}
-; CHECK-NEXT: DW_IDX_parent: true
+; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT: }
 
 ; VERIFY: No errors.
diff --git a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
index a6855d77a34ac23..c15e2ad1d56b0c4 100644
--- a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
+++ b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
@@ -59,7 +59,7 @@
 ; CHECK-NEXT:         Abbrev: [[ABBREV]]
 ; CHECK-NEXT:         Tag: DW_TAG_base_type
 ; CHECK-NEXT:         DW_IDX_die_offset: [[TYPEDIE]]
-; CHECK-NEXT:         DW_IDX_parent: true
+; CHECK-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:     }
 ; CHECK-NEXT:   ]
@@ -71,17 +71,17 @@
 ; CHECK-NEXT:         Abbrev: [[ABBREV1]]
 ; CHECK-NEXT:         Tag: DW_TAG_variable
 ; CHECK-NEXT:         DW_IDX_die_offset: [[VARDIE]]
-; CHECK-NEXT:         DW_IDX_parent: true
+; CHECK-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:     }
 ; CHECK-NEXT:     Name 3 {
 ; CHECK-NEXT:       Hash: 0x7C96FE71
 ; CHECK-NEXT:       String: {{.+}} "func"
-; CHECK-NEXT:       Entry @ {{.+}} {
+; CHECK-NEXT:       Entry @ [[FUNC_ENTRY:0x.+]] {
 ; CHECK-NEXT:         Abbrev: [[ABBREV_SP]]
 ; CHECK-NEXT:         Tag: DW_TAG_subprogram
 ; CHECK-NEXT:         DW_IDX_die_offset: [[SPDIE]]
-; CHECK-NEXT:         DW_IDX_parent: true
+; CHECK-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:     }
 ; CHECK-NEXT:   ]
@@ -96,7 +96,7 @@
 ; CHECK-NEXT:         Abbrev: [[ABBREV_LABEL]]
 ; CHECK-NEXT:         Tag: DW_TAG_label
 ; CHECK-NEXT:         DW_IDX_die_offset: [[LABELDIE]]
-; CHECK-NEXT:         DW_IDX_parent: 0x{{.*}}
+; CHECK-NEXT:         DW_IDX_parent: Entry @ [[FUNC_ENTRY]]
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:     }
 ; CHECK-NEXT:   ]
diff --git a/llvm/test/DebugInfo/X86/debug-names-parents-same-offset.ll b/llvm/test/DebugInfo/X86/debug-names-parents-same-offset.ll
index 9170cfc8508fa5e..95d85ab0ffe0fb3 100644
--- a/llvm/test/DebugInfo/X86/debug-names-parents-same-offset.ll
+++ b/llvm/test/DebugInfo/X86/debug-names-parents-same-offset.ll
@@ -21,16 +21,30 @@
 ; CHECK-NEXT:        Abbrev: [[ABBREV:0x.*]]
 ; CHECK-NEXT:        Tag: DW_TAG_structure_type
 ; CHECK-NEXT:        DW_IDX_type_unit: 0x01
-; CHECK-NEXT:        DW_IDX_die_offset: [[DieOffset:0x.*]]
-; CHECK-NEXT:        DW_IDX_parent: [[Parent1:0x.*]]
+; CHECK-NEXT:        DW_IDX_die_offset: [[DieOffsetStruct:0x.*]]
+; CHECK-NEXT:        DW_IDX_parent: Entry @ [[Parent2:0x.*]]
+; CHECK:      String: {{.*}} "MyNamespace"
+; CHECK-NEXT:      Entry @ [[Parent1:0x.*]] {
+; CHECK-NEXT:        Abbrev: {{.*}}
+; CHECK-NEXT:        Tag: DW_TAG_namespace
+; CHECK-NEXT:        DW_IDX_type_unit: 0x00
+; CHECK-NEXT:        DW_IDX_die_offset: [[DieOffsetNamespace:0x.*]]
+; CHECK-NEXT:        DW_IDX_parent: <parent not indexed>
+; CHECK-NEXT:      }
+; CHECK-NEXT:      Entry @ [[Parent2]] {
+; CHECK-NEXT:        Abbrev: {{.*}}
+; CHECK-NEXT:        Tag: DW_TAG_namespace
+; CHECK-NEXT:        DW_IDX_type_unit: 0x01
+; CHECK-NEXT:        DW_IDX_die_offset: [[DieOffsetNamespace:0x.*]]
+; CHECK-NEXT:        DW_IDX_parent: <parent not indexed>
+; CHECK-NEXT:      }
 ; CHECK:      String: {{.*}} "MyStruct1"
 ; CHECK-NEXT:      Entry @ {{.*}} {
 ; CHECK-NEXT:        Abbrev: [[ABBREV]]
 ; CHECK-NEXT:        Tag: DW_TAG_structure_type
 ; CHECK-NEXT:        DW_IDX_type_unit: 0x00
-; CHECK-NEXT:        DW_IDX_die_offset: [[DieOffset:0x.*]]
-; CHECK-NOT:         DW_IDX_parent: [[Parent1]]
-; CHECK-NEXT:        DW_IDX_parent: 0x{{.*}}
+; CHECK-NEXT:        DW_IDX_die_offset: [[DieOffsetStruct:0x.*]]
+; CHECK-NEXT:        DW_IDX_parent: Entry @ [[Parent1]]
 
 
 %"struct.MyNamespace::MyStruct1" = type { i8 }
diff --git a/llvm/test/DebugInfo/X86/debug-names-types.ll b/llvm/test/DebugInfo/X86/debug-names-types.ll
index c44e82578f14a42..f41bb5524b9c33f 100644
--- a/llvm/test/DebugInfo/X86/debug-names-types.ll
+++ b/llvm/test/DebugInfo/X86/debug-names-types.ll
@@ -73,7 +73,7 @@
 ; CHECK-NEXT:         Abbrev: [[ABBREV]]
 ; CHECK-NEXT:         Tag: DW_TAG_base_type
 ; CHECK-NEXT:         DW_IDX_die_offset: 0x0000003e
-; CHECK-NEXT:         DW_IDX_parent: true
+; CHECK-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:     }
 ; CHECK-NEXT:   ]
@@ -86,13 +86,13 @@
 ; CHECK-NEXT:           Tag: DW_TAG_structure_type
 ; CHECK-NEXT:           DW_IDX_type_unit: 0x00
 ; CHECK-NEXT:           DW_IDX_die_offset: 0x00000023
-; CHECK-NEXT:           DW_IDX_parent: true
+; CHECK-NEXT:           DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:       Entry @ {{.+}} {
 ; CHECK-NEXT:         Abbrev: [[ABBREV1]]
 ; CHECK-NEXT:         Tag: DW_TAG_structure_type
 ; CHECK-NEXT:         DW_IDX_die_offset: 0x00000042
-; CHECK-NEXT:         DW_IDX_parent: true
+; CHECK-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:     }
 ; CHECK-NEXT:   ]
@@ -104,7 +104,7 @@
 ; CHECK-NEXT:         Abbrev: [[ABBREV2]]
 ; CHECK-NEXT:         Tag: DW_TAG_subprogram
 ; CHECK-NEXT:         DW_IDX_die_offset: 0x00000023
-; CHECK-NEXT:         DW_IDX_parent: true
+; CHECK-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:     }
 ; CHECK-NEXT:   ]
@@ -117,7 +117,7 @@
 ; CHECK-NEXT:           Tag: DW_TAG_base_type
 ; CHECK-NEXT:           DW_IDX_type_unit: 0x00
 ; CHECK-NEXT:           DW_IDX_die_offset: 0x00000038
-; CHECK-NEXT:           DW_IDX_parent: true
+; CHECK-NEXT:           DW_IDX_parent: <parent not indexed>
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:     }
 ; CHECK-NEXT:   ]
@@ -176,7 +176,7 @@
 ; CHECK-SPLIT-NEXT:         Abbrev: [[ABBREV2]]
 ; CHECK-SPLIT-NEXT:         Tag: DW_TAG_base_type
 ; CHECK-SPLIT-NEXT:         DW_IDX_die_offset: 0x00000035
-; CHECK-SPLIT-NEXT:         DW_IDX_parent: true
+; CHECK-SPLIT-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-SPLIT-NEXT:       }
 ; CHECK-SPLIT-NEXT:     }
 ; CHECK-SPLIT-NEXT:   ]
@@ -189,13 +189,13 @@
 ; CHECK-SPLIT-NEXT:         Tag: DW_TAG_structure_type
 ; CHECK-SPLIT-NEXT:         DW_IDX_type_unit: 0x00
 ; CHECK-SPLIT-NEXT:         DW_IDX_die_offset: 0x00000021
-; CHECK-SPLIT-NEXT:         DW_IDX_parent: true
+; CHECK-SPLIT-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-SPLIT-NEXT:       }
 ; CHECK-SPLIT-NEXT:       Entry @ {{.*}} {
 ; CHECK-SPLIT-NEXT:         Abbrev: [[ABBREV]]
 ; CHECK-SPLIT-NEXT:         Tag: DW_TAG_structure_type
 ; CHECK-SPLIT-NEXT:         DW_IDX_die_offset: 0x00000039
-; CHECK-SPLIT-NEXT:         DW_IDX_parent: true
+; CHECK-SPLIT-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-SPLIT-NEXT:       }
 ; CHECK-SPLIT-NEXT:     }
 ; CHECK-SPLIT-NEXT:   ]
@@ -207,7 +207,7 @@
 ; CHECK-SPLIT-NEXT:         Abbrev: [[ABBREV3]]
 ; CHECK-SPLIT-NEXT:         Tag: DW_TAG_subprogram
 ; CHECK-SPLIT-NEXT:         DW_IDX_die_offset: 0x0000001a
-; CHECK-SPLIT-NEXT:         DW_IDX_parent: true
+; CHECK-SPLIT-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-SPLIT-NEXT:       }
 ; CHECK-SPLIT-NEXT:     }
 ; CHECK-SPLIT-NEXT:   ]
@@ -220,7 +220,7 @@
 ; CHECK-SPLIT-NEXT:         Tag: DW_TAG_base_type
 ; CHECK-SPLIT-NEXT:         DW_IDX_type_unit: 0x00
 ; CHECK-SPLIT-NEXT:         DW_IDX_die_offset: 0x00000036
-; CHECK-SPLIT-NEXT:         DW_IDX_parent: true
+; CHECK-SPLIT-NEXT:         DW_IDX_parent: <parent not indexed>
 ; CHECK-SPLIT-NEXT:       }
 ; CHECK-SPLIT-NEXT:     }
 ; CHECK-SPLIT-NEXT:   ]
diff --git a/llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test b/llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test
index a8bf191e036f75a..8afbe34dcdbfb1d 100644
--- a/llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test
+++ b/llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test
@@ -23,13 +23,13 @@ DWARF-NEXT:     Entry {{.*}} {
 DWARF-NEXT:       Abbrev: {{.*}}
 DWARF-NEXT:       Tag: DW_TAG_namespace
 DWARF:       DW_IDX_die_offset: [[NAMESPACE]]
-DWARF-NEXT:  DW_IDX_parent: 0x{{.*}}
+DWARF-NEXT:  DW_IDX_parent: Entry @ 0x{{.*}}
 DWARF-NEXT:     }
 DWARF-NEXT:     Entry {{.*}} {
 DWARF-NEXT:       Abbrev: {{.*}}
 DWARF:       Tag: DW_TAG_imported_declaration
 DWARF:       DW_IDX_die_offset: 0x0000005c
-DWARF-NEXT:  DW_IDX_parent: 0x{{.*}}
+DWARF-NEXT:  DW_IDX_parent: Entry @ 0x{{.*}}
 DWARF-NEXT:     }
 DWARF-NEXT:   }
 

>From 3b6189c9835e858cfa01f08af75f059a1c8b95dc Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Wed, 24 Jan 2024 06:19:28 -0800
Subject: [PATCH 2/2] fixup! Use /// for func docs

---
 llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 57f74d70cf9671c..44a19c7b13f9a7b 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -620,8 +620,8 @@ 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.
+    /// 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);



More information about the llvm-commits mailing list