Author: Michael Buch Date: 2023-02-10T17:22:02Z New Revision: b296ddd91cb8e7676b3c38ca7f6d7bdbd84eb4af
URL: https://github.com/llvm/llvm-project/commit/b296ddd91cb8e7676b3c38ca7f6d7bdbd84eb4af DIFF: https://github.com/llvm/llvm-project/commit/b296ddd91cb8e7676b3c38ca7f6d7bdbd84eb4af.diff LOG: [lldb][DWARFASTParserClang] Attach linkage name to ctors/dtors if missing **Summary** This patch addresses the case where we have a `DW_AT_external` subprogram for a constructor (and/or destructor) that doesn't carry a `DW_AT_linkage_name` attribute. The corresponding DIE(s) that represent the definition will have a linkage name, but if the name contains constructs that LLDBs fallback mechanism for guessing mangled names to resolve external symbols doesn't support (e.g., abi-tags) then we end up failing to resolve the function call. We address this by trying to find the linkage name before we create the constructor/destructor decl, which will get attached using an `AsmLabelAttr` to make symbol resolution easier. **Testing** * Added API test Differential Revision: https://reviews.llvm.org/D143652 Added: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp Modified: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp Removed: ################################################################################ diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 4429b4fcae2a..0aacfd1bb0cf 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -888,6 +888,45 @@ ConvertDWARFCallingConventionToClang(const ParsedDWARFTypeAttributes &attrs) { return clang::CC_C; } +/// Given a DIE with an external definition (and thus no linkage name) +/// find the definitions by lookup into the DWARF name index. +/// We check the DW_AT_specification for each DIE in the index with +/// the same name as the specified 'die' until we find one that references +/// 'die'. Then return that linkage name. If no such DIE is found in the index, +/// returns nullptr. +static char const *FindLinkageName(DWARFDIE die) { + auto *dwarf = die.GetDWARF(); + if (!dwarf) + return nullptr; + + ConstString func_name(die.GetName()); + if (!func_name) + return nullptr; + + SymbolContextList sc_list; + Module::LookupInfo lookup_info(func_name, + FunctionNameType::eFunctionNameTypeMethod | + FunctionNameType::eFunctionNameTypeFull, + LanguageType::eLanguageTypeUnknown); + dwarf->FindFunctions(lookup_info, {}, true, sc_list); + + for (auto const &sc : sc_list.SymbolContexts()) { + if (auto *func = sc.function) { + auto func_die = dwarf->GetDIE(func->GetID()); + if (!func_die.IsValid()) + continue; + + auto spec_die = + func_die.GetAttributeValueAsReferenceDIE(DW_AT_specification); + if (spec_die.IsValid() && spec_die == die) { + return func->GetMangled().GetMangledName().AsCString(); + } + } + } + + return nullptr; +} + TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs) { Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); @@ -1116,6 +1155,12 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, if (attrs.accessibility == eAccessNone) attrs.accessibility = eAccessPublic; + // Make sure we find the linkage name here so it gets + // attached to the member function inside + // AddMethodToCXXRecordType below. + if (!attrs.mangled_name && attrs.storage == clang::SC_Extern) + attrs.mangled_name = FindLinkageName(die); + clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType( class_opaque_type.GetOpaqueQualType(), diff --git a/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile new file mode 100644 index 000000000000..99998b20bcb0 --- /dev/null +++ b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py new file mode 100644 index 000000000000..027fd8e39d07 --- /dev/null +++ b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py @@ -0,0 +1,30 @@ +""" +Test that we can constructors/destructors +without a linkage name because they are +marked DW_AT_external and the fallback +mangled-name-guesser in LLDB doesn't account +for ABI tags. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class ExternalCtorDtorLookupTestCase(TestBase): + + def test(self): + self.build() + lldbutil.run_to_source_breakpoint(self, 'b\.getWrapper\(\)', + lldb.SBFileSpec('main.cpp', False)) + + self.expect_expr('b.sinkWrapper(b.getWrapper())', result_type='int', result_value='-1') + self.filecheck("target module dump ast", __file__) +# CHECK: ClassTemplateSpecializationDecl {{.*}} class Wrapper definition +# CHECK: |-TemplateArgument type 'Foo' +# CHECK: | `-RecordType {{.*}} 'Foo' +# CHECK: | `-CXXRecord {{.*}} 'Foo' +# CHECK: |-CXXConstructorDecl {{.*}} Wrapper 'void ()' +# CHECK-NEXT: | `-AsmLabelAttr {{.*}} Implicit "_ZN7WrapperI3FooEC1B4testEv" +# CHECK-NEXT: `-CXXDestructorDecl {{.*}} ~Wrapper 'void ()' +# CHECK-NEXT: `-AsmLabelAttr {{.*}} Implicit "_ZN7WrapperI3FooED1B4testEv" diff --git a/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h new file mode 100644 index 000000000000..070ba7ba7473 --- /dev/null +++ b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h @@ -0,0 +1,11 @@ +#ifndef LIB_H_IN +#define LIB_H_IN + +template <typename T> class Wrapper { +public: + [[gnu::abi_tag("test")]] Wrapper(){}; + + [[gnu::abi_tag("test")]] ~Wrapper(){}; +}; + +#endif // _H_IN diff --git a/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp new file mode 100644 index 000000000000..1503ae3f7da7 --- /dev/null +++ b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp @@ -0,0 +1,13 @@ +#include "lib.h" + +struct Foo {}; + +struct Bar { + Wrapper<Foo> getWrapper() { return Wrapper<Foo>(); } + int sinkWrapper(Wrapper<Foo>) { return -1; } +}; + +int main() { + Bar b; + return b.sinkWrapper(b.getWrapper()); +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits