[llvm-branch-commits] [lldb] [lldb] Allow multiple ABI runtimes for C++ (PR #212015)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Aug 3 07:19:17 PDT 2026


https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/212015

>From dc8a018400eb48fcf211eec8c43b5587e863e2ea Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 1 Jul 2026 17:08:30 +0200
Subject: [PATCH 1/2] [lldb] Allow multiple ABI runtimes for C++

---
 .../CPlusPlus/CPPLanguageRuntime.cpp          | 52 +++++++++++++------
 .../CPlusPlus/CPPLanguageRuntime.h            |  5 +-
 .../CPlusPlus/CommonABIRuntime.cpp            | 21 ++++++++
 .../CPlusPlus/CommonABIRuntime.h              | 22 ++++++++
 .../CPlusPlus/ItaniumABIRuntime.cpp           |  7 ++-
 .../CPlusPlus/ItaniumABIRuntime.h             | 14 ++---
 6 files changed, 95 insertions(+), 26 deletions(-)

diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
index 1db208366fc55..23ffd1d67f163 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
@@ -13,6 +13,7 @@
 
 #include "CPPLanguageRuntime.h"
 #include "CommandObjectCPlusPlus.h"
+#include "ItaniumABIRuntime.h"
 #include "VerboseTrapFrameRecognizer.h"
 
 #include "llvm/ADT/StringRef.h"
@@ -32,6 +33,7 @@
 #include "lldb/Target/StackFrameRecognizer.h"
 #include "lldb/Target/ThreadPlanRunToAddress.h"
 #include "lldb/Target/ThreadPlanStepInRange.h"
+#include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Timer.h"
 
 using namespace lldb;
@@ -110,7 +112,7 @@ class LibCXXFrameRecognizer : public StackFrameRecognizer {
 };
 
 CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
-    : LanguageRuntime(process), m_itanium_runtime(process) {
+    : LanguageRuntime(process) {
   if (process) {
     process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
         StackFrameRecognizerSP(new LibCXXFrameRecognizer()), {},
@@ -120,6 +122,8 @@ CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
 
     RegisterVerboseTrapFrameRecognizer(*process);
   }
+
+  m_abi_runtimes.emplace_back(new ItaniumABIRuntime(process));
 }
 
 bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
@@ -548,9 +552,8 @@ bool CPPLanguageRuntime::GetDynamicTypeAndAddress(
     return false;
   }
 
-  return m_itanium_runtime.GetDynamicTypeAndAddress(
-      in_value, use_dynamic, entry->info, class_type_or_name, dynamic_address,
-      value_type);
+  return entry->runtime->GetDynamicTypeAndAddress(
+      in_value, use_dynamic, entry->info, class_type_or_name, dynamic_address);
 }
 
 TypeAndOrName
@@ -631,8 +634,9 @@ CPPLanguageRuntime::CreateExceptionResolver(const BreakpointSP &bkpt,
                                             bool catch_bp, bool throw_bp,
                                             bool for_expressions) {
   std::vector<const char *> exception_names;
-  m_itanium_runtime.AppendExceptionBreakpointFunctions(
-      exception_names, catch_bp, throw_bp, for_expressions);
+  for (const auto &runtime : m_abi_runtimes)
+    runtime->AppendExceptionBreakpointFunctions(exception_names, catch_bp,
+                                                throw_bp, for_expressions);
 
   BreakpointResolverSP resolver_sp(new BreakpointResolverName(
       bkpt, exception_names.data(), exception_names.size(),
@@ -645,8 +649,9 @@ lldb::SearchFilterSP CPPLanguageRuntime::CreateExceptionSearchFilter() {
   Target &target = m_process->GetTarget();
 
   FileSpecList filter_modules;
-  m_itanium_runtime.AppendExceptionBreakpointFilterModules(filter_modules,
-                                                           target);
+  for (const auto &runtime : m_abi_runtimes)
+    runtime->AppendExceptionBreakpointFilterModules(filter_modules, target);
+
   return target.GetSearchFilterForModuleList(&filter_modules);
 }
 
@@ -713,7 +718,12 @@ bool CPPLanguageRuntime::ExceptionBreakpointsExplainStop(
 
 lldb::ValueObjectSP
 CPPLanguageRuntime::GetExceptionObjectForThread(lldb::ThreadSP thread_sp) {
-  return m_itanium_runtime.GetExceptionObjectForThread(std::move(thread_sp));
+  for (const auto &runtime : m_abi_runtimes) {
+    ValueObjectSP valobj = runtime->GetExceptionObjectForThread(thread_sp);
+    if (valobj)
+      return valobj;
+  }
+  return {};
 }
 
 static llvm::Error TypeHasVTable(CompilerType type) {
@@ -807,13 +817,23 @@ CPPLanguageRuntime::GetVTableInfoEntry(ValueObject &in_value, bool check_type) {
     return llvm::createStringError(std::errc::invalid_argument,
                                    "no symbol found for 0x%" PRIx64,
                                    vtable_load_addr);
-  if (m_itanium_runtime.IsVTableSymbol(symbol->GetMangled())) {
-    VTableInfoEntry entry{
-        /*info=*/VTableInfo{vtable_addr, symbol},
-    };
-    std::lock_guard<std::mutex> locker(m_vtable_mutex);
-    m_vtable_info_map[vtable_addr] = entry;
-    return entry;
+
+  Mangled &mangled = symbol->GetMangled();
+  Log *log = GetLog(LLDBLog::Object);
+  for (const auto &runtime : m_abi_runtimes) {
+    if (runtime->IsVTableSymbol(symbol->GetMangled())) {
+      LLDB_LOG(log, "{0:x16} ({1}): symbol='{2}' matches {3}", original_ptr,
+               in_value.GetTypeName(), mangled.GetDemangledName(),
+               runtime->GetName());
+
+      VTableInfoEntry entry{
+          /*info=*/VTableInfo{vtable_addr, symbol},
+          /*runtime=*/runtime.get(),
+      };
+      std::lock_guard<std::mutex> locker(m_vtable_mutex);
+      m_vtable_info_map[vtable_addr] = entry;
+      return entry;
+    }
   }
   return llvm::createStringError(std::errc::invalid_argument,
                                  "symbol found that contains 0x%" PRIx64
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
index 0ed1a71b976be..823a968cbad8c 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
@@ -13,7 +13,7 @@
 
 #include "llvm/ADT/StringMap.h"
 
-#include "ItaniumABIRuntime.h"
+#include "CommonABIRuntime.h"
 #include "lldb/Core/PluginInterface.h"
 #include "lldb/Target/LanguageRuntime.h"
 #include "lldb/lldb-private.h"
@@ -143,10 +143,11 @@ class CPPLanguageRuntime : public LanguageRuntime {
   OperatorStringToCallableInfoMap CallableLookupCache;
 
   lldb::BreakpointSP m_cxx_exception_bp_sp;
-  ItaniumABIRuntime m_itanium_runtime;
+  std::vector<std::unique_ptr<CommonABIRuntime>> m_abi_runtimes;
 
   struct VTableInfoEntry {
     VTableInfo info;
+    CommonABIRuntime *runtime;
   };
 
   llvm::Expected<VTableInfoEntry> GetVTableInfoEntry(ValueObject &in_value,
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp
index a8ed0e810b700..eecaed18f9103 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp
@@ -17,6 +17,27 @@ using namespace lldb_private;
 
 CommonABIRuntime::CommonABIRuntime(Process *process) : m_process(process) {}
 
+bool CommonABIRuntime::IsVTableSymbol(Mangled &mangled) const { return false; }
+
+bool CommonABIRuntime::GetDynamicTypeAndAddress(
+    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+    const LanguageRuntime::VTableInfo &vtable_info,
+    TypeAndOrName &class_type_or_name, Address &dynamic_address) {
+  return false;
+}
+
+void CommonABIRuntime::AppendExceptionBreakpointFunctions(
+    std::vector<const char *> &names, bool catch_bp, bool throw_bp,
+    bool for_expressions) {}
+
+void CommonABIRuntime::AppendExceptionBreakpointFilterModules(
+    FileSpecList &list, const Target &target) {}
+
+lldb::ValueObjectSP
+CommonABIRuntime::GetExceptionObjectForThread(lldb::ThreadSP thread_sp) {
+  return {};
+}
+
 lldb::TypeSP
 CommonABIRuntime::LookupTypeByName(llvm::StringRef type_name,
                                    lldb::ModuleSP preferred_module) const {
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
index 7fc8248c3e192..b387ff0f8da8e 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
@@ -9,7 +9,9 @@
 #ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_CPLUSPLUS_COMMONABIRUNTIME_H
 #define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_CPLUSPLUS_COMMONABIRUNTIME_H
 
+#include "lldb/Target/LanguageRuntime.h"
 #include "lldb/Target/Process.h"
+#include "lldb/ValueObject/ValueObject.h"
 
 #include <map>
 #include <mutex>
@@ -20,6 +22,26 @@ class CommonABIRuntime {
 public:
   virtual ~CommonABIRuntime() = default;
 
+  virtual llvm::StringRef GetName() const = 0;
+
+  virtual bool IsVTableSymbol(Mangled &mangled) const;
+
+  virtual bool GetDynamicTypeAndAddress(
+      ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+      const LanguageRuntime::VTableInfo &vtable_info,
+      TypeAndOrName &class_type_or_name, Address &dynamic_address);
+
+  virtual void
+  AppendExceptionBreakpointFunctions(std::vector<const char *> &names,
+                                     bool catch_bp, bool throw_bp,
+                                     bool for_expressions);
+
+  virtual void AppendExceptionBreakpointFilterModules(FileSpecList &list,
+                                                      const Target &target);
+
+  virtual lldb::ValueObjectSP
+  GetExceptionObjectForThread(lldb::ThreadSP thread_sp);
+
 protected:
   CommonABIRuntime(Process *process);
 
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp
index db1c2a62681d3..7ace3e2e8aebb 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp
@@ -22,6 +22,10 @@ static const char *vtable_demangled_prefix = "vtable for ";
 ItaniumABIRuntime::ItaniumABIRuntime(Process *process)
     : CommonABIRuntime(process) {}
 
+llvm::StringRef ItaniumABIRuntime::GetName() const {
+  return "Itanium ABI runtime";
+}
+
 bool ItaniumABIRuntime::IsVTableSymbol(Mangled &mangled) const {
   return mangled.GetDemangledName().GetStringRef().starts_with(
       vtable_demangled_prefix);
@@ -78,8 +82,7 @@ ItaniumABIRuntime::GetTypeInfo(ValueObject &in_value,
 bool ItaniumABIRuntime::GetDynamicTypeAndAddress(
     ValueObject &in_value, lldb::DynamicValueType use_dynamic,
     const LanguageRuntime::VTableInfo &vtable_info,
-    TypeAndOrName &class_type_or_name, Address &dynamic_address,
-    Value::ValueType &value_type) {
+    TypeAndOrName &class_type_or_name, Address &dynamic_address) {
   // For Itanium, if the type has a vtable pointer in the object, it will be at
   // offset 0 in the object.  That will point to the "address point" within the
   // vtable (not the beginning of the vtable.)  We can then look up the symbol
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h
index 7c4cf019ee975..af0eb5e0c6603 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h
@@ -21,23 +21,25 @@ class ItaniumABIRuntime : public CommonABIRuntime {
 public:
   ItaniumABIRuntime(Process *process);
 
-  bool IsVTableSymbol(Mangled &manged) const;
+  llvm::StringRef GetName() const override;
+
+  bool IsVTableSymbol(Mangled &manged) const override;
 
   bool GetDynamicTypeAndAddress(ValueObject &in_value,
                                 lldb::DynamicValueType use_dynamic,
                                 const LanguageRuntime::VTableInfo &vtable_info,
                                 TypeAndOrName &class_type_or_name,
-                                Address &dynamic_address,
-                                Value::ValueType &value_type);
+                                Address &dynamic_address) override;
 
   void AppendExceptionBreakpointFunctions(std::vector<const char *> &names,
                                           bool catch_bp, bool throw_bp,
-                                          bool for_expressions);
+                                          bool for_expressions) override;
 
   void AppendExceptionBreakpointFilterModules(FileSpecList &list,
-                                              const Target &target);
+                                              const Target &target) override;
 
-  lldb::ValueObjectSP GetExceptionObjectForThread(lldb::ThreadSP thread_sp);
+  lldb::ValueObjectSP
+  GetExceptionObjectForThread(lldb::ThreadSP thread_sp) override;
 
 private:
   TypeAndOrName GetTypeInfo(ValueObject &in_value,

>From 8b72ae90ce14752c8e682da6bd67220ef335ab37 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Mon, 3 Aug 2026 16:18:51 +0200
Subject: [PATCH 2/2] fix: define empty functions in the header

---
 .../CPlusPlus/CommonABIRuntime.cpp            | 21 -------------------
 .../CPlusPlus/CommonABIRuntime.h              | 14 ++++++++-----
 2 files changed, 9 insertions(+), 26 deletions(-)

diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp
index eecaed18f9103..a8ed0e810b700 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp
@@ -17,27 +17,6 @@ using namespace lldb_private;
 
 CommonABIRuntime::CommonABIRuntime(Process *process) : m_process(process) {}
 
-bool CommonABIRuntime::IsVTableSymbol(Mangled &mangled) const { return false; }
-
-bool CommonABIRuntime::GetDynamicTypeAndAddress(
-    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
-    const LanguageRuntime::VTableInfo &vtable_info,
-    TypeAndOrName &class_type_or_name, Address &dynamic_address) {
-  return false;
-}
-
-void CommonABIRuntime::AppendExceptionBreakpointFunctions(
-    std::vector<const char *> &names, bool catch_bp, bool throw_bp,
-    bool for_expressions) {}
-
-void CommonABIRuntime::AppendExceptionBreakpointFilterModules(
-    FileSpecList &list, const Target &target) {}
-
-lldb::ValueObjectSP
-CommonABIRuntime::GetExceptionObjectForThread(lldb::ThreadSP thread_sp) {
-  return {};
-}
-
 lldb::TypeSP
 CommonABIRuntime::LookupTypeByName(llvm::StringRef type_name,
                                    lldb::ModuleSP preferred_module) const {
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
index b387ff0f8da8e..c68d5a63a0057 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
@@ -24,23 +24,27 @@ class CommonABIRuntime {
 
   virtual llvm::StringRef GetName() const = 0;
 
-  virtual bool IsVTableSymbol(Mangled &mangled) const;
+  virtual bool IsVTableSymbol(Mangled &mangled) const { return false; }
 
   virtual bool GetDynamicTypeAndAddress(
       ValueObject &in_value, lldb::DynamicValueType use_dynamic,
       const LanguageRuntime::VTableInfo &vtable_info,
-      TypeAndOrName &class_type_or_name, Address &dynamic_address);
+      TypeAndOrName &class_type_or_name, Address &dynamic_address) {
+    return false;
+  }
 
   virtual void
   AppendExceptionBreakpointFunctions(std::vector<const char *> &names,
                                      bool catch_bp, bool throw_bp,
-                                     bool for_expressions);
+                                     bool for_expressions) {}
 
   virtual void AppendExceptionBreakpointFilterModules(FileSpecList &list,
-                                                      const Target &target);
+                                                      const Target &target) {}
 
   virtual lldb::ValueObjectSP
-  GetExceptionObjectForThread(lldb::ThreadSP thread_sp);
+  GetExceptionObjectForThread(lldb::ThreadSP thread_sp) {
+    return {};
+  }
 
 protected:
   CommonABIRuntime(Process *process);



More information about the llvm-branch-commits mailing list