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 <apra...@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) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits