Author: Nerixyz
Date: 2026-08-08T11:57:15+02:00
New Revision: 6685d79985c4727cba6f71386665232d4d25f745

URL: 
https://github.com/llvm/llvm-project/commit/6685d79985c4727cba6f71386665232d4d25f745
DIFF: 
https://github.com/llvm/llvm-project/commit/6685d79985c4727cba6f71386665232d4d25f745.diff

LOG: [lldb] Allow multiple ABI runtimes for C++ (#212015)

This allows `CPPLanguageRuntime` to contain more than one ABI runtime.
For dynamic types, we ask each runtime if it knows how to deal with a
vtable symbol. For exception breakpoints, we will create all
breakpoints. Note that the MS ABI will only be added on Windows targets.
So the MS ABI will not be added to `m_abi_runtimes` on other targets.

Added: 
    

Modified: 
    lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
    lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
    lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
    lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp
    lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h

Removed: 
    


################################################################################
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.h 
b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
index 54d44caa2ebbc..72ded8c8f6481 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,30 @@ class CommonABIRuntime {
 public:
   virtual ~CommonABIRuntime() = default;
 
+  virtual llvm::StringRef GetName() const = 0;
+
+  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) {
+    return false;
+  }
+
+  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) {
+    return {};
+  }
+
 protected:
   CommonABIRuntime(Process *process);
 
@@ -37,6 +63,11 @@ class CommonABIRuntime {
   void SetDynamicTypeInfo(const lldb_private::Address &vtable_addr,
                           const TypeAndOrName &type_info);
 
+  TypeAndOrName GetDynamicTypeInfo(const lldb_private::Address &vtable_addr);
+
+  void SetDynamicTypeInfo(const lldb_private::Address &vtable_addr,
+                          const TypeAndOrName &type_info);
+
 protected:
   Process *m_process;
   std::mutex m_mutex;

diff  --git 
a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp 
b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp
index 5b983878623db..cd86d4a0ddb3a 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);
@@ -83,8 +87,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,


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to