[Lldb-commits] [lldb] Expose DWARFDIE::GetDeclContext() in lldb_private::Function. (PR #69981)

Adrian Prantl via lldb-commits lldb-commits at lists.llvm.org
Mon Oct 23 16:05:58 PDT 2023


https://github.com/adrian-prantl created https://github.com/llvm/llvm-project/pull/69981

I need this API in the Swift plugin, but it seems generally useful enough to expose it in the main branch.

>From 6b41e8ccaf7c3daf787cb7f7399ba815c5fe5b77 Mon Sep 17 00:00:00 2001
From: Adrian Prantl <aprantl at apple.com>
Date: Mon, 23 Oct 2023 15:55:40 -0700
Subject: [PATCH] Expose DWARFDIE::GetDeclContext() in lldb_private::Function.

I need this API in the Swift plugin, but it seems generally useful
enough to expose it in the main branch.
---
 lldb/include/lldb/Symbol/Function.h           |  6 ++++
 lldb/include/lldb/Symbol/SymbolFile.h         | 12 ++++---
 lldb/include/lldb/Symbol/Type.h               |  2 +-
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  |  9 +++---
 .../Plugins/SymbolFile/DWARF/DWARFDIE.cpp     | 32 ++++++++++---------
 .../Plugins/SymbolFile/DWARF/DWARFDIE.h       |  2 +-
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      | 14 ++++++--
 .../SymbolFile/DWARF/SymbolFileDWARF.h        |  3 ++
 .../DWARF/SymbolFileDWARFDebugMap.cpp         | 13 ++++++--
 .../DWARF/SymbolFileDWARFDebugMap.h           |  2 ++
 lldb/source/Symbol/Function.cpp               | 23 ++++++++++++-
 lldb/source/Symbol/Type.cpp                   | 32 ++++++++++---------
 .../DWARF/x86/find-basic-function.cpp         |  2 +-
 .../SymbolFile/DWARF/x86/module-ownership.mm  |  2 +-
 lldb/tools/lldb-test/lldb-test.cpp            | 12 ++++---
 15 files changed, 113 insertions(+), 53 deletions(-)

diff --git a/lldb/include/lldb/Symbol/Function.h b/lldb/include/lldb/Symbol/Function.h
index 28afdbff1eb233e..de69fd949d24748 100644
--- a/lldb/include/lldb/Symbol/Function.h
+++ b/lldb/include/lldb/Symbol/Function.h
@@ -533,6 +533,12 @@ class Function : public UserID, public SymbolContextScope {
   ///     The DeclContext, or NULL if none exists.
   CompilerDeclContext GetDeclContext();
 
+  /// Get the CompilerContext for this function, if available.
+  ///
+  /// \return
+  ///     The CompilerContext, or NULL if none exists.
+  std::vector<CompilerContext> GetCompilerContext();
+
   /// Get accessor for the type that describes the function return value type,
   /// and parameter types.
   ///
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h
index 512dd9acb86db61..b40d0f03b6e0130 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -225,14 +225,16 @@ class SymbolFile : public PluginInterface {
 
   virtual bool CompleteType(CompilerType &compiler_type) = 0;
   virtual void ParseDeclsForContext(CompilerDeclContext decl_ctx) {}
-  virtual CompilerDecl GetDeclForUID(lldb::user_id_t uid) {
-    return CompilerDecl();
-  }
+  virtual CompilerDecl GetDeclForUID(lldb::user_id_t uid) { return {}; }
   virtual CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) {
-    return CompilerDeclContext();
+    return {};
   }
   virtual CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) {
-    return CompilerDeclContext();
+    return {};
+  }
+  virtual std::vector<CompilerContext>
+  GetCompilerContextForUID(lldb::user_id_t uid) {
+    return {};
   }
   virtual uint32_t ResolveSymbolContext(const Address &so_addr,
                                         lldb::SymbolContextItem resolve_scope,
diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h
index c505262cd9eaecf..3d9ed2183d81ecd 100644
--- a/lldb/include/lldb/Symbol/Type.h
+++ b/lldb/include/lldb/Symbol/Type.h
@@ -34,7 +34,7 @@ struct CompilerContext {
   }
   bool operator!=(const CompilerContext &rhs) const { return !(*this == rhs); }
 
-  void Dump() const;
+  void Dump(Stream *s) const;
 
   CompilerContextKind kind;
   ConstString name;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 545a5dcc7d0fd09..43d61a9f66c0ba2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -142,8 +142,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
   // If this type comes from a Clang module, recursively look in the
   // DWARF section of the .pcm file in the module cache. Clang
   // generates DWO skeleton units as breadcrumbs to find them.
-  llvm::SmallVector<CompilerContext, 4> decl_context;
-  die.GetDeclContext(decl_context);
+  std::vector<CompilerContext> decl_context = die.GetDeclContext();
   TypeMap pcm_types;
 
   // The type in the Clang module must have the same language as the current CU.
@@ -2286,7 +2285,7 @@ CompilerDecl DWARFASTParserClang::GetDeclForUIDFromDWARF(const DWARFDIE &die) {
   clang::Decl *clang_decl = GetClangDeclForDIE(die);
   if (clang_decl != nullptr)
     return m_ast.GetCompilerDecl(clang_decl);
-  return CompilerDecl();
+  return {};
 }
 
 CompilerDeclContext
@@ -2294,7 +2293,7 @@ DWARFASTParserClang::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) {
   clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE(die);
   if (clang_decl_ctx)
     return m_ast.CreateDeclContext(clang_decl_ctx);
-  return CompilerDeclContext();
+  return {};
 }
 
 CompilerDeclContext
@@ -2303,7 +2302,7 @@ DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) {
       GetClangDeclContextContainingDIE(die, nullptr);
   if (clang_decl_ctx)
     return m_ast.CreateDeclContext(clang_decl_ctx);
-  return CompilerDeclContext();
+  return {};
 }
 
 size_t DWARFASTParserClang::ParseChildEnumerators(
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index d43c2ac276fb819..b5bfa31a40a8ff2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -373,47 +373,49 @@ std::vector<DWARFDIE> DWARFDIE::GetDeclContextDIEs() const {
   return result;
 }
 
-void DWARFDIE::GetDeclContext(
-    llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const {
+std::vector<lldb_private::CompilerContext> DWARFDIE::GetDeclContext() const {
+  std::vector<lldb_private::CompilerContext> context;
   const dw_tag_t tag = Tag();
   if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
-    return;
+    return context;
   DWARFDIE parent = GetParent();
   if (parent)
-    parent.GetDeclContext(context);
+    context = parent.GetDeclContext();
+  auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) {
+    context.push_back({kind, ConstString(name)});
+  };
   switch (tag) {
   case DW_TAG_module:
-    context.push_back({CompilerContextKind::Module, ConstString(GetName())});
+    push_ctx(CompilerContextKind::Module, GetName());
     break;
   case DW_TAG_namespace:
-    context.push_back({CompilerContextKind::Namespace, ConstString(GetName())});
+    push_ctx(CompilerContextKind::Namespace, GetName());
     break;
   case DW_TAG_structure_type:
-    context.push_back({CompilerContextKind::Struct, ConstString(GetName())});
+    push_ctx(CompilerContextKind::Struct, GetName());
     break;
   case DW_TAG_union_type:
-    context.push_back({CompilerContextKind::Union, ConstString(GetName())});
+    push_ctx(CompilerContextKind::Union, GetName());
     break;
   case DW_TAG_class_type:
-    context.push_back({CompilerContextKind::Class, ConstString(GetName())});
+    push_ctx(CompilerContextKind::Class, GetName());
     break;
   case DW_TAG_enumeration_type:
-    context.push_back({CompilerContextKind::Enum, ConstString(GetName())});
+    push_ctx(CompilerContextKind::Enum, GetName());
     break;
   case DW_TAG_subprogram:
-    context.push_back(
-        {CompilerContextKind::Function, ConstString(GetPubname())});
+    push_ctx(CompilerContextKind::Function, GetPubname());
     break;
   case DW_TAG_variable:
-    context.push_back(
-        {CompilerContextKind::Variable, ConstString(GetPubname())});
+push_ctx(CompilerContextKind::Variable, GetPubname());
     break;
   case DW_TAG_typedef:
-    context.push_back({CompilerContextKind::Typedef, ConstString(GetName())});
+    push_ctx(CompilerContextKind::Typedef, GetName());
     break;
   default:
     break;
   }
+  return context;
 }
 
 DWARFDIE
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index 25b313bf0995742..a68af62c8b3e20c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -74,7 +74,7 @@ class DWARFDIE : public DWARFBaseDIE {
 
   /// Return this DIE's decl context as it is needed to look up types
   /// in Clang's -gmodules debug info format.
-  void GetDeclContext(llvm::SmallVectorImpl<CompilerContext> &context) const;
+  std::vector<CompilerContext> GetDeclContext() const;
 
   // Getting attribute values from the DIE.
   //
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 737c65d0712e0db..f306093819d41d1 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1454,6 +1454,17 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
   return CompilerDeclContext();
 }
 
+std::vector<CompilerContext>
+SymbolFileDWARF::GetCompilerContextForUID(lldb::user_id_t type_uid) {
+  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+  // Anytime we have a lldb::user_id_t, we must get the DIE by calling
+  // SymbolFileDWARF::GetDIE(). See comments inside the
+  // SymbolFileDWARF::GetDIE() for details.
+  if (DWARFDIE die = GetDIE(type_uid))
+    return die.GetDeclContext();
+  return {};
+}
+
 Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
   // Anytime we have a lldb::user_id_t, we must get the DIE by calling
@@ -2709,8 +2720,7 @@ void SymbolFileDWARF::FindTypes(
     if (!languages[GetLanguageFamily(*die.GetCU())])
       return true;
 
-    llvm::SmallVector<CompilerContext, 4> die_context;
-    die.GetDeclContext(die_context);
+    std::vector<CompilerContext> die_context = die.GetDeclContext();
     if (!contextMatches(die_context, pattern))
       return true;
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 646d5d9a471c41c..0689ffe0d65dcf6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -153,6 +153,9 @@ class SymbolFileDWARF : public SymbolFileCommon {
 
   CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override;
 
+  std::vector<CompilerContext>
+  GetCompilerContextForUID(lldb::user_id_t uid) override;
+
   void ParseDeclsForContext(CompilerDeclContext decl_ctx) override;
 
   uint32_t ResolveSymbolContext(const Address &so_addr,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index f789cbac9a717f1..567c06b4a475d25 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -1382,7 +1382,7 @@ SymbolFileDWARFDebugMap::GetDeclContextForUID(lldb::user_id_t type_uid) {
   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
   if (oso_dwarf)
     return oso_dwarf->GetDeclContextForUID(type_uid);
-  return CompilerDeclContext();
+  return {};
 }
 
 CompilerDeclContext
@@ -1391,7 +1391,16 @@ SymbolFileDWARFDebugMap::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
   if (oso_dwarf)
     return oso_dwarf->GetDeclContextContainingUID(type_uid);
-  return CompilerDeclContext();
+  return {};
+}
+
+std::vector<CompilerContext>
+SymbolFileDWARFDebugMap::GetCompilerContextForUID(lldb::user_id_t type_uid) {
+  const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
+  SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
+  if (oso_dwarf)
+    return oso_dwarf->GetCompilerContextForUID(type_uid);
+  return {};
 }
 
 void SymbolFileDWARFDebugMap::ParseDeclsForContext(
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 52fa1dca3da5f23..a337a76b7a69a66 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -93,6 +93,8 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon {
 
   CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) override;
   CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override;
+  std::vector<CompilerContext>
+  GetCompilerContextForUID(lldb::user_id_t uid) override;
   void ParseDeclsForContext(CompilerDeclContext decl_ctx) override;
 
   bool CompleteType(CompilerType &compiler_type) override;
diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp
index c651e4573854108..b89d36eaa7fd110 100644
--- a/lldb/source/Symbol/Function.cpp
+++ b/lldb/source/Symbol/Function.cpp
@@ -396,6 +396,17 @@ void Function::GetDescription(Stream *s, lldb::DescriptionLevel level,
     s->AsRawOstream() << ", name = \"" << name << '"';
   if (mangled)
     s->AsRawOstream() << ", mangled = \"" << mangled << '"';
+  if (level == eDescriptionLevelVerbose) {
+    *s << ", decl_context = {";
+    auto decl_context = GetCompilerContext();
+    // Drop the function itself from the context chain.
+    if (decl_context.size())
+      decl_context.pop_back();
+    llvm::interleave(
+        decl_context.begin(), decl_context.end(),
+        [&](CompilerContext &ctx) { ctx.Dump(s); }, [&]() { *s << ", "; });
+    *s << "}";
+  }
   *s << ", range = ";
   Address::DumpStyle fallback_style;
   if (level == eDescriptionLevelVerbose)
@@ -519,7 +530,17 @@ CompilerDeclContext Function::GetDeclContext() {
     if (SymbolFile *sym_file = module_sp->GetSymbolFile())
       return sym_file->GetDeclContextForUID(GetID());
   }
-  return CompilerDeclContext();
+  return {};
+}
+
+std::vector<CompilerContext> Function::GetCompilerContext() {
+  ModuleSP module_sp = CalculateSymbolContextModule();
+
+  if (module_sp) {
+    if (SymbolFile *sym_file = module_sp->GetSymbolFile())
+      return sym_file->GetCompilerContextForUID(GetID());
+  }
+  return {};
 }
 
 Type *Function::GetType() {
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index 548300d5709533c..66b2369c504a15a 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -64,49 +64,51 @@ bool lldb_private::contextMatches(llvm::ArrayRef<CompilerContext> context_chain,
   return true;
 }
 
-void CompilerContext::Dump() const {
+void CompilerContext::Dump(Stream *s) const {
+  if (!s)
+    return;
   switch (kind) {
   default:
-    printf("Invalid");
+    *s << "Invalid";
     break;
   case CompilerContextKind::TranslationUnit:
-    printf("TranslationUnit");
+    *s << "TranslationUnit";
     break;
   case CompilerContextKind::Module:
-    printf("Module");
+    *s << "Module";
     break;
   case CompilerContextKind::Namespace:
-    printf("Namespace");
+    *s << "Namespace";
     break;
   case CompilerContextKind::Class:
-    printf("Class");
+    *s << "Class";
     break;
   case CompilerContextKind::Struct:
-    printf("Structure");
+    *s << "Structure";
     break;
   case CompilerContextKind::Union:
-    printf("Union");
+    *s << "Union";
     break;
   case CompilerContextKind::Function:
-    printf("Function");
+    *s << "Function";
     break;
   case CompilerContextKind::Variable:
-    printf("Variable");
+    *s << "Variable";
     break;
   case CompilerContextKind::Enum:
-    printf("Enumeration");
+    *s << "Enumeration";
     break;
   case CompilerContextKind::Typedef:
-    printf("Typedef");
+    *s << "Typedef";
     break;
   case CompilerContextKind::AnyModule:
-    printf("AnyModule");
+    *s << "AnyModule";
     break;
   case CompilerContextKind::AnyType:
-    printf("AnyType");
+    *s << "AnyType";
     break;
   }
-  printf("(\"%s\")\n", name.GetCString());
+  *s << "(" << name << ")";
 }
 
 class TypeAppendVisitor {
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-function.cpp b/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-function.cpp
index c4fdee113eab9a4..204568a446d0a49 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-function.cpp
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-function.cpp
@@ -82,7 +82,7 @@
 // FULL-MANGLED-METHOD-DAG: name = "sbar::foo(int)", mangled = "_ZN4sbar3fooEi"
 
 // CONTEXT: Found 1 functions:
-// CONTEXT-DAG: name = "bar::foo()", mangled = "_ZN3bar3fooEv"
+// CONTEXT-DAG: name = "bar::foo()", mangled = "_ZN3bar3fooEv", decl_context = {Namespace(bar)}
 
 // EMPTY: Found 0 functions:
 
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/module-ownership.mm b/lldb/test/Shell/SymbolFile/DWARF/x86/module-ownership.mm
index a8dd6cf1d901aa9..4f39e2e5a9e170e 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/module-ownership.mm
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/module-ownership.mm
@@ -26,7 +26,7 @@
 // CHECK-ANON-S1: CXXRecordDecl {{.*}} imported in A struct
 
 StructB s3;
-// CHECK-ANON-S2: CXXRecordDecl {{.*}} imported in A.B {{.*}} struct
+// CHECK-ANON-S2: CXXRecordDecl {{.*}} imported in A.B {{.*}}struct
 // CHECK-ANON-S2: -FieldDecl {{.*}} in A.B anon_field_b 'int'
 
 Nested s4;
diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp
index d9c30b4f2ed8135..fa758bae5023348 100644
--- a/lldb/tools/lldb-test/lldb-test.cpp
+++ b/lldb/tools/lldb-test/lldb-test.cpp
@@ -322,10 +322,12 @@ std::vector<CompilerContext> parseCompilerContext() {
     }
     result.push_back({kind, ConstString{value}});
   }
-  outs() << "Search context: {\n";
-  for (auto entry: result)
-    entry.Dump();
-  outs() << "}\n";
+  outs() << "Search context: {";
+  lldb_private::StreamString s;
+  llvm::interleave(
+      result.begin(), result.end(), [&](CompilerContext &ctx) { ctx.Dump(&s); },
+      [&]() { s << ", "; });
+  outs() << s.GetString().str() << "}\n";
 
   return result;
 }
@@ -816,6 +818,8 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
           "Specify search type (-find) to use search options.");
     return dumpModule;
 
+
+    
   case FindType::Function:
     if (!File.empty() + (Line != 0) == 1)
       return make_string_error("Both file name and line number must be "



More information about the lldb-commits mailing list