Skip to content

[lldb] Extend FindTypes to optionally search by mangled type name #113007

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
Oct 31, 2024

Conversation

augusto2112
Copy link
Contributor

Swift types have mangled type names. This adds functionality to look up those types through the FindTypes API by searching for the mangled type name instead of the regular name.

@augusto2112
Copy link
Contributor Author

This depends on #113006

@llvmbot
Copy link
Member

llvmbot commented Oct 19, 2024

@llvm/pr-subscribers-lldb

Author: Augusto Noronha (augusto2112)

Changes

Swift types have mangled type names. This adds functionality to look up those types through the FindTypes API by searching for the mangled type name instead of the regular name.


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

7 Files Affected:

  • (modified) lldb/include/lldb/Symbol/Type.h (+8)
  • (modified) lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp (+10-4)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp (+28-7)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h (+3-2)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+1-1)
  • (modified) lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (+4-1)
  • (modified) lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp (+4-1)
diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h
index 03d9f927997476..b90cfc44e907b9 100644
--- a/lldb/include/lldb/Symbol/Type.h
+++ b/lldb/include/lldb/Symbol/Type.h
@@ -84,6 +84,8 @@ FLAGS_ENUM(TypeQueryOptions){
     /// matching type is found. When false, the type query should find all
     /// matching types.
     e_find_one = (1u << 4),
+    // If set, treat TypeQuery::m_name as a mangled name that should be searched.
+    e_search_by_mangled_name = (1u << 5),
 };
 LLDB_MARK_AS_BITMASK_ENUM(TypeQueryOptions)
 
@@ -300,6 +302,12 @@ class TypeQuery {
       m_options &= ~e_find_one;
   }
 
+  /// Returns true if the type query is supposed to treat the name to be searched
+  /// as a mangled name.
+  bool GetSearchByMangledName() const {
+    return (m_options & e_search_by_mangled_name) != 0;
+  }
+
   /// Access the internal compiler context array.
   ///
   /// Clients can use this to populate the context manually.
diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
index bb738c3dcc54a0..ee63c21663128a 100644
--- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
+++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
@@ -1032,10 +1032,16 @@ void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match,
 
   ConstString name = match.GetTypeBasename();
   for (TypeSP type_sp : GetTypeList().Types()) {
-    if (type_sp && type_sp->GetName() == name) {
-      results.InsertUnique(type_sp);
-      if (results.Done(match))
-        return;
+    if (type_sp) {
+      auto type_name =
+          match.GetSearchByMangledName()
+              ? type_sp->GetForwardCompilerType().GetMangledTypeName()
+              : type_sp->GetName();
+      if (type_name == name) {
+        results.InsertUnique(type_sp);
+        if (results.Done(match))
+          return;
+      }
     }
   }
 }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index d83740f8e2113b..d4604d72b3a3b6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -14,6 +14,7 @@
 #include "DWARFDeclContext.h"
 #include "DWARFUnit.h"
 #include "lldb/Symbol/Type.h"
+#include "lldb/lldb-private-enumerations.h"
 
 #include "llvm/ADT/iterator.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -368,7 +369,7 @@ lldb_private::Type *DWARFDIE::ResolveTypeUID(const DWARFDIE &die) const {
   return nullptr;
 }
 
-static void GetDeclContextImpl(DWARFDIE die,
+static void GetDeclContextImpl(DWARFDIE die, bool use_mangled_name,
                                llvm::SmallSet<lldb::user_id_t, 4> &seen,
                                std::vector<CompilerContext> &context) {
   // Stop if we hit a cycle.
@@ -383,6 +384,13 @@ static void GetDeclContextImpl(DWARFDIE die,
     auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) {
       context.push_back({kind, ConstString(name)});
     };
+
+    // Since mangled names are unique there's no need to build an entire context.
+    if (use_mangled_name) {
+      push_ctx(CompilerContextKind::AnyType, die.GetMangledName());
+      return;
+    }
+
     switch (die.Tag()) {
     case DW_TAG_module:
       push_ctx(CompilerContextKind::Module, die.GetName());
@@ -417,15 +425,15 @@ static void GetDeclContextImpl(DWARFDIE die,
   }
 }
 
-std::vector<CompilerContext> DWARFDIE::GetDeclContext() const {
+std::vector<CompilerContext> DWARFDIE::GetDeclContext(bool use_mangled_name) const {
   llvm::SmallSet<lldb::user_id_t, 4> seen;
   std::vector<CompilerContext> context;
-  GetDeclContextImpl(*this, seen, context);
+  GetDeclContextImpl(*this, use_mangled_name, seen, context);
   std::reverse(context.begin(), context.end());
   return context;
 }
 
-static void GetTypeLookupContextImpl(DWARFDIE die,
+static void GetTypeLookupContextImpl(DWARFDIE die, bool use_mangled_name,
                                      llvm::SmallSet<lldb::user_id_t, 4> &seen,
                                      std::vector<CompilerContext> &context) {
   // Stop if we hit a cycle.
@@ -434,6 +442,19 @@ static void GetTypeLookupContextImpl(DWARFDIE die,
     auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) {
       context.push_back({kind, ConstString(name)});
     };
+
+    // Since mangled names are unique there's no need to build an entire context.
+    if (use_mangled_name) {
+      push_ctx(CompilerContextKind::AnyType, die.GetMangledName());
+      return;
+    }
+
+    // If there is no name, then there is no need to look anything up for this
+    // DIE.
+       const char *name = die.GetName();
+    if (!name || !name[0])
+      return;
+
     switch (die.Tag()) {
     case DW_TAG_namespace:
       push_ctx(CompilerContextKind::Namespace, die.GetName());
@@ -453,7 +474,7 @@ static void GetTypeLookupContextImpl(DWARFDIE die,
       break;
     case DW_TAG_typedef:
       push_ctx(CompilerContextKind::Typedef, die.GetName());
-      break;
+   break;
     case DW_TAG_base_type:
       push_ctx(CompilerContextKind::Builtin, die.GetName());
       break;
@@ -477,10 +498,10 @@ static void GetTypeLookupContextImpl(DWARFDIE die,
   }
 }
 
-std::vector<CompilerContext> DWARFDIE::GetTypeLookupContext() const {
+std::vector<CompilerContext> DWARFDIE::GetTypeLookupContext(bool use_mangled_name) const {
   llvm::SmallSet<lldb::user_id_t, 4> seen;
   std::vector<CompilerContext> context;
-  GetTypeLookupContextImpl(*this, seen, context);
+  GetTypeLookupContextImpl(*this, use_mangled_name, seen, context);
   std::reverse(context.begin(), context.end());
   return context;
 }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index e1318953a384cd..109070bdcb6e95 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -72,7 +72,7 @@ class DWARFDIE : public DWARFBaseDIE {
   /// Return this DIE's decl context as it is needed to look up types
   /// in Clang modules. This context will include any modules or functions that
   /// the type is declared in so an exact module match can be efficiently made.
-  std::vector<CompilerContext> GetDeclContext() const;
+  std::vector<CompilerContext> GetDeclContext(bool use_mangled_name = false) const;
 
   /// Get a context to a type so it can be looked up.
   ///
@@ -84,7 +84,8 @@ class DWARFDIE : public DWARFBaseDIE {
   /// appropriate time, like either the translation unit or at a function
   /// context. This is designed to allow users to efficiently look for types
   /// using a full or partial CompilerContext array.
-  std::vector<CompilerContext> GetTypeLookupContext() const;
+  std::vector<CompilerContext>
+  GetTypeLookupContext(bool use_mangled_name = false) const;
 
   DWARFDeclContext GetDWARFDeclContext() const;
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 9287d4baf19e9c..f1956f006de84d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2762,7 +2762,7 @@ void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) {
     if (query.GetModuleSearch())
       die_context = die.GetDeclContext();
     else
-      die_context = die.GetTypeLookupContext();
+      die_context = die.GetTypeLookupContext(query.GetSearchByMangledName());
     assert(!die_context.empty());
     if (!query.ContextMatches(die_context))
       return true; // Keep iterating over index types, context mismatch.
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 7fded6a31a3af5..b55518a136c997 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1735,7 +1735,10 @@ void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query,
       continue;
 
     // We resolved a type. Get the fully qualified name to ensure it matches.
-    ConstString name = type_sp->GetQualifiedName();
+    ConstString name =
+        query.GetSearchByMangledName()
+            ? type_sp->GetForwardCompilerType().GetMangledTypeName()
+            : type_sp->GetQualifiedName();
     TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match);
     if (query.ContextMatches(type_match.GetContextRef())) {
       results.InsertUnique(type_sp);
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index 584c2115459c66..0179c52df9e563 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -1562,7 +1562,10 @@ void SymbolFilePDB::FindTypes(const lldb_private::TypeQuery &query,
     if (iter == m_types.end())
       continue;
     // We resolved a type. Get the fully qualified name to ensure it matches.
-    ConstString name = iter->second->GetQualifiedName();
+    ConstString name =
+        query.GetSearchByMangledName()
+            ? iter->second->GetForwardCompilerType().GetMangledTypeName()
+            : iter->second->GetQualifiedName();
     TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match);
     if (query.ContextMatches(type_match.GetContextRef())) {
       type_results.InsertUnique(iter->second);

Copy link

github-actions bot commented Oct 19, 2024

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

@Michael137 Michael137 requested a review from labath October 19, 2024 09:32
@augusto2112 augusto2112 force-pushed the find-types-mangled-name branch from eb1f2bb to 7881a25 Compare October 22, 2024 21:24
@augusto2112 augusto2112 force-pushed the find-types-mangled-name branch from 7881a25 to eab35bd Compare October 22, 2024 21:34
Copy link
Collaborator

@clayborg clayborg left a comment

Choose a reason for hiding this comment

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

Typenames don't often get put into the acclerator tables as mangled names for C/C++/ObjC. Functions do, but not typenames. Is there a case where the debug info contains a mangled name for a type?

I know swift does use mangled names for types though as that is how these types are extracted from the Swift AST data blob by the Swift compiler.

So I see no problem with this patch. If this is for Swift then we need to make sure there is a test for this in the Swift.org LLDB. Not sure if we can write a test using C/C++/ObjC or and language that comes from Clang ASTs.

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

Yea not entirely sure how to test this either. As Greg points out, type mangling isn't really a thing LLDB cared about for C++. Maybe if we had this option exposed somehow (e.g., through lldb-test) we could come up with a DWARF yaml that has a type with a linkage name in the accelerator tables? Then we could test it that way. But if that's too much hassle and we have a test on the Apple fork that exercises this API maybe we're ok

@Michael137
Copy link
Member

Yea using the new TypeQuery option in lldb-test seems doable. Whether obj2yaml/yaml2obj supports .debug_names, i'm not sure, haven't tried

@augusto2112 augusto2112 requested a review from clayborg October 29, 2024 22:43
@augusto2112
Copy link
Contributor Author

@Michael137 I wasn't able to run yaml2obj to convert back an object file that contains debug info, I'm not sure if the issue is that yaml2obj doesn't support something that's encoded in the debug info, or some bug with MachO.

This is the error:

error: wrote too much data somewhere, section offsets in section __debug_str_offs__DWARF for segment __DWARF don't line up: [cursor=0x41d1e0], [fileStart=0x41ccdc], [sectionOffset=0x4f2]

// Since mangled names are unique, we only need to check if the names are
// the same.
if (query.GetSearchByMangledName()) {
if (die.GetMangledName(/*substitute_name_allowed=*/false) !=
Copy link
Member

@Michael137 Michael137 Oct 30, 2024

Choose a reason for hiding this comment

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

Even with substitutions allowed, that would only cause problems if the DW_AT_name somehow contained the mangled name, right? Even then, that might not actually be a problem. For the purposes of this check, if a DIE didn't have a linkage name this comparison would have evaluated to false anyway, unless I'm missing something.

But I guess being more explicit about really only checking the linkage name seems fine/easier to reason about

@Michael137
Copy link
Member

@Michael137 I wasn't able to run yaml2obj to convert back an object file that contains debug info, I'm not sure if the issue is that yaml2obj doesn't support something that's encoded in the debug info, or some bug with MachO.

This is the error:

error: wrote too much data somewhere, section offsets in section __debug_str_offs__DWARF for segment __DWARF don't line up: [cursor=0x41d1e0], [fileStart=0x41ccdc], [sectionOffset=0x4f2]

Hmm yea I wouldn't be surprised if yaml2obj doesn't properly handle this. Could give it a shot using ELF (I think that has better support). But if that doesn't work either I wouldn't bother

Copy link
Collaborator

@adrian-prantl adrian-prantl left a comment

Choose a reason for hiding this comment

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

Can you add a test (perhaps using lldb-test and a .ll or .s file)?

Swift types have mangled type names. This adds functionality to look
up those types through the FindTypes API by searching for the mangled
type name instead of the regular name.
@augusto2112 augusto2112 force-pushed the find-types-mangled-name branch from 56b76ab to 7fc51bb Compare October 30, 2024 18:11
@augusto2112
Copy link
Contributor Author

Ok, I was able to add a test

ret i32 0, !dbg !26
}

attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fp-armv8,+neon,+v8a,-fmv" }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you try to remove most of the attributes?

@augusto2112 augusto2112 force-pushed the find-types-mangled-name branch from 578d2c8 to 7c66383 Compare October 31, 2024 00:45
@augusto2112 augusto2112 merged commit d6b9028 into llvm:main Oct 31, 2024
7 checks passed
smallp-o-p pushed a commit to smallp-o-p/llvm-project that referenced this pull request Nov 3, 2024
…vm#113007)

Swift types have mangled type names. This adds functionality to look up
those types through the FindTypes API by searching for the mangled type
name instead of the regular name.
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
…vm#113007)

Swift types have mangled type names. This adds functionality to look up
those types through the FindTypes API by searching for the mangled type
name instead of the regular name.
augusto2112 added a commit to augusto2112/llvm-project that referenced this pull request Nov 9, 2024
…vm#113007)

Swift types have mangled type names. This adds functionality to look up
those types through the FindTypes API by searching for the mangled type
name instead of the regular name.
augusto2112 added a commit to augusto2112/llvm-project that referenced this pull request Nov 9, 2024
…vm#113007)

Swift types have mangled type names. This adds functionality to look up
those types through the FindTypes API by searching for the mangled type
name instead of the regular name.
augusto2112 added a commit to augusto2112/llvm-project that referenced this pull request Nov 14, 2024
…vm#113007)

Swift types have mangled type names. This adds functionality to look up
those types through the FindTypes API by searching for the mangled type
name instead of the regular name.

(cherry picked from commit d6b9028)
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.

5 participants