[Lldb-commits] [lldb] b296ddd - [lldb][DWARFASTParserClang] Attach linkage name to ctors/dtors if missing

Michael Buch via lldb-commits lldb-commits at lists.llvm.org
Fri Feb 10 09:22:25 PST 2023


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());
+}


        


More information about the lldb-commits mailing list