Michael137 created this revision. Michael137 added reviewers: aprantl, labath, aeubanks. Herald added a reviewer: shafik. Herald added a project: All. Michael137 requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
**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 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D143652 Files: lldb/include/lldb/Symbol/Function.h lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 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
Index: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp @@ -0,0 +1,17 @@ +#include "lib.h" + +struct Foo {}; + +using FooWrapped = Wrapper<Foo>; + +struct S { + FooWrapped getTarget() { return Wrapper<Foo>(); } + int foo(FooWrapped) const { return -1; } + void bar() { foo(getTarget()); } +}; + +int main() { + S s; + s.foo(s.getTarget()); + return 0; +} Index: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h @@ -0,0 +1,11 @@ +#ifndef SPTR_H_IN +#define SPTR_H_IN + +template <typename T> class Wrapper { +public: + [[gnu::abi_tag("test")]] Wrapper(){}; + + [[gnu::abi_tag("test")]] ~Wrapper(){}; +}; + +#endif // _H_IN Index: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py =================================================================== --- /dev/null +++ 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, 'getTarget\(\)\)', + lldb.SBFileSpec('main.cpp', False)) + + self.expect_expr('s.foo(s.getTarget())', 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: | `-AsmLabelAttr {{.*}} Implicit "_ZN7WrapperI3FooEC1B4testEv" +# CHECK: `-CXXDestructorDecl {{.*}} ~Wrapper 'void ()' +# CHECK: `-AsmLabelAttr {{.*}} Implicit "_ZN7WrapperI3FooED1B4testEv" Index: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -888,6 +888,45 @@ 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; + + char const* new_mangled = 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()) { + auto* func = sc.function; + if (func) { + auto uid = func->GetID(); + auto spec_die = dwarf->GetDIE(uid).GetAttributeValueAsReferenceDIE(DW_AT_specification); + if (spec_die.IsValid() && spec_die == die) { + new_mangled = func->GetMangled().GetMangledName().AsCString(); + break; + } + } + } + + return new_mangled; +} + TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs) { Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); @@ -1116,6 +1155,12 @@ 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(), Index: lldb/include/lldb/Symbol/Function.h =================================================================== --- lldb/include/lldb/Symbol/Function.h +++ lldb/include/lldb/Symbol/Function.h @@ -630,6 +630,8 @@ bool GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor, Stream &strm, bool force_live_memory = false); + lldb::user_id_t GetUID() const { return m_type_uid; } + protected: enum { /// Whether we already tried to calculate the prologue size.
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits