[Lldb-commits] [lldb] [lldb] DWARFDIE: Follow DW_AT_specification when computing CompilerCo… (PR #77157)
Adrian Prantl via lldb-commits
lldb-commits at lists.llvm.org
Mon Jan 8 15:00:46 PST 2024
https://github.com/adrian-prantl updated https://github.com/llvm/llvm-project/pull/77157
>From 5f34a103d0b06220bb93b55525865e23694854b4 Mon Sep 17 00:00:00 2001
From: Adrian Prantl <aprantl at apple.com>
Date: Fri, 5 Jan 2024 15:11:24 -0800
Subject: [PATCH] [lldb] DWARFDIE: Follow DW_AT_specification when computing
CompilerContext
Following the specification chain seems to be clearly the expected
behavior of GetDeclContext(). Otherwise C++ methods have an empty
CompilerContext instead of being nested in their struct/class.
Theprimary motivation for this functionality is the Swift plugin. In
order to test the change I added a proof-of-concept implementation of
a Module::FindFunction() variant that takes a CompilerContext, expesed
via lldb-test.
rdar://120553412
---
lldb/include/lldb/Core/Module.h | 6 +++
lldb/source/Core/Module.cpp | 17 +++++++
.../Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 44 ++++++++++++-------
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 11 ++---
.../DWARF/x86/find-basic-function.cpp | 6 +++
lldb/tools/lldb-test/lldb-test.cpp | 4 ++
6 files changed, 67 insertions(+), 21 deletions(-)
diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index f4973cdda1efcc..0188057247a68b 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -337,6 +337,12 @@ class Module : public std::enable_shared_from_this<Module>,
const ModuleFunctionSearchOptions &options,
SymbolContextList &sc_list);
+ /// Find functions by compiler context.
+ void FindFunctions(llvm::ArrayRef<CompilerContext> compiler_ctx,
+ lldb::FunctionNameType name_type_mask,
+ const ModuleFunctionSearchOptions &options,
+ SymbolContextList &sc_list);
+
/// Find functions by name.
///
/// If the function is an inlined function, it will have a block,
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index c0574b724ace7b..331cf324664114 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -855,6 +855,23 @@ void Module::FindFunctions(ConstString name,
}
}
+void Module::FindFunctions(llvm::ArrayRef<CompilerContext> compiler_ctx,
+ FunctionNameType name_type_mask,
+ const ModuleFunctionSearchOptions &options,
+ SymbolContextList &sc_list) {
+ if (compiler_ctx.empty() ||
+ compiler_ctx.back().kind != CompilerContextKind::Function)
+ return;
+ ConstString name = compiler_ctx.back().name;
+ SymbolContextList unfiltered;
+ FindFunctions(name, CompilerDeclContext(), name_type_mask, options,
+ unfiltered);
+ // Filter by context.
+ for (auto &sc : unfiltered)
+ if (sc.function && compiler_ctx.equals(sc.function->GetCompilerContext()))
+ sc_list.Append(sc);
+}
+
void Module::FindFunctions(const RegularExpression ®ex,
const ModuleFunctionSearchOptions &options,
SymbolContextList &sc_list) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index bed68f45426f67..d4446befd83b05 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -373,44 +373,51 @@ std::vector<DWARFDIE> DWARFDIE::GetDeclContextDIEs() const {
return result;
}
-std::vector<lldb_private::CompilerContext> DWARFDIE::GetDeclContext() const {
+static std::vector<lldb_private::CompilerContext>
+GetDeclContextImpl(llvm::SmallSet<lldb::user_id_t, 4> &seen, DWARFDIE die) {
std::vector<lldb_private::CompilerContext> context;
- const dw_tag_t tag = Tag();
- if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
+ // Stop if we hit a cycle.
+ if (!die || !seen.insert(die.GetID()).second)
return context;
- DWARFDIE parent = GetParent();
- if (parent)
- context = parent.GetDeclContext();
+
+ // Handle outline member function DIEs by following the specification.
+ if (DWARFDIE spec = die.GetReferencedDIE(DW_AT_specification))
+ return GetDeclContextImpl(seen, spec);
+
+ // Get the parent context chain.
+ context = GetDeclContextImpl(seen, die.GetParent());
+
+ // Add this DIE's contribution at the end of the chain.
auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) {
context.push_back({kind, ConstString(name)});
};
- switch (tag) {
+ switch (die.Tag()) {
case DW_TAG_module:
- push_ctx(CompilerContextKind::Module, GetName());
+ push_ctx(CompilerContextKind::Module, die.GetName());
break;
case DW_TAG_namespace:
- push_ctx(CompilerContextKind::Namespace, GetName());
+ push_ctx(CompilerContextKind::Namespace, die.GetName());
break;
case DW_TAG_structure_type:
- push_ctx(CompilerContextKind::Struct, GetName());
+ push_ctx(CompilerContextKind::Struct, die.GetName());
break;
case DW_TAG_union_type:
- push_ctx(CompilerContextKind::Union, GetName());
+ push_ctx(CompilerContextKind::Union, die.GetName());
break;
case DW_TAG_class_type:
- push_ctx(CompilerContextKind::Class, GetName());
+ push_ctx(CompilerContextKind::Class, die.GetName());
break;
case DW_TAG_enumeration_type:
- push_ctx(CompilerContextKind::Enum, GetName());
+ push_ctx(CompilerContextKind::Enum, die.GetName());
break;
case DW_TAG_subprogram:
- push_ctx(CompilerContextKind::Function, GetPubname());
+ push_ctx(CompilerContextKind::Function, die.GetName());
break;
case DW_TAG_variable:
- push_ctx(CompilerContextKind::Variable, GetPubname());
+ push_ctx(CompilerContextKind::Variable, die.GetPubname());
break;
case DW_TAG_typedef:
- push_ctx(CompilerContextKind::Typedef, GetName());
+ push_ctx(CompilerContextKind::Typedef, die.GetName());
break;
default:
break;
@@ -418,6 +425,11 @@ std::vector<lldb_private::CompilerContext> DWARFDIE::GetDeclContext() const {
return context;
}
+std::vector<lldb_private::CompilerContext> DWARFDIE::GetDeclContext() const {
+ llvm::SmallSet<lldb::user_id_t, 4> seen;
+ return GetDeclContextImpl(seen, *this);
+}
+
std::vector<lldb_private::CompilerContext>
DWARFDIE::GetTypeLookupContext() const {
std::vector<lldb_private::CompilerContext> context;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 447930ffe07b3f..f539ed5d2ae570 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2574,11 +2574,12 @@ void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info,
Module::LookupInfo no_tp_lookup_info(lookup_info);
no_tp_lookup_info.SetLookupName(ConstString(name_no_template_params));
- m_index->GetFunctions(no_tp_lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) {
- if (resolved_dies.insert(die.GetDIE()).second)
- ResolveFunction(die, include_inlines, sc_list);
- return true;
- });
+ m_index->GetFunctions(no_tp_lookup_info, *this, parent_decl_ctx,
+ [&](DWARFDIE die) {
+ if (resolved_dies.insert(die.GetDIE()).second)
+ ResolveFunction(die, include_inlines, sc_list);
+ return true;
+ });
}
}
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 204568a446d0a4..30143a41d5e734 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-function.cpp
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-function.cpp
@@ -34,6 +34,8 @@
// RUN: FileCheck --check-prefix=FULL-MANGLED-METHOD %s
// RUN: lldb-test symbols --name=foo --context=context --find=function --function-flags=base %t | \
// RUN: FileCheck --check-prefix=CONTEXT %s
+// RUN: lldb-test symbols --compiler-context=Struct:sbar,Function:foo -language=c++ -find=function -function-flags=method %t | \
+// RUN: FileCheck --check-prefix=COMPILER-CONTEXT %s
// RUN: lldb-test symbols --name=not_there --find=function %t | \
// RUN: FileCheck --check-prefix=EMPTY %s
@@ -84,6 +86,10 @@
// CONTEXT: Found 1 functions:
// CONTEXT-DAG: name = "bar::foo()", mangled = "_ZN3bar3fooEv", decl_context = {Namespace(bar)}
+// COMPILER-CONTEXT: Found 2 functions:
+// COMPILER-CONTEXT-DAG: name = "sbar::foo()", mangled = "_ZN4sbar3fooEv"
+// COMPILER-CONTEXT-DAG: name = "sbar::foo(int)", mangled = "_ZN4sbar3fooEi"
+
// EMPTY: Found 0 functions:
void foo() {}
diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp
index e326a84c1dbd2f..33281cfb150747 100644
--- a/lldb/tools/lldb-test/lldb-test.cpp
+++ b/lldb/tools/lldb-test/lldb-test.cpp
@@ -466,6 +466,7 @@ static lldb::DescriptionLevel GetDescriptionLevel() {
Error opts::symbols::findFunctions(lldb_private::Module &Module) {
SymbolFile &Symfile = *Module.GetSymbolFile();
SymbolContextList List;
+ auto compiler_context = parseCompilerContext();
if (!File.empty()) {
assert(Line != 0);
@@ -498,6 +499,9 @@ Error opts::symbols::findFunctions(lldb_private::Module &Module) {
assert(RE.IsValid());
List.Clear();
Symfile.FindFunctions(RE, true, List);
+ } else if (!compiler_context.empty()) {
+ List.Clear();
+ Module.FindFunctions(compiler_context, getFunctionNameFlags(), {}, List);
} else {
Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
if (!ContextOr)
More information about the lldb-commits
mailing list