[llvm-branch-commits] [lldb] [lldb] Allow multiple ABI runtimes for C++ (PR #212015)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Jul 25 04:18:35 PDT 2026
https://github.com/Nerixyz created https://github.com/llvm/llvm-project/pull/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.
---
<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
>From 80f1904fec56ba4ef76b9d88e76e7b41898b80b0 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 1 Jul 2026 17:08:30 +0200
Subject: [PATCH] [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,
More information about the llvm-branch-commits
mailing list