[llvm] Add support for verifying .debug_names in split DWARF for CUs and TUs. (PR #101775)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 2 16:50:09 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-debuginfo

Author: Greg Clayton (clayborg)

<details>
<summary>Changes</summary>

This patch fixes .debug_names verification for split DWARF with no type units. It will print out an error for any name entries where we can't locate the .dwo file. It finds the non skeleton unit and correctly figures out the DIE offset in the .dwo file. If the non skeleton unit is found and yet the skeleton unit has a DWO ID, an error will be emitted showing we couldn't access the non-skeleton compile unit.

---
Full diff: https://github.com/llvm/llvm-project/pull/101775.diff


3 Files Affected:

- (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h (+3) 
- (modified) llvm/lib/DebugInfo/DWARF/DWARFContext.cpp (+5-2) 
- (modified) llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp (+44-3) 


``````````diff
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
index d800850450eb3..455ccaab74d7e 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -264,6 +264,9 @@ class DWARFContext : public DIContext {
   DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
   DWARFTypeUnit *getTypeUnitForHash(uint16_t Version, uint64_t Hash, bool IsDWO);
 
+  /// Return the DWARF unit that includes an offset (relative to .debug_info).
+  DWARFUnit *getUnitForOffset(uint64_t Offset);
+
   /// Return the compile unit that includes an offset (relative to .debug_info).
   DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset);
 
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index f36399ed00a6e..045f5e219d34a 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -1510,9 +1510,12 @@ DWARFUnitVector &DWARFContext::getDWOUnits(bool Lazy) {
   return State->getDWOUnits(Lazy);
 }
 
+DWARFUnit *DWARFContext::getUnitForOffset(uint64_t Offset) {
+  return State->getNormalUnits().getUnitForOffset(Offset);
+}
+
 DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) {
-  return dyn_cast_or_null<DWARFCompileUnit>(
-      State->getNormalUnits().getUnitForOffset(Offset));
+  return dyn_cast_or_null<DWARFCompileUnit>(getUnitForOffset(Offset));
 }
 
 DWARFCompileUnit *DWARFContext::getCompileUnitForCodeAddress(uint64_t Address) {
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 8ff6ebd230025..7c6da712d1276 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -1626,8 +1626,44 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
       UnitOffset = NI.getCUOffset(*CUIndex);
     if (!UnitOffset)
       continue;
-    uint64_t DIEOffset = *UnitOffset + *EntryOr->getDIEUnitOffset();
-    DWARFDie DIE = DCtx.getDIEForOffset(DIEOffset);
+    // 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
+    // DIE offset to add the DW_IDX_die_offset to.
+    DWARFUnit *DU = DCtx.getUnitForOffset(*UnitOffset);
+    if (DU == nullptr || DU->getOffset() != *UnitOffset) {
+      // If we didn't find a DWARF Unit from the UnitOffset, or if the offset
+      // of the unit doesn't match exactly, report an error.
+      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",
+                               NI.getUnitOffset(), EntryID, *UnitOffset);
+          });
+      ++NumErrors;
+      continue;
+    }
+    // This function will try to get the non skeleton unit DIE, but if it is
+    // unable to load the .dwo file from the .dwo or .dwp, it will return the
+    // unit DIE of the DWARFUnit in "DU". So we need to check if the DWARFUnit
+    // has a .dwo file, but we couldn't load it.
+    DWARFDie NonSkeletonUnitDie = DU->getNonSkeletonUnitDIE();
+    if (DU->getDWOId() && DU->getUnitDIE() == 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);
+      });
+      ++NumErrors;
+      continue;
+    }
+    DWARFUnit *NonSkeletonUnit = NonSkeletonUnitDie.getDwarfUnit();
+    uint64_t DIEOffset =
+        NonSkeletonUnit->getOffset() + *EntryOr->getDIEUnitOffset();
+    DWARFDie DIE = NonSkeletonUnit->getDIEForOffset(DIEOffset);
+
     if (!DIE) {
       ErrorCategory.Report("NameIndex references nonexistent DIE", [&]() {
         error() << formatv("Name Index @ {0:x}: Entry @ {1:x} references a "
@@ -1637,7 +1673,12 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
       ++NumErrors;
       continue;
     }
-    if (DIE.getDwarfUnit()->getOffset() != *UnitOffset) {
+    // Only compare the DIE we found's DWARFUnit offset if the DIE lives in
+    // the DWARFUnit from the DW_IDX_comp_unit or DW_IDX_type_unit. If we are
+    // using split DWARF, then the DIE's DWARFUnit doesn't need to match the
+    // skeleton unit.
+    if (DIE.getDwarfUnit() == DU &&
+        DIE.getDwarfUnit()->getOffset() != *UnitOffset) {
       ErrorCategory.Report("Name index contains mismatched CU of DIE", [&]() {
         error() << formatv(
             "Name Index @ {0:x}: Entry @ {1:x}: mismatched CU of "

``````````

</details>


https://github.com/llvm/llvm-project/pull/101775


More information about the llvm-commits mailing list