Skip to content

[LLDB][NativePDB] Use undecorated name for types if UniqueName isn't mangled #152114

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 2 commits into from
Aug 6, 2025

Conversation

Nerixyz
Copy link
Contributor

@Nerixyz Nerixyz commented Aug 5, 2025

Languages other than C/C++ don't necessarily emit mangled names in the UniqueName field of type records. Rust specifically emits a unique ID that doesn't contain the name.

For example, (i32, i32) is emitted as

!266 = !DICompositeType(
  tag: DW_TAG_structure_type, name: "tuple$<i32,i32>", file: !9, size: 64, align: 32,
  elements: !267, templateParams: !17, identifier: "19122721b0632fe96c0dd37477674472"
)

which results in

  0x1091 | LF_STRUCTURE [size = 72, hash = 0x1AC67] `tuple$<i32,i32>`
           unique name: `19122721b0632fe96c0dd37477674472`
           vtable: <no type>, base list: <no type>, field list: 0x1090
           options: has unique name, sizeof 8

In C++ with Clang and MSVC, a structure similar to this would result in

   0x136F | LF_STRUCTURE [size = 44, hash = 0x30BE2] `MyTuple`
            unique name: `.?AUMyTuple@@`
            vtable: <no type>, base list: <no type>, field list: 0x136E
            options: has unique name, sizeof 8

With this PR, if a UniqueName is encountered that couldn't be parsed, it will fall back to using the undecorated (→ do the same as if the unique name is empty/unavailable).

I'm not sure how to test this. Maybe compiling the LLVM IR that rustc emits?

Fixes #152051.

@Nerixyz Nerixyz requested a review from JDevlieghere as a code owner August 5, 2025 10:18
@llvmbot llvmbot added the lldb label Aug 5, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 5, 2025

@llvm/pr-subscribers-lldb

Author: nerix (Nerixyz)

Changes

Languages other than C/C++ don't necessarily emit mangled names in the UniqueName field of type records. Rust specifically emits a unique ID that doesn't contain the name.

For example, (i32, i32) is emitted as

!266 = !DICompositeType(
  tag: DW_TAG_structure_type, name: "tuple$&lt;i32,i32&gt;", file: !9, size: 64, align: 32,
  elements: !267, templateParams: !17, identifier: "19122721b0632fe96c0dd37477674472"
)

which results in

  0x1091 | LF_STRUCTURE [size = 72, hash = 0x1AC67] `tuple$&lt;i32,i32&gt;`
           unique name: `19122721b0632fe96c0dd37477674472`
           vtable: &lt;no type&gt;, base list: &lt;no type&gt;, field list: 0x1090
           options: has unique name, sizeof 8

In C++ with Clang and MSVC, a structure similar to this would result in

   0x136F | LF_STRUCTURE [size = 44, hash = 0x30BE2] `MyTuple`
            unique name: `.?AUMyTuple@@`
            vtable: &lt;no type&gt;, base list: &lt;no type&gt;, field list: 0x136E
            options: has unique name, sizeof 8

With this PR, if a UniqueName is encountered that couldn't be parsed, it will fall back to using the undecorated (→ do the same as if the unique name is empty/unavailable).

I'm not sure how to test this. Maybe compiling the LLVM IR that rustc emits?

Fixes #152051.


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

2 Files Affected:

  • (modified) lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp (+1-1)
  • (modified) lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (+3-7)
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 8137622842253..36950c00f9e7f 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -178,7 +178,7 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
   std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());
   llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
   if (demangler.Error)
-    return {m_clang.GetTranslationUnitDecl(), std::string(record.UniqueName)};
+    return CreateDeclInfoForUndecoratedName(record.Name);
 
   llvm::ms_demangle::IdentifierNode *idn =
       ttn->QualifiedName->getUnqualifiedIdentifier();
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 7af53e16ce9d5..24b80c13a10d8 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -618,18 +618,14 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
 }
 
 static std::string GetUnqualifiedTypeName(const TagRecord &record) {
-  if (!record.hasUniqueName()) {
-    MSVCUndecoratedNameParser parser(record.Name);
-    llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
-
-    return std::string(specs.back().GetBaseName());
-  }
+  if (!record.hasUniqueName())
+    return std::string(MSVCUndecoratedNameParser::DropScope(record.Name));
 
   llvm::ms_demangle::Demangler demangler;
   std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());
   llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
   if (demangler.Error)
-    return std::string(record.Name);
+    return std::string(MSVCUndecoratedNameParser::DropScope(record.Name));
 
   llvm::ms_demangle::IdentifierNode *idn =
       ttn->QualifiedName->getUnqualifiedIdentifier();

Copy link
Member

@Michael137 Michael137 left a comment

Choose a reason for hiding this comment

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

Seems reasonable to me. I'd let @ZequanWu or @Walnut356 take a look too

return std::string(specs.back().GetBaseName());
}
if (!record.hasUniqueName())
return std::string(MSVCUndecoratedNameParser::DropScope(record.Name));
Copy link
Member

Choose a reason for hiding this comment

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

Was this change required? Or a drive-by cleanup?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, this isn't required. This was basically the implementation of DropScope before. I changed it for clarity - to be identical with the other case.

@Michael137 Michael137 requested a review from ZequanWu August 5, 2025 10:30
@ZequanWu
Copy link
Contributor

ZequanWu commented Aug 5, 2025

Can you add a test for this if it's not hard to create one?

@Nerixyz
Copy link
Contributor Author

Nerixyz commented Aug 5, 2025

Can you add a test for this if it's not hard to create one?

Found a way to make the IR a bit smaller by compiling an rlib with a main().

@JDevlieghere JDevlieghere merged commit 2d4e5c4 into llvm:main Aug 6, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[LLDB] [Native PDB] Wrong name is used for Rust types
5 participants