[llvm] 2e7ee4d - [DWARFVerifier] Allow simplified template names in debug_name

Felipe de Azevedo Piovezan via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 14 07:22:30 PDT 2023


Author: Felipe de Azevedo Piovezan
Date: 2023-08-14T10:22:17-04:00
New Revision: 2e7ee4dc21430b0fe4c9ee306dc1d8c7986a6646

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

LOG: [DWARFVerifier] Allow simplified template names in debug_name

LLDB can benefit from having the base name of functions (i.e. without any
template parameters) as an entry into accelerator tables pointing back in the
DIE for the corresponding function specialization. In fact, some LLDB
functionality is only possible when those entries are present.

The DWARFLinker has been adding such entries for a while now, both with
apple_names and with debug_names. However, this has two side effects:

1. Some LLDB functionality is only possible when dsym bundles are present (i.e.
the linker touched the debug info).
2. The DWARFVerifier doesn't accept debug_name sections created by the linker,
as such names are (usually) neither the AT_name nor the AT_linkage_name of the
DIE.

Based on recent discussion [1], and because the DWARF 5 spec says that:

> A producer may choose to implement additional rules for what names are placed
> in the index

This patch relaxes the checks on the verifier to allow for simplified template
names in the accelerator table. To do so, we move some helper functions from
DWARFLinker into the core lib debug info. This addresses the point 2) above.

This patch also enables addressing point 1) in the future, since the helper
function is now visible to other parts of LLVM.

[1]: https://github.com/llvm/llvm-project/issues/58362

Differential Revision: https://reviews.llvm.org/D155723

Added: 
    

Modified: 
    llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
    llvm/lib/DWARFLinker/DWARFLinker.cpp
    llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
    llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
    llvm/test/tools/dsymutil/X86/dwarf5-accel.test

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index ce5d2f6c1457dc..d8279d35ba3b81 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -743,6 +743,12 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
   const NameIndex *getCUNameIndex(uint64_t CUOffset);
 };
 
+/// If `Name` is the name of a templated function that includes template
+/// parameters, returns a substring of `Name` containing no template
+/// parameters.
+/// E.g.: StripTemplateParameters("foo<int>") = "foo".
+std::optional<StringRef> StripTemplateParameters(StringRef Name);
+
 } // end namespace llvm
 
 #endif // LLVM_DEBUGINFO_DWARF_DWARFACCELERATORTABLE_H

diff  --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index 32191bfb4a991c..968fba2ffea251 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -15,6 +15,7 @@
 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
 #include "llvm/DWARFLinker/DWARFStreamer.h"
 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
@@ -140,37 +141,6 @@ AddressesMap::~AddressesMap() = default;
 
 DwarfEmitter::~DwarfEmitter() = default;
 
-static std::optional<StringRef> StripTemplateParameters(StringRef Name) {
-  // We are looking for template parameters to strip from Name. e.g.
-  //
-  //  operator<<B>
-  //
-  // We look for > at the end but if it does not contain any < then we
-  // have something like operator>>. We check for the operator<=> case.
-  if (!Name.endswith(">") || Name.count("<") == 0 || Name.endswith("<=>"))
-    return {};
-
-  // How many < until we have the start of the template parameters.
-  size_t NumLeftAnglesToSkip = 1;
-
-  // If we have operator<=> then we need to skip its < as well.
-  NumLeftAnglesToSkip += Name.count("<=>");
-
-  size_t RightAngleCount = Name.count('>');
-  size_t LeftAngleCount = Name.count('<');
-
-  // If we have more < than > we have operator< or operator<<
-  // we to account for their < as well.
-  if (LeftAngleCount > RightAngleCount)
-    NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
-
-  size_t StartOfTemplate = 0;
-  while (NumLeftAnglesToSkip--)
-    StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
-
-  return Name.substr(0, StartOfTemplate - 1);
-}
-
 bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die,
                                          AttributesInfo &Info,
                                          OffsetsStringPool &StringPool,

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 14962cd36c2359..97a0a438b882ae 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -969,3 +969,34 @@ DWARFDebugNames::getCUNameIndex(uint64_t CUOffset) {
   }
   return CUToNameIndex.lookup(CUOffset);
 }
+
+std::optional<StringRef> llvm::StripTemplateParameters(StringRef Name) {
+  // We are looking for template parameters to strip from Name. e.g.
+  //
+  //  operator<<B>
+  //
+  // We look for > at the end but if it does not contain any < then we
+  // have something like operator>>. We check for the operator<=> case.
+  if (!Name.endswith(">") || Name.count("<") == 0 || Name.endswith("<=>"))
+    return {};
+
+  // How many < until we have the start of the template parameters.
+  size_t NumLeftAnglesToSkip = 1;
+
+  // If we have operator<=> then we need to skip its < as well.
+  NumLeftAnglesToSkip += Name.count("<=>");
+
+  size_t RightAngleCount = Name.count('>');
+  size_t LeftAngleCount = Name.count('<');
+
+  // If we have more < than > we have operator< or operator<<
+  // we to account for their < as well.
+  if (LeftAngleCount > RightAngleCount)
+    NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
+
+  size_t StartOfTemplate = 0;
+  while (NumLeftAnglesToSkip--)
+    StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
+
+  return Name.substr(0, StartOfTemplate - 1);
+}

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 58900e1e80cbfa..8f9b0c8f196906 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -1351,12 +1351,18 @@ DWARFVerifier::verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI) {
   return NumErrors;
 }
 
-static SmallVector<StringRef, 2> getNames(const DWARFDie &DIE,
+static SmallVector<StringRef, 3> getNames(const DWARFDie &DIE,
+                                          bool IncludeStrippedTemplateNames,
                                           bool IncludeLinkageName = true) {
   SmallVector<StringRef, 2> Result;
-  if (const char *Str = DIE.getShortName())
+  if (const char *Str = DIE.getShortName()) {
     Result.emplace_back(Str);
-  else if (DIE.getTag() == dwarf::DW_TAG_namespace)
+    if (IncludeStrippedTemplateNames) {
+      if (std::optional<StringRef> StrippedName =
+              StripTemplateParameters(Result.back()))
+        Result.push_back(*StrippedName);
+    }
+  } else if (DIE.getTag() == dwarf::DW_TAG_namespace)
     Result.emplace_back("(anonymous namespace)");
 
   if (IncludeLinkageName) {
@@ -1423,7 +1429,12 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
       ++NumErrors;
     }
 
-    auto EntryNames = getNames(DIE);
+    // We allow an extra name for functions: their name without any template
+    // parameters.
+    auto IncludeStrippedTemplateNames =
+        DIE.getTag() == DW_TAG_subprogram ||
+        DIE.getTag() == DW_TAG_inlined_subroutine;
+    auto EntryNames = getNames(DIE, IncludeStrippedTemplateNames);
     if (!is_contained(EntryNames, Str)) {
       error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched Name "
                          "of DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
@@ -1496,7 +1507,11 @@ unsigned DWARFVerifier::verifyNameIndexCompleteness(
   // the linkage name."
   auto IncludeLinkageName = Die.getTag() == DW_TAG_subprogram ||
                             Die.getTag() == DW_TAG_inlined_subroutine;
-  auto EntryNames = getNames(Die, IncludeLinkageName);
+  // We *allow* stripped template names as an extra entry into the template,
+  // but we don't *require* them to pass the completeness test.
+  auto IncludeStrippedTemplateNames = false;
+  auto EntryNames =
+      getNames(Die, IncludeStrippedTemplateNames, IncludeLinkageName);
   if (EntryNames.empty())
     return 0;
 

diff  --git a/llvm/test/tools/dsymutil/X86/dwarf5-accel.test b/llvm/test/tools/dsymutil/X86/dwarf5-accel.test
index 2516d7681415b6..2bbe8775587c57 100644
--- a/llvm/test/tools/dsymutil/X86/dwarf5-accel.test
+++ b/llvm/test/tools/dsymutil/X86/dwarf5-accel.test
@@ -13,12 +13,10 @@
 ## $ clang -gdwarf-5 dwarf5-accel.cpp -c -o dwarf5-accel.o
 
 #RUN: dsymutil -accelerator=Dwarf -oso-prepend-path %p/Inputs -y %s -o %t.dSYM
-#COM: Uncomment next line when dwarfdump will handle stripped template names.
-#COM: llvm-dwarfdump --verify  %t.dSYM | FileCheck %s --check-prefix VERIFY
+#RUN: llvm-dwarfdump --verify  %t.dSYM | FileCheck %s --check-prefix VERIFY
 #RUN: llvm-dwarfdump -a --verbose  %t.dSYM | FileCheck %s
 
-#COM: Uncomment next line when dwarfdump will handle stripped template names.
-#COM: #VERIFY: No errors.
+#VERIFY: No errors.
 
 #CHECK: .debug_names
 #CHECK: "foo"


        


More information about the llvm-commits mailing list