mirror of
https://github.com/intel/llvm.git
synced 2026-02-01 00:46:45 +08:00
[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
This commit is contained in:
@@ -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(),
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include Makefile.rules
|
||||
@@ -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"
|
||||
11
lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h
Normal file
11
lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h
Normal file
@@ -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
|
||||
13
lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp
Normal file
13
lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp
Normal file
@@ -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());
|
||||
}
|
||||
Reference in New Issue
Block a user