Skip to content

Add verification support for .debug_names with foreign type units. #109011

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 22, 2024

Conversation

clayborg
Copy link
Collaborator

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

@llvmbot
Copy link
Member

llvmbot commented Sep 17, 2024

@llvm/pr-subscribers-debuginfo

Author: Greg Clayton (clayborg)

Changes

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


Patch is 25.02 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/109011.diff

9 Files Affected:

  • (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h (+5-5)
  • (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h (+4-1)
  • (modified) llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp (+7-5)
  • (modified) llvm/lib/DebugInfo/DWARF/DWARFContext.cpp (+3-2)
  • (modified) llvm/lib/DebugInfo/DWARF/DWARFDie.cpp (+3-3)
  • (modified) llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp (+83-32)
  • (added) llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_dwo.yaml (+44)
  • (added) llvm/test/tools/llvm-dwarfdump/Inputs/verify_split_dwarf_debug_names_ftus_exe.yaml (+109)
  • (added) llvm/test/tools/llvm-dwarfdump/verify_split_dwarf_debug_names_ftus.test (+36)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 0117c90e77f990..2320c1da37f57c 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;
@@ -803,7 +803,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 +820,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..e02c54829594dd 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;
@@ -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 9c26c4f8892b01..ad2bf6784d5745 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -320,7 +320,7 @@ DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
       Result = SpecUnit->getDIEForOffset(*Offset);
   } else if (std::optional<uint64_t> Sig = V.getAsSignatureReference()) {
     if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash(
-            U->getVersion(), *Sig, U->isDWOUnit()))
+            *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 eb2751ab30ac50..be4e69f2a06455 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"
@@ -1481,13 +1482,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);
@@ -1575,10 +1569,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", [&]() {
@@ -1598,7 +1588,7 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
   for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
                                 EntryOr = NI.getEntry(&NextEntryID)) {
 
-    std::optional<uint64_t> CUIndex = EntryOr->getCUIndex();
+    std::optional<uint64_t> CUIndex = EntryOr->getRelatedCUIndex();
     std::optional<uint64_t> TUIndex = EntryOr->getLocalTUIndex();
     if (CUIndex && *CUIndex >= NI.getCUCount()) {
       ErrorCategory.Report("Name Index entry contains invalid CU index", [&]() {
@@ -1609,7 +1599,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",
@@ -1619,10 +1611,28 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
       continue;
     }
     std::optional<uint64_t> UnitOffset;
-    if (TUIndex)
-      UnitOffset = NI.getLocalTUOffset(*TUIndex);
-    else if (CUIndex)
+    if (CUIndex)
       UnitOffset = NI.getCUOffset(*CUIndex);
+    else if (TUIndex) {
+      if (*TUIndex >= NumLocalTUs) {
+        // 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.
+        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;
+      }
+      UnitOffset = NI.getLocalTUOffset(*TUIndex);
+    }
     if (!UnitOffset)
       continue;
     // For split DWARF entries we need to make sure we find the non skeleton
@@ -1652,20 +1662,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 on 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();
@@ -1922,15 +1964,24 @@ 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 = cast<DWARFCompileUnit>(U.get());
+      if (CU && 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:         0x2...
[truncated]

Copy link

github-actions bot commented Sep 17, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

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 on or
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: on or => one or

@@ -1598,7 +1588,7 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
EntryOr = NI.getEntry(&NextEntryID)) {

std::optional<uint64_t> CUIndex = EntryOr->getCUIndex();
std::optional<uint64_t> CUIndex = EntryOr->getRelatedCUIndex();
std::optional<uint64_t> TUIndex = EntryOr->getLocalTUIndex();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the API be renamed from getLocalTUIndex() be getTUIndex() since the returned index can be either local or foreign type unit index now?

Comment on lines 1617 to 1628
if (*TUIndex >= NumLocalTUs) {
// 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.
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);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment does not seem to align with the code?
From the comment, I was expecting, we try to get DW_IDX_compile_unit attribute value from the Entry, then check it against NumCUCount. That is not what the logic here.

This commit enables 'llvm-dwarfdump --veriy' to verify the DWARF in foreign type units when using split DWARF for the .debug_names section.
@clayborg clayborg force-pushed the dwarfdump-verify-foreign-tus branch from b92585f to 04f9d9e Compare October 14, 2024 19:11
@clayborg
Copy link
Collaborator Author

ABove test suite failures needed to be fixed. I have found and fixed the issues with the latest diff.

@clayborg clayborg merged commit dc5c044 into llvm:main Oct 22, 2024
6 of 8 checks passed
@clayborg clayborg deleted the dwarfdump-verify-foreign-tus branch October 22, 2024 16:35
@clayborg
Copy link
Collaborator Author

Buildbots are failing due to this patch:
https://lab.llvm.org/buildbot/#/builders/11/builds/6984/steps/6/logs/stdio

I have a fix coming

@clayborg
Copy link
Collaborator Author

The buildbot issue was fixed with:

commit 6803062eb7f2e5ca3db2695688239aa57cdbcd0e (HEAD -> main, origin/main, origin/HEAD)
Author: Kazu Hirata <[email protected]>
Date:   Tue Oct 22 10:20:20 2024 -0700

    [BOLT] Fix a build failure
    
    This patch fixes:
    
      bolt/lib/Core/DIEBuilder.cpp:285:40: error: too many arguments to
      function call, expected 2, have 3

@llvm-ci
Copy link
Collaborator

llvm-ci commented Oct 22, 2024

LLVM Buildbot has detected a new failure on builder bolt-x86_64-ubuntu-nfc running on bolt-worker while building llvm at step 7 "build-bolt".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/92/builds/8437

Here is the relevant piece of the build log for the reference
Step 7 (build-bolt) failure: build (failure)
...
      |                      ^~~~~~~~~~~~~~~~~~~~~~~
33.929 [137/18/1822] Building CXX object tools/bolt/lib/Passes/CMakeFiles/LLVMBOLTPasses.dir/BinaryPasses.cpp.o
In file included from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinarySection.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinaryContext.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Passes/BinaryPasses.h:16,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/lib/Passes/BinaryPasses.cpp:13:
/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/DebugData.h:512:22: warning: ‘maybe_unused’ attribute ignored [-Wattributes]
  512 |   DenseSet<uint64_t> DebugStrOffsetFinalized;
      |                      ^~~~~~~~~~~~~~~~~~~~~~~
34.171 [136/18/1823] Building CXX object tools/bolt/lib/Core/CMakeFiles/LLVMBOLTCore.dir/DIEBuilder.cpp.o
FAILED: tools/bolt/lib/Core/CMakeFiles/LLVMBOLTCore.dir/DIEBuilder.cpp.o 
ccache /usr/bin/c++ -DCMAKE_INSTALL_FULL_LIBDIR=\"/usr/local/lib\" -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/build/tools/bolt/lib/Core -I/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/lib/Core -I/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/build/include -I/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/llvm/include -I/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include -I/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/build/tools/bolt/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -fno-lifetime-dse -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wno-misleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -std=c++17 -MD -MT tools/bolt/lib/Core/CMakeFiles/LLVMBOLTCore.dir/DIEBuilder.cpp.o -MF tools/bolt/lib/Core/CMakeFiles/LLVMBOLTCore.dir/DIEBuilder.cpp.o.d -o tools/bolt/lib/Core/CMakeFiles/LLVMBOLTCore.dir/DIEBuilder.cpp.o -c /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/lib/Core/DIEBuilder.cpp
In file included from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinarySection.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinaryContext.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/DIEBuilder.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/lib/Core/DIEBuilder.cpp:9:
/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/DebugData.h:512:22: warning: ‘maybe_unused’ attribute ignored [-Wattributes]
  512 |   DenseSet<uint64_t> DebugStrOffsetFinalized;
      |                      ^~~~~~~~~~~~~~~~~~~~~~~
/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/lib/Core/DIEBuilder.cpp: In member function ‘void llvm::bolt::DIEBuilder::buildTypeUnits(llvm::bolt::DebugStrOffsetsWriter*, bool)’:
/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/lib/Core/DIEBuilder.cpp:284:39: error: no matching function for call to ‘llvm::DWARFContext::getTypeUnitForHash(unsigned int, uint64_t&, bool)’
  284 |       DwarfContext->getTypeUnitForHash(DwarfContext->getMaxVersion(), Signature,
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  285 |                                        true);
      |                                        ~~~~~
In file included from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/DebugData.h:19,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinarySection.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinaryContext.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/DIEBuilder.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/lib/Core/DIEBuilder.cpp:9:
/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h:268:18: note: candidate: ‘llvm::DWARFTypeUnit* llvm::DWARFContext::getTypeUnitForHash(uint64_t, bool)’
  268 |   DWARFTypeUnit *getTypeUnitForHash(uint64_t Hash, bool IsDWO);
      |                  ^~~~~~~~~~~~~~~~~~
/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h:268:18: note:   candidate expects 2 arguments, 3 provided
35.017 [136/17/1824] Building CXX object tools/bolt/lib/Core/CMakeFiles/LLVMBOLTCore.dir/GDBIndex.cpp.o
In file included from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinarySection.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinaryContext.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/GDBIndex.h:17,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/lib/Core/GDBIndex.cpp:9:
/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/DebugData.h:512:22: warning: ‘maybe_unused’ attribute ignored [-Wattributes]
  512 |   DenseSet<uint64_t> DebugStrOffsetFinalized;
      |                      ^~~~~~~~~~~~~~~~~~~~~~~
35.055 [136/16/1825] Building CXX object tools/bolt/lib/Core/CMakeFiles/LLVMBOLTCore.dir/BinaryFunctionProfile.cpp.o
In file included from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinarySection.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinaryContext.h:18,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/BinaryFunction.h:29,
                 from /home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/lib/Core/BinaryFunctionProfile.cpp:15:
/home/worker/bolt-worker2/bolt-x86_64-ubuntu-nfc/llvm-project/bolt/include/bolt/Core/DebugData.h:512:22: warning: ‘maybe_unused’ attribute ignored [-Wattributes]
  512 |   DenseSet<uint64_t> DebugStrOffsetFinalized;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants