[llvm] dc5c044 - Add verification support for .debug_names with foreign type units. (#109011)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 22 09:35:14 PDT 2024


Author: Greg Clayton
Date: 2024-10-22T09:35:10-07:00
New Revision: dc5c044193b31231dcb1d32c76bb03cbc9ed2c74

URL: https://github.com/llvm/llvm-project/commit/dc5c044193b31231dcb1d32c76bb03cbc9ed2c74
DIFF: https://github.com/llvm/llvm-project/commit/dc5c044193b31231dcb1d32c76bb03cbc9ed2c74.diff

LOG: Add verification support for .debug_names with foreign type units. (#109011)

This commit enables 'llvm-dwarfdump --veriy' to verify the DWARF in
foreign type units when using split DWARF for the .debug_names section.

Added: 
    llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_dwo.yaml
    llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_exe.yaml
    llvm/test/tools/llvm-dwarfdump/verify_split_dwarf_debug_names_ftus.test

Modified: 
    llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
    llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
    llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
    llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
    llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
    llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 0117c90e77f990..9d7ac12cefdc85 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -447,7 +447,7 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
     std::optional<uint64_t> getForeignTUTypeSignature() const override;
     std::optional<dwarf::Tag> getTag() const override { return tag(); }
 
-    // Special function that will return the related CU offset needed type 
+    // Special function that will return the related CU offset needed type
     // units. This gets used to find the .dwo file that originated the entries
     // for a given type unit.
     std::optional<uint64_t> getRelatedCUOffset() const;
@@ -468,12 +468,13 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
     /// index for an entry that is a type unit.
     std::optional<uint64_t> getRelatedCUIndex() const;
 
-    /// Returns the Index into the Local Type Unit list of the owning Name
+    /// Returns the index of the Type Unit of the owning
+    /// Name
     /// Index or std::nullopt if this Accelerator Entry does not have an
     /// associated Type Unit. It is up to the user to verify that the
-    /// returned Index is valid in the owning NameIndex (or use
+    /// returned Index is a valid index in the owning NameIndex (or use
     /// getLocalTUOffset(), which will handle that check itself).
-    std::optional<uint64_t> getLocalTUIndex() const;
+    std::optional<uint64_t> getTUIndex() const;
 
     /// .debug_names-specific getter, which always succeeds (DWARF v5 index
     /// entries always have a tag).
@@ -803,7 +804,7 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
 
 private:
   SmallVector<NameIndex, 0> NameIndices;
-  DenseMap<uint64_t, const NameIndex *> CUToNameIndex;
+  DenseMap<uint64_t, const NameIndex *> UnitOffsetToNameIndex;
 
 public:
   DWARFDebugNames(const DWARFDataExtractor &AccelSection,
@@ -820,9 +821,9 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
   const_iterator begin() const { return NameIndices.begin(); }
   const_iterator end() const { return NameIndices.end(); }
 
-  /// 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);
+  /// Return the Name Index covering the compile unit or local type unit at
+  /// UnitOffset, or nullptr if there is no Name Index covering that unit.
+  const NameIndex *getCUOrTUNameIndex(uint64_t UnitOffset);
 };
 
 /// Calculates the starting offsets for various sections within the

diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 455ccaab74d7e0..0d6e2b076cc344 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -209,6 +209,9 @@ class DWARFContext : public DIContext {
     return State->getDWOUnits();
   }
 
+  /// Return true of this DWARF context is a DWP file.
+  bool isDWP() const;
+
   /// Get units from .debug_types.dwo in the DWO context.
   unit_iterator_range dwo_types_section_units() {
     DWARFUnitVector &DWOUnits = State->getDWOUnits();
@@ -262,7 +265,7 @@ class DWARFContext : public DIContext {
   }
 
   DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
-  DWARFTypeUnit *getTypeUnitForHash(uint16_t Version, uint64_t Hash, bool IsDWO);
+  DWARFTypeUnit *getTypeUnitForHash(uint64_t Hash, bool IsDWO);
 
   /// Return the DWARF unit that includes an offset (relative to .debug_info).
   DWARFUnit *getUnitForOffset(uint64_t Offset);

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 7fba00d0e457b6..ea336378bebb33 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -635,7 +635,7 @@ std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUIndex() const {
   if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
     return Off->getAsUnsignedConstant();
   // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
-  // implicitly refer to the single CU. 
+  // implicitly refer to the single CU.
   if (NameIdx->getCUCount() == 1)
     return 0;
   return std::nullopt;
@@ -665,7 +665,7 @@ std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUOffset() const {
 }
 
 std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUOffset() const {
-  std::optional<uint64_t> Index = getLocalTUIndex();
+  std::optional<uint64_t> Index = getTUIndex();
   if (!Index || *Index >= NameIdx->getLocalTUCount())
     return std::nullopt;
   return NameIdx->getLocalTUOffset(*Index);
@@ -673,7 +673,7 @@ std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUOffset() const {
 
 std::optional<uint64_t>
 DWARFDebugNames::Entry::getForeignTUTypeSignature() const {
-  std::optional<uint64_t> Index = getLocalTUIndex();
+  std::optional<uint64_t> Index = getTUIndex();
   const uint32_t NumLocalTUs = NameIdx->getLocalTUCount();
   if (!Index || *Index < NumLocalTUs)
     return std::nullopt; // Invalid TU index or TU index is for a local TU
@@ -684,7 +684,7 @@ DWARFDebugNames::Entry::getForeignTUTypeSignature() const {
   return NameIdx->getForeignTUSignature(ForeignTUIndex);
 }
 
-std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUIndex() const {
+std::optional<uint64_t> DWARFDebugNames::Entry::getTUIndex() const {
   if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_type_unit))
     return Off->getAsUnsignedConstant();
   return std::nullopt;
@@ -1061,14 +1061,16 @@ DWARFDebugNames::equal_range(StringRef Key) const {
 }
 
 const DWARFDebugNames::NameIndex *
-DWARFDebugNames::getCUNameIndex(uint64_t CUOffset) {
-  if (CUToNameIndex.size() == 0 && NameIndices.size() > 0) {
+DWARFDebugNames::getCUOrTUNameIndex(uint64_t UnitOffset) {
+  if (UnitOffsetToNameIndex.size() == 0 && NameIndices.size() > 0) {
     for (const auto &NI : *this) {
       for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
-        CUToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
+        UnitOffsetToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
+      for (uint32_t TU = 0; TU < NI.getLocalTUCount(); ++TU)
+        UnitOffsetToNameIndex.try_emplace(NI.getLocalTUOffset(TU), &NI);
     }
   }
-  return CUToNameIndex.lookup(CUOffset);
+  return UnitOffsetToNameIndex.lookup(UnitOffset);
 }
 
 static bool isObjCSelector(StringRef Name) {

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index bca0d179dacf21..e8337571fb2c0f 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -1345,8 +1345,7 @@ void DWARFContext::dump(
     getDebugNames().dump(OS);
 }
 
-DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint16_t Version, uint64_t Hash,
-                                                bool IsDWO) {
+DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint64_t Hash, bool IsDWO) {
   DWARFUnitVector &DWOUnits = State->getDWOUnits();
   if (const auto &TUI = getTUIndex()) {
     if (const auto *R = TUI.getFromHash(Hash))
@@ -2478,3 +2477,5 @@ uint8_t DWARFContext::getCUAddrSize() {
   auto CUs = compile_units();
   return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize();
 }
+
+bool DWARFContext::isDWP() const { return !DObj->getCUIndexSection().empty(); }

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 6e7b5870dfa29f..c1cd587877de0c 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -319,8 +319,8 @@ DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
     if (DWARFUnit *SpecUnit = U->getUnitVector().getUnitForOffset(*Offset))
       Result = SpecUnit->getDIEForOffset(*Offset);
   } else if (std::optional<uint64_t> Sig = V.getAsSignatureReference()) {
-    if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash(
-            U->getVersion(), *Sig, U->isDWOUnit()))
+    if (DWARFTypeUnit *TU =
+            U->getContext().getTypeUnitForHash(*Sig, U->isDWOUnit()))
       Result = TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());
   }
   return Result;
@@ -329,8 +329,8 @@ DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
 DWARFDie DWARFDie::resolveTypeUnitReference() const {
   if (auto Attr = find(DW_AT_signature)) {
     if (std::optional<uint64_t> Sig = Attr->getAsReferenceUVal()) {
-      if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash(
-              U->getVersion(), *Sig, U->isDWOUnit()))
+      if (DWARFTypeUnit *TU =
+              U->getContext().getTypeUnitForHash(*Sig, U->isDWOUnit()))
         return TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());
     }
   }

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index fa3e8ad21dbd4d..1fe3eb1e90fe65 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -24,6 +24,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/Object/Error.h"
 #include "llvm/Support/DJB.h"
@@ -1479,13 +1480,6 @@ unsigned DWARFVerifier::verifyNameIndexAttribute(
 
 unsigned
 DWARFVerifier::verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI) {
-  if (NI.getForeignTUCount() > 0) {
-    warn() << formatv("Name Index @ {0:x}: Verifying indexes of foreign type "
-                      "units is not currently supported.\n",
-                      NI.getUnitOffset());
-    return 0;
-  }
-
   unsigned NumErrors = 0;
   for (const auto &Abbrev : NI.getAbbrevs()) {
     StringRef TagName = dwarf::TagString(Abbrev.Tag);
@@ -1573,10 +1567,6 @@ static SmallVector<std::string, 3> getNames(const DWARFDie &DIE,
 unsigned DWARFVerifier::verifyNameIndexEntries(
     const DWARFDebugNames::NameIndex &NI,
     const DWARFDebugNames::NameTableEntry &NTE) {
-  // Verifying foreign type unit indexes not supported.
-  if (NI.getForeignTUCount() > 0)
-    return 0;
-
   const char *CStr = NTE.getString();
   if (!CStr) {
     ErrorCategory.Report("Unable to get string associated with name", [&]() {
@@ -1596,8 +1586,8 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
   for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
                                 EntryOr = NI.getEntry(&NextEntryID)) {
 
-    std::optional<uint64_t> CUIndex = EntryOr->getCUIndex();
-    std::optional<uint64_t> TUIndex = EntryOr->getLocalTUIndex();
+    std::optional<uint64_t> CUIndex = EntryOr->getRelatedCUIndex();
+    std::optional<uint64_t> TUIndex = EntryOr->getTUIndex();
     if (CUIndex && *CUIndex >= NI.getCUCount()) {
       ErrorCategory.Report("Name Index entry contains invalid CU index", [&]() {
         error() << formatv("Name Index @ {0:x}: Entry @ {1:x} contains an "
@@ -1607,7 +1597,9 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
       ++NumErrors;
       continue;
     }
-    if (TUIndex && *TUIndex >= NI.getLocalTUCount()) {
+    const uint32_t NumLocalTUs = NI.getLocalTUCount();
+    const uint32_t NumForeignTUs = NI.getForeignTUCount();
+    if (TUIndex && *TUIndex >= (NumLocalTUs + NumForeignTUs)) {
       ErrorCategory.Report("Name Index entry contains invalid TU index", [&]() {
         error() << formatv("Name Index @ {0:x}: Entry @ {1:x} contains an "
                            "invalid TU index ({2}).\n",
@@ -1617,11 +1609,44 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
       continue;
     }
     std::optional<uint64_t> UnitOffset;
-    if (TUIndex)
-      UnitOffset = NI.getLocalTUOffset(*TUIndex);
-    else if (CUIndex)
+    if (TUIndex) {
+      // We have a local or foreign type unit.
+      if (*TUIndex >= NumLocalTUs) {
+        // This is a foreign type unit, we will find the right type unit by
+        // type unit signature later in this function.
+
+        // Foreign type units must have a valid CU index, either from a
+        // DW_IDX_comp_unit attribute value or from the .debug_names table only
+        // having a single compile unit. We need the originating compile unit
+        // because foreign type units can come from any .dwo file, yet only one
+        // copy of the type unit will end up in the .dwp file.
+        if (CUIndex) {
+          // We need the local skeleton unit offset for the code below.
+          UnitOffset = NI.getCUOffset(*CUIndex);
+        } else {
+          ErrorCategory.Report(
+              "Name Index entry contains foreign TU index with invalid CU "
+              "index",
+              [&]() {
+                error() << formatv(
+                    "Name Index @ {0:x}: Entry @ {1:x} contains an "
+                    "foreign TU index ({2}) with no CU index.\n",
+                    NI.getUnitOffset(), EntryID, *TUIndex);
+              });
+          ++NumErrors;
+          continue;
+        }
+      } else {
+        // Local type unit, get the DWARF unit offset for the type unit.
+        UnitOffset = NI.getLocalTUOffset(*TUIndex);
+      }
+    } else if (CUIndex) {
+      // Local CU entry, get the DWARF unit offset for the CU.
       UnitOffset = NI.getCUOffset(*CUIndex);
-    if (!UnitOffset)
+    }
+
+    // Watch for tombstoned type unit entries.
+    if (!UnitOffset || UnitOffset == UINT32_MAX)
       continue;
     // For split DWARF entries we need to make sure we find the non skeleton
     // DWARF unit that is needed and use that's DWARF unit offset as the
@@ -1633,7 +1658,7 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
       ErrorCategory.Report(
           "Name Index entry contains invalid CU or TU offset", [&]() {
             error() << formatv("Name Index @ {0:x}: Entry @ {1:x} contains an "
-                               "invalid CU or TU offset {1:x}.\n",
+                               "invalid CU or TU offset {2:x}.\n",
                                NI.getUnitOffset(), EntryID, *UnitOffset);
           });
       ++NumErrors;
@@ -1650,20 +1675,52 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
     // call to properly deal with it. It isn't clear that getNonSkeletonUnitDIE
     // will return the unit DIE of DU if we aren't able to get the .dwo file,
     // but that is what the function currently does.
+    DWARFDie UnitDie = DU->getUnitDIE();
     DWARFDie NonSkeletonUnitDie = DU->getNonSkeletonUnitDIE();
-    if (DU->getDWOId() && DU->getUnitDIE() == NonSkeletonUnitDie) {
+    if (DU->getDWOId() && UnitDie == NonSkeletonUnitDie) {
       ErrorCategory.Report("Unable to get load .dwo file", [&]() {
-        error() << formatv("Name Index @ {0:x}: Entry @ {1:x} unable to load "
-                           ".dwo file \"{2}\" for DWARF unit @ {3:x}.\n",
-                           NI.getUnitOffset(), EntryID,
-                           dwarf::toString(DU->getUnitDIE().find(
-                               {DW_AT_dwo_name, DW_AT_GNU_dwo_name})),
-                           *UnitOffset);
+        error() << formatv(
+            "Name Index @ {0:x}: Entry @ {1:x} unable to load "
+            ".dwo file \"{2}\" for DWARF unit @ {3:x}.\n",
+            NI.getUnitOffset(), EntryID,
+            dwarf::toString(UnitDie.find({DW_AT_dwo_name, DW_AT_GNU_dwo_name})),
+            *UnitOffset);
       });
       ++NumErrors;
       continue;
     }
-    DWARFUnit *NonSkeletonUnit = NonSkeletonUnitDie.getDwarfUnit();
+    DWARFUnit *NonSkeletonUnit = nullptr;
+    if (TUIndex && *TUIndex >= NumLocalTUs) {
+      // We have a foreign TU index, which either means we have a .dwo file
+      // that has one or more type units, or we have a .dwp file with one or
+      // more type units. We need to get the type unit from the DWARFContext
+      // of the .dwo. We got the NonSkeletonUnitDie above that has the .dwo
+      // or .dwp DWARF context, so we have to get the type unit from that file.
+      // We have also verified that NonSkeletonUnitDie points to a DWO file
+      // above, so we know we have the right file.
+      const uint32_t ForeignTUIdx = *TUIndex - NumLocalTUs;
+      const uint64_t TypeSig = NI.getForeignTUSignature(ForeignTUIdx);
+      llvm::DWARFContext &SkeletonDCtx =
+          NonSkeletonUnitDie.getDwarfUnit()->getContext();
+      // Now find the type unit from the type signature and then update the
+      // NonSkeletonUnitDie to point to the actual type unit in the .dwo/.dwp.
+      NonSkeletonUnit =
+          SkeletonDCtx.getTypeUnitForHash(TypeSig, /*IsDWO=*/true);
+      NonSkeletonUnitDie = NonSkeletonUnit->getUnitDIE(true);
+      // If we have foreign type unit in a DWP file, then we need to ignore
+      // any entries from type units that don't match the one that made it into
+      // the .dwp file.
+      if (SkeletonDCtx.isDWP()) {
+        StringRef DUDwoName = dwarf::toStringRef(
+            UnitDie.find({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
+        StringRef TUDwoName = dwarf::toStringRef(
+            NonSkeletonUnitDie.find({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
+        if (DUDwoName != TUDwoName)
+          continue; // Skip this TU, it isn't the one in the .dwp file.
+      }
+    } else {
+      NonSkeletonUnit = NonSkeletonUnitDie.getDwarfUnit();
+    }
     uint64_t DIEOffset =
         NonSkeletonUnit->getOffset() + *EntryOr->getDIEUnitOffset();
     const uint64_t NextUnitOffset = NonSkeletonUnit->getNextUnitOffset();
@@ -1920,15 +1977,26 @@ unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
     for (const DWARFDebugNames::NameTableEntry &NTE : NI)
       NumErrors += verifyNameIndexEntries(NI, NTE);
 
-  if (NumErrors > 0)
-    return NumErrors;
-
-  for (const std::unique_ptr<DWARFUnit> &U : DCtx.compile_units()) {
+  for (const std::unique_ptr<DWARFUnit> &U : DCtx.info_section_units()) {
     if (const DWARFDebugNames::NameIndex *NI =
-            AccelTable.getCUNameIndex(U->getOffset())) {
-      auto *CU = cast<DWARFCompileUnit>(U.get());
-      for (const DWARFDebugInfoEntry &Die : CU->dies())
-        NumErrors += verifyNameIndexCompleteness(DWARFDie(CU, &Die), *NI);
+            AccelTable.getCUOrTUNameIndex(U->getOffset())) {
+      DWARFCompileUnit *CU = dyn_cast<DWARFCompileUnit>(U.get());
+      if (CU) {
+        if (CU->getDWOId()) {
+          DWARFDie CUDie = CU->getUnitDIE(true);
+          DWARFDie NonSkeletonUnitDie =
+              CUDie.getDwarfUnit()->getNonSkeletonUnitDIE(false);
+          if (CUDie != NonSkeletonUnitDie) {
+            for (const DWARFDebugInfoEntry &Die :
+                 NonSkeletonUnitDie.getDwarfUnit()->dies())
+              NumErrors += verifyNameIndexCompleteness(
+                  DWARFDie(NonSkeletonUnitDie.getDwarfUnit(), &Die), *NI);
+          }
+        } else {
+          for (const DWARFDebugInfoEntry &Die : CU->dies())
+            NumErrors += verifyNameIndexCompleteness(DWARFDie(CU, &Die), *NI);
+        }
+      }
     }
   }
   return NumErrors;

diff  --git a/llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_dwo.yaml b/llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_dwo.yaml
new file mode 100644
index 00000000000000..3e0e8737291fe3
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_dwo.yaml
@@ -0,0 +1,44 @@
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+  SectionHeaderStringTable: .strtab
+Sections:
+  - Name:            .debug_info.dwo
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_EXCLUDE ]
+    AddressAlign:    0x1
+    Content:         3A0000000500060800000000F25C0974DC2049EF210000000121000304000000000205070400020305300000000004000439000000060003000501050400320000000500060800000000F111DEDB09E62F8A2100000001210003040000000002050A0400070309310000000008000005010504005300000005000508000000004F3AF08A9CD57502060B21000C04070021000000015600000B400000000802917802000C440000000802917408000D4D000000000501050409F25C0974DC2049EF09F111DEDB09E62F8A00
+  - Name:            .debug_str_offsets.dwo
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_EXCLUDE ]
+    AddressAlign:    0x1
+    Content:         38000000050000000000000005000000090000000B0000000D0000001600000018000000240000002F00000034000000360000003F000000AF000000
+  - Name:            .debug_str.dwo
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x1
+    EntSize:         0x1
+    Content:         6D61696E00696E740063002E006D61696E2E64776F007800496E74656765725479706500437573746F6D547970650063617270006100436172705479706500636C616E672076657273696F6E2032302E302E30676974202868747470733A2F2F6769746875622E636F6D2F636C6179626F72672F6C6C766D2D70726F6A6563742E676974203937383833363863333763333139623131656239613331616630663130616163363262613466373229006D61696E2E63707000
+  - Name:            .debug_abbrev.dwo
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_EXCLUDE ]
+    AddressAlign:    0x1
+    Content:         01410113051B25762510170000021301360B03250B0B3A0B3B0B0000030D00032549133A0B3B0B380B0000041600491303253A0B3B0B000005240003253E0B0B0B000006110125251305032576250000072E01111B1206401803253A0B3B0B49133F190000083400021803253A0B3B0B491300000913003C196920000000
+  - Name:            .debug_line.dwo
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_EXCLUDE ]
+    AddressAlign:    0x1
+    Content:         36000000050008002E000000010101FB0E01010108012E00030108020F051E016D61696E2E6370700000D76E37CBD0032FAB59BE5997238B5EB3
+  - Type:            SectionHeaderTable
+    Sections:
+      - Name:            .strtab
+      - Name:            .debug_info.dwo
+      - Name:            .debug_str_offsets.dwo
+      - Name:            .debug_str.dwo
+      - Name:            .debug_abbrev.dwo
+      - Name:            .debug_line.dwo
+...
+

diff  --git a/llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_exe.yaml b/llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_exe.yaml
new file mode 100644
index 00000000000000..dd87fdcd4b4c3a
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_exe.yaml
@@ -0,0 +1,109 @@
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+ProgramHeaders:
+  - Type:            PT_PHDR
+    Flags:           [ PF_R ]
+    VAddr:           0x200040
+    Align:           0x8
+    Offset:          0x40
+  - Type:            PT_LOAD
+    Flags:           [ PF_R ]
+    FirstSec:        .rodata
+    LastSec:         .eh_frame
+    VAddr:           0x200000
+    Align:           0x1000
+    Offset:          0x0
+  - Type:            PT_LOAD
+    Flags:           [ PF_X, PF_R ]
+    FirstSec:        .text
+    LastSec:         .text
+    VAddr:           0x201170
+    Align:           0x1000
+    Offset:          0x170
+  - Type:            PT_GNU_STACK
+    Flags:           [ PF_W, PF_R ]
+    Align:           0x0
+    Offset:          0x0
+Sections:
+  - Name:            .rodata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_MERGE ]
+    Address:         0x200120
+    AddressAlign:    0x4
+    EntSize:         0x4
+    Content:         '0200000001000000'
+  - Name:            .eh_frame
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x200128
+    AddressAlign:    0x8
+    Content:         1400000000000000017A5200017810011B0C0708900100001C0000001C000000281000002100000000410E108602430D065C0C070800000000000000
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x201170
+    AddressAlign:    0x10
+    Content:         554889E5C745FC000000008B05A3EFFFFF8945F88B0596EFFFFF8945F431C05DC3
+  - Name:            .debug_abbrev
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x1
+    Content:         014A00101772171B257625111B12067317000000
+  - Name:            .debug_info
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x1
+    Content:         2400000005000408000000004F3AF08A9CD575020100000000080000000001002100000008000000
+  - Name:            .debug_str_offsets
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x1
+    Content:         0C000000050000001200000009000000
+  - Name:            .debug_names
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x4
+    Content:         EC0000000500000001000000000000000200000005000000050000002F000000080000004C4C564D3037303000000000F25C0974DC2049EFF111DEDB09E62F8A000000000100000004000000050000000000000042877C10CD1F12166A7F9A7C15BDEE453080880B14000000000000001F000000280000002400000000000000070000000E000000140000001F0000000113020B031304190000022E0313041900000316020B0313041300000424020B0313041900000524031304190000000100210000000001012100000000021A000000000300300000000000000000040131000000040039000000054000000000
+  - Name:            .comment
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x1
+    EntSize:         0x1
+    Content:         4C696E6B65723A204C4C442032302E302E30202868747470733A2F2F6769746875622E636F6D2F636C6179626F72672F6C6C766D2D70726F6A6563742E6769742039373838333638633337633331396231316562396133316166306631306161633632626134663732290000636C616E672076657273696F6E2032302E302E30676974202868747470733A2F2F6769746875622E636F6D2F636C6179626F72672F6C6C766D2D70726F6A6563742E67697420393738383336386333376333313962313165623961333161663066313061616336326261346637322900
+  - Name:            .debug_line
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x1
+    Content:         610000000500080037000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E010200000000D76E37CBD0032FAB59BE5997238B5EB304000009027011200000000000030A01050E0AAD050C91050391060B2E0202000101
+  - Name:            .debug_line_str
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x1
+    EntSize:         0x1
+    Content:         2E006D61696E2E63707000
+Symbols:
+  - Name:            main.cpp
+    Type:            STT_FILE
+    Index:           SHN_ABS
+  - Name:            main
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x201170
+    Size:            0x21
+DWARF:
+  debug_str:
+    - CarpType
+    - main.dwo
+    - .
+    - CustomType
+    - main
+    - int
+    - IntegerType
+  debug_addr:
+    - Length:          0xC
+      Version:         0x5
+      AddressSize:     0x8
+      Entries:
+        - Address:         0x201170
+...
+

diff  --git a/llvm/test/tools/llvm-dwarfdump/verify_split_dwarf_debug_names_ftus.test b/llvm/test/tools/llvm-dwarfdump/verify_split_dwarf_debug_names_ftus.test
new file mode 100644
index 00000000000000..03ba63bd9b0d77
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/verify_split_dwarf_debug_names_ftus.test
@@ -0,0 +1,36 @@
+# Verify we can successfully verify .debug_names with split DWARF.
+#
+# RUN: rm -rf %t1/
+# RUN: mkdir %t1
+# RUN: yaml2obj %p/Inputs/verify_split_dwarf_debug_names_ftus_exe.yaml > %t1/a.out
+# RUN: yaml2obj %p/Inputs/verify_split_dwarf_debug_names_ftus_dwo.yaml > %t1/main.dwo
+# RUN: cd %t1
+# RUN: llvm-dwarfdump --verify %t1/a.out | FileCheck %s
+
+# CHECK: Verifying unit: 1 / 1
+# CHECK: Verifying dwo Units...
+# CHECK: Verifying .debug_line...
+# CHECK: Verifying .debug_str_offsets...
+# CHECK: Verifying .debug_names...
+# CHECK: No errors.
+
+# Now verify if we remove the "main.dwo" file that we get an error letting us
+# know that the .dwo file was not able to be found.
+# RUN: rm %t1/main.dwo
+# RUN: not llvm-dwarfdump --verify %t1/a.out | FileCheck --check-prefix=NODWO %s
+
+# NODWO: Verifying unit: 1 / 1
+# NODWO: Verifying dwo Units...
+# NODWO: Verifying .debug_line...
+# NODWO: Verifying .debug_str_offsets...
+# NODWO: Verifying .debug_names...
+# NODWO: error: Name Index @ 0x0: Entry @ 0xbf unable to load .dwo file "main.dwo" for DWARF unit @ 0x0.
+# NODWO: error: Name Index @ 0x0: Entry @ 0xc6 unable to load .dwo file "main.dwo" for DWARF unit @ 0x0.
+# NODWO: error: Name Index @ 0x0: Entry @ 0xcd unable to load .dwo file "main.dwo" for DWARF unit @ 0x0.
+# NODWO: error: Name Index @ 0x0: Entry @ 0xd3 unable to load .dwo file "main.dwo" for DWARF unit @ 0x0.
+# NODWO: error: Name Index @ 0x0: Entry @ 0xde unable to load .dwo file "main.dwo" for DWARF unit @ 0x0.
+# NODWO: error: Name Index @ 0x0: Entry @ 0xe4 unable to load .dwo file "main.dwo" for DWARF unit @ 0x0.
+# NODWO: error: Name Index @ 0x0: Entry @ 0xea unable to load .dwo file "main.dwo" for DWARF unit @ 0x0.
+# NODWO: error: Aggregated error counts:
+# NODWO: error: Unable to get load .dwo file occurred 7 time(s).
+# NODWO: Errors detected.


        


More information about the llvm-commits mailing list