Skip to content

Commit 2e7ee4d

Browse files
[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]: llvm#58362 Differential Revision: https://reviews.llvm.org/D155723
1 parent 421c9bb commit 2e7ee4d

File tree

5 files changed

+60
-40
lines changed

5 files changed

+60
-40
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,12 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
743743
const NameIndex *getCUNameIndex(uint64_t CUOffset);
744744
};
745745

746+
/// If `Name` is the name of a templated function that includes template
747+
/// parameters, returns a substring of `Name` containing no template
748+
/// parameters.
749+
/// E.g.: StripTemplateParameters("foo<int>") = "foo".
750+
std::optional<StringRef> StripTemplateParameters(StringRef Name);
751+
746752
} // end namespace llvm
747753

748754
#endif // LLVM_DEBUGINFO_DWARF_DWARFACCELERATORTABLE_H

llvm/lib/DWARFLinker/DWARFLinker.cpp

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
1616
#include "llvm/DWARFLinker/DWARFStreamer.h"
1717
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
18+
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
1819
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
1920
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
2021
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
@@ -140,37 +141,6 @@ AddressesMap::~AddressesMap() = default;
140141

141142
DwarfEmitter::~DwarfEmitter() = default;
142143

143-
static std::optional<StringRef> StripTemplateParameters(StringRef Name) {
144-
// We are looking for template parameters to strip from Name. e.g.
145-
//
146-
// operator<<B>
147-
//
148-
// We look for > at the end but if it does not contain any < then we
149-
// have something like operator>>. We check for the operator<=> case.
150-
if (!Name.endswith(">") || Name.count("<") == 0 || Name.endswith("<=>"))
151-
return {};
152-
153-
// How many < until we have the start of the template parameters.
154-
size_t NumLeftAnglesToSkip = 1;
155-
156-
// If we have operator<=> then we need to skip its < as well.
157-
NumLeftAnglesToSkip += Name.count("<=>");
158-
159-
size_t RightAngleCount = Name.count('>');
160-
size_t LeftAngleCount = Name.count('<');
161-
162-
// If we have more < than > we have operator< or operator<<
163-
// we to account for their < as well.
164-
if (LeftAngleCount > RightAngleCount)
165-
NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
166-
167-
size_t StartOfTemplate = 0;
168-
while (NumLeftAnglesToSkip--)
169-
StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
170-
171-
return Name.substr(0, StartOfTemplate - 1);
172-
}
173-
174144
bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die,
175145
AttributesInfo &Info,
176146
OffsetsStringPool &StringPool,

llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,3 +969,34 @@ DWARFDebugNames::getCUNameIndex(uint64_t CUOffset) {
969969
}
970970
return CUToNameIndex.lookup(CUOffset);
971971
}
972+
973+
std::optional<StringRef> llvm::StripTemplateParameters(StringRef Name) {
974+
// We are looking for template parameters to strip from Name. e.g.
975+
//
976+
// operator<<B>
977+
//
978+
// We look for > at the end but if it does not contain any < then we
979+
// have something like operator>>. We check for the operator<=> case.
980+
if (!Name.endswith(">") || Name.count("<") == 0 || Name.endswith("<=>"))
981+
return {};
982+
983+
// How many < until we have the start of the template parameters.
984+
size_t NumLeftAnglesToSkip = 1;
985+
986+
// If we have operator<=> then we need to skip its < as well.
987+
NumLeftAnglesToSkip += Name.count("<=>");
988+
989+
size_t RightAngleCount = Name.count('>');
990+
size_t LeftAngleCount = Name.count('<');
991+
992+
// If we have more < than > we have operator< or operator<<
993+
// we to account for their < as well.
994+
if (LeftAngleCount > RightAngleCount)
995+
NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
996+
997+
size_t StartOfTemplate = 0;
998+
while (NumLeftAnglesToSkip--)
999+
StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
1000+
1001+
return Name.substr(0, StartOfTemplate - 1);
1002+
}

llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,12 +1351,18 @@ DWARFVerifier::verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI) {
13511351
return NumErrors;
13521352
}
13531353

1354-
static SmallVector<StringRef, 2> getNames(const DWARFDie &DIE,
1354+
static SmallVector<StringRef, 3> getNames(const DWARFDie &DIE,
1355+
bool IncludeStrippedTemplateNames,
13551356
bool IncludeLinkageName = true) {
13561357
SmallVector<StringRef, 2> Result;
1357-
if (const char *Str = DIE.getShortName())
1358+
if (const char *Str = DIE.getShortName()) {
13581359
Result.emplace_back(Str);
1359-
else if (DIE.getTag() == dwarf::DW_TAG_namespace)
1360+
if (IncludeStrippedTemplateNames) {
1361+
if (std::optional<StringRef> StrippedName =
1362+
StripTemplateParameters(Result.back()))
1363+
Result.push_back(*StrippedName);
1364+
}
1365+
} else if (DIE.getTag() == dwarf::DW_TAG_namespace)
13601366
Result.emplace_back("(anonymous namespace)");
13611367

13621368
if (IncludeLinkageName) {
@@ -1423,7 +1429,12 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
14231429
++NumErrors;
14241430
}
14251431

1426-
auto EntryNames = getNames(DIE);
1432+
// We allow an extra name for functions: their name without any template
1433+
// parameters.
1434+
auto IncludeStrippedTemplateNames =
1435+
DIE.getTag() == DW_TAG_subprogram ||
1436+
DIE.getTag() == DW_TAG_inlined_subroutine;
1437+
auto EntryNames = getNames(DIE, IncludeStrippedTemplateNames);
14271438
if (!is_contained(EntryNames, Str)) {
14281439
error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched Name "
14291440
"of DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
@@ -1496,7 +1507,11 @@ unsigned DWARFVerifier::verifyNameIndexCompleteness(
14961507
// the linkage name."
14971508
auto IncludeLinkageName = Die.getTag() == DW_TAG_subprogram ||
14981509
Die.getTag() == DW_TAG_inlined_subroutine;
1499-
auto EntryNames = getNames(Die, IncludeLinkageName);
1510+
// We *allow* stripped template names as an extra entry into the template,
1511+
// but we don't *require* them to pass the completeness test.
1512+
auto IncludeStrippedTemplateNames = false;
1513+
auto EntryNames =
1514+
getNames(Die, IncludeStrippedTemplateNames, IncludeLinkageName);
15001515
if (EntryNames.empty())
15011516
return 0;
15021517

llvm/test/tools/dsymutil/X86/dwarf5-accel.test

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@
1313
## $ clang -gdwarf-5 dwarf5-accel.cpp -c -o dwarf5-accel.o
1414

1515
#RUN: dsymutil -accelerator=Dwarf -oso-prepend-path %p/Inputs -y %s -o %t.dSYM
16-
#COM: Uncomment next line when dwarfdump will handle stripped template names.
17-
#COM: llvm-dwarfdump --verify %t.dSYM | FileCheck %s --check-prefix VERIFY
16+
#RUN: llvm-dwarfdump --verify %t.dSYM | FileCheck %s --check-prefix VERIFY
1817
#RUN: llvm-dwarfdump -a --verbose %t.dSYM | FileCheck %s
1918

20-
#COM: Uncomment next line when dwarfdump will handle stripped template names.
21-
#COM: #VERIFY: No errors.
19+
#VERIFY: No errors.
2220

2321
#CHECK: .debug_names
2422
#CHECK: "foo"

0 commit comments

Comments
 (0)