[Lldb-commits] [lldb] 6b5c273 - Revert "[lldb] Move common functionality out of Itanium ABI runtime (#191275)" (#206816)
via lldb-commits
lldb-commits at lists.llvm.org
Tue Jun 30 13:01:14 PDT 2026
Author: Nerixyz
Date: 2026-06-30T20:01:09Z
New Revision: 6b5c27376a275ce34464631be3caed65967ab161
URL: https://github.com/llvm/llvm-project/commit/6b5c27376a275ce34464631be3caed65967ab161
DIFF: https://github.com/llvm/llvm-project/commit/6b5c27376a275ce34464631be3caed65967ab161.diff
LOG: Revert "[lldb] Move common functionality out of Itanium ABI runtime (#191275)" (#206816)
This reverts commit 0f51760a342cd8fed1c657e6ca134097c9e8f88c.
A test fails with the commit
(https://github.com/llvm/llvm-project/pull/191275#issuecomment-4846936554):
```
Traceback (most recent call last):
File "/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 596, in test_python_source_frames
self.assertNotIn("0xffffffffffffffff", output.lower())
AssertionError: '0xffffffffffffffff' unexpectedly found in "* thread #2, name = 'a.out', stop reason = breakpoint 1.1\n * frame #0: compute_fibonacci at python_helper.py:7 [synthetic]\n frame #1: process_data at python_helper.py:16 [synthetic]\n frame #2: main at python_helper.py:27 [synthetic]\n frame #3: 0x0000badc2de81358 a.out`thread_func(thread_num=0) at main.cpp:44:13\n frame #4: 0x0000badc2de81f9c a.out`void std::__invoke_impl<void, void (*)(int), int>((null)=__invoke_other @ 0x0000f1555ebae74f, __f=0x0000badc66845ec0, __args=0x0000badc66845eb8) at invoke.h:61:14\n frame #5: 0x0000badc2de81f18 a.out`std::__invoke_result<void (*)(int), int>::type std::__invoke<void (*)(int), int>(__fn=0x0000badc66845ec0, __args=0x0000badc66845eb8) at invoke.h:96:14\n frame #6: 0x0000badc2de81ee4 a.out`void std::thread::_invoker<std::tuple<void (*)(int), int>>::_m_invoke<0ul, 1ul>(this=0x0000badc66845eb8, (null)=_index_tuple<0ul, 1ul> @ 0x0000f1555ebae7af) at std_thread.h:259:13\n frame #7: 0x0000badc2de81e98 a.out`std::thread::_invoker<std::tuple<void (*)(int), int>>::operator()(this=0x0000badc66845eb8) at std_thread.h:266:11\n frame #8: 0x0000badc2de81d70 a.out`std::thread::_state_impl<std::thread::_invoker<std::tuple<void (*)(int), int>>>::_m_run(this=0xffffffffffffffff) at std_thread.h:211:13\n frame #9: 0x0000f1555ef029cc libstdc++.so.6`___lldb_unnamed_symbol_d29b0 + 28\n frame #10: 0x0000f1555ec30398 libc.so.6`___lldb_unnamed_symbol_800c0 + 728\n frame #11: 0x0000f1555ec99e9c libc.so.6`___lldb_unnamed_symbol_e9e90 + 12\n"
```
I don't know why this test fails with the PR, but I don't have time to
fix it now, so revert it to unblock CI.
The backtrace was
```
frame #0: compute_fibonacci at python_helper.py:7 [synthetic]
frame #1: process_data at python_helper.py:16 [synthetic]
frame #2: main at python_helper.py:27 [synthetic]
frame #3: 0x0000badc2de81358 a.out`thread_func(thread_num=0) at main.cpp:44:13
frame #4: 0x0000badc2de81f9c a.out`void std::__invoke_impl<void, void (*)(int), int>((null)=__invoke_other @ 0x0000f1555ebae74f, __f=0x0000badc66845ec0, __args=0x0000badc66845eb8) at invoke.h:61:14
frame #5: 0x0000badc2de81f18 a.out`std::__invoke_result<void (*)(int), int>::type std::__invoke<void (*)(int), int>(__fn=0x0000badc66845ec0, __args=0x0000badc66845eb8) at invoke.h:96:14
frame #6: 0x0000badc2de81ee4 a.out`void std::thread::_invoker<std::tuple<void (*)(int), int>>::_m_invoke<0ul, 1ul>(this=0x0000badc66845eb8, (null)=_index_tuple<0ul, 1ul> @ 0x0000f1555ebae7af) at std_thread.h:259:13
frame #7: 0x0000badc2de81e98 a.out`std::thread::_invoker<std::tuple<void (*)(int), int>>::operator()(this=0x0000badc66845eb8) at std_thread.h:266:11
frame #8: 0x0000badc2de81d70 a.out`std::thread::_state_impl<std::thread::_invoker<std::tuple<void (*)(int), int>>>::_m_run(this=0xffffffffffffffff) at std_thread.h:211:13
frame #9: 0x0000f1555ef029cc libstdc++.so.6`___lldb_unnamed_symbol_d29b0 + 28
frame #10: 0x0000f1555ec30398 libc.so.6`___lldb_unnamed_symbol_800c0 + 728
frame #11: 0x0000f1555ec99e9c libc.so.6`___lldb_unnamed_symbol_e9e90 + 12
```
This contains 0xffffffffffffffff in frame 8.
Added:
Modified:
lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp
lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h
Removed:
lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp
lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
################################################################################
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt
index dcf8fcd850db5..ca54601d99cff 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt
@@ -1,6 +1,5 @@
add_lldb_library(lldbPluginCPPRuntime PLUGIN
CommandObjectCPlusPlus.cpp
- CommonABIRuntime.cpp
CPPLanguageRuntime.cpp
ItaniumABIRuntime.cpp
VerboseTrapFrameRecognizer.cpp
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
index 2b657796c4f5e..c517ec8611932 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
@@ -13,7 +13,6 @@
#include "CPPLanguageRuntime.h"
#include "CommandObjectCPlusPlus.h"
-#include "ItaniumABIRuntime.h"
#include "VerboseTrapFrameRecognizer.h"
#include "llvm/ADT/StringRef.h"
@@ -33,7 +32,6 @@
#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;
@@ -112,7 +110,7 @@ class LibCXXFrameRecognizer : public StackFrameRecognizer {
};
CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
- : LanguageRuntime(process) {
+ : LanguageRuntime(process), m_itanium_runtime(process) {
if (process) {
process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
StackFrameRecognizerSP(new LibCXXFrameRecognizer()), {},
@@ -122,7 +120,6 @@ CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
RegisterVerboseTrapFrameRecognizer(*process);
}
- m_abi_runtimes.emplace_back(std::make_unique<ItaniumABIRuntime>(process));
}
bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
@@ -527,15 +524,8 @@ bool CPPLanguageRuntime::GetDynamicTypeAndAddress(
if (!CouldHaveDynamicValue(in_value))
return false;
- llvm::Expected<VTableInfoEntry> entry =
- GetVTableInfoEntry(in_value, /*check_type=*/false);
- if (!entry) {
- llvm::consumeError(entry.takeError());
- return false;
- }
-
- return entry->runtime->GetDynamicTypeAndAddress(
- in_value, use_dynamic, entry->info, class_type_or_name, dynamic_address);
+ return m_itanium_runtime.GetDynamicTypeAndAddress(
+ in_value, use_dynamic, class_type_or_name, dynamic_address, value_type);
}
TypeAndOrName
@@ -598,11 +588,7 @@ void CPPLanguageRuntime::Terminate() {
llvm::Expected<LanguageRuntime::VTableInfo>
CPPLanguageRuntime::GetVTableInfo(ValueObject &in_value, bool check_type) {
- llvm::Expected<VTableInfoEntry> entry =
- GetVTableInfoEntry(in_value, check_type);
- if (!entry)
- return entry.takeError();
- return entry->info;
+ return m_itanium_runtime.GetVTableInfo(in_value, check_type);
}
BreakpointResolverSP
@@ -616,10 +602,8 @@ CPPLanguageRuntime::CreateExceptionResolver(const BreakpointSP &bkpt,
bool catch_bp, bool throw_bp,
bool for_expressions) {
std::vector<const char *> exception_names;
- for (const auto &runtime : m_abi_runtimes) {
- runtime->AppendExceptionBreakpointFunctions(exception_names, catch_bp,
- throw_bp, for_expressions);
- }
+ m_itanium_runtime.AppendExceptionBreakpointFunctions(
+ exception_names, catch_bp, throw_bp, for_expressions);
BreakpointResolverSP resolver_sp(new BreakpointResolverName(
bkpt, exception_names.data(), exception_names.size(),
@@ -632,9 +616,8 @@ lldb::SearchFilterSP CPPLanguageRuntime::CreateExceptionSearchFilter() {
Target &target = m_process->GetTarget();
FileSpecList filter_modules;
- for (const auto &runtime : m_abi_runtimes)
- runtime->AppendExceptionBreakpointFilterModules(filter_modules, target);
-
+ m_itanium_runtime.AppendExceptionBreakpointFilterModules(filter_modules,
+ target);
return target.GetSearchFilterForModuleList(&filter_modules);
}
@@ -701,127 +684,5 @@ bool CPPLanguageRuntime::ExceptionBreakpointsExplainStop(
lldb::ValueObjectSP
CPPLanguageRuntime::GetExceptionObjectForThread(lldb::ThreadSP thread_sp) {
- for (auto &runtime : m_abi_runtimes) {
- ValueObjectSP valobj = runtime->GetExceptionObjectForThread(thread_sp);
- if (valobj)
- return valobj;
- }
- return {};
-}
-
-static llvm::Error typeHasVTable(CompilerType type) {
- // Check to make sure the class has a vtable.
- CompilerType original_type = type;
- if (type.IsPointerOrReferenceType()) {
- CompilerType pointee_type = type.GetPointeeType();
- if (pointee_type)
- type = pointee_type;
- }
-
- // Make sure this is a class or a struct first by checking the type class
- // bitfield that gets returned.
- if ((type.GetTypeClass() & (eTypeClassStruct | eTypeClassClass)) == 0) {
- return llvm::createStringError(
- std::errc::invalid_argument,
- "type \"%s\" is not a class or struct or a pointer to one",
- original_type.GetTypeName().AsCString("<invalid>"));
- }
-
- // Check if the type has virtual functions by asking it if it is polymorphic.
- if (!type.IsPolymorphicClass()) {
- return llvm::createStringError(std::errc::invalid_argument,
- "type \"%s\" doesn't have a vtable",
- type.GetTypeName().AsCString("<invalid>"));
- }
- return llvm::Error::success();
-}
-
-// This function can accept both pointers or references to classes as well as
-// instances of classes. If you are using this function during dynamic type
-// detection, only valid ValueObjects that return true to
-// CouldHaveDynamicValue(...) should call this function and \a check_type
-// should be set to false. This function is also used by ValueObjectVTable
-// and is can pass in instances of classes which is not suitable for dynamic
-// type detection, these cases should pass true for \a check_type.
-llvm::Expected<CPPLanguageRuntime::VTableInfoEntry>
-CPPLanguageRuntime::GetVTableInfoEntry(ValueObject &in_value, bool check_type) {
- CompilerType type = in_value.GetCompilerType();
- if (check_type) {
- if (llvm::Error err = typeHasVTable(type))
- return std::move(err);
- }
- ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
- Process *process = exe_ctx.GetProcessPtr();
- if (process == nullptr)
- return llvm::createStringError(std::errc::invalid_argument,
- "invalid process");
-
- auto [original_ptr, address_type] =
- type.IsPointerOrReferenceType()
- ? in_value.GetPointerValue()
- : in_value.GetAddressOf(/*scalar_is_load_address=*/true);
- if (original_ptr == LLDB_INVALID_ADDRESS || address_type != eAddressTypeLoad)
- return llvm::createStringError(std::errc::invalid_argument,
- "failed to get the address of the value");
-
- Status error;
- lldb::addr_t vtable_load_addr =
- process->ReadPointerFromMemory(original_ptr, error);
-
- if (!error.Success() || vtable_load_addr == LLDB_INVALID_ADDRESS)
- return llvm::createStringError(
- std::errc::invalid_argument,
- "failed to read vtable pointer from memory at 0x%" PRIx64,
- original_ptr);
-
- // The vtable load address can have authentication bits with
- // AArch64 targets on Darwin.
- vtable_load_addr = process->FixDataAddress(vtable_load_addr);
-
- // Find the symbol that contains the "vtable_load_addr" address
- Address vtable_addr;
- if (!process->GetTarget().ResolveLoadAddress(vtable_load_addr, vtable_addr))
- return llvm::createStringError(std::errc::invalid_argument,
- "failed to resolve vtable pointer 0x%" PRIx64
- " to a section",
- vtable_load_addr);
-
- // Check our cache first to see if we already have this info
- {
- std::lock_guard<std::mutex> locker(m_vtable_mutex);
- auto pos = m_vtable_info_map.find(vtable_addr);
- if (pos != m_vtable_info_map.end())
- return pos->second;
- }
-
- Symbol *symbol = vtable_addr.CalculateSymbolContextSymbol();
- if (symbol == nullptr)
- return llvm::createStringError(std::errc::invalid_argument,
- "no symbol found for 0x%" PRIx64,
- vtable_load_addr);
- Mangled &mangled = symbol->GetMangled();
- Log *log = GetLog(LLDBLog::Object);
- for (const auto &runtime : m_abi_runtimes) {
- if (runtime->IsVTableSymbol(mangled)) {
- 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;
- }
- }
-
- LLDB_LOG(log, "{0:x16} ({1}): symbol='{2}' does not match any runtime",
- original_ptr, in_value.GetTypeName(), mangled.GetDemangledName());
-
- return llvm::createStringError(std::errc::invalid_argument,
- "symbol found that contains 0x%" PRIx64
- " is not a vtable symbol",
- vtable_load_addr);
+ return m_itanium_runtime.GetExceptionObjectForThread(std::move(thread_sp));
}
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
index 823a968cbad8c..7c3dade76d703 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 "CommonABIRuntime.h"
+#include "ItaniumABIRuntime.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/lldb-private.h"
@@ -143,18 +143,7 @@ class CPPLanguageRuntime : public LanguageRuntime {
OperatorStringToCallableInfoMap CallableLookupCache;
lldb::BreakpointSP m_cxx_exception_bp_sp;
- std::vector<std::unique_ptr<CommonABIRuntime>> m_abi_runtimes;
-
- struct VTableInfoEntry {
- VTableInfo info;
- CommonABIRuntime *runtime;
- };
-
- llvm::Expected<VTableInfoEntry> GetVTableInfoEntry(ValueObject &in_value,
- bool check_type);
-
- std::map<Address, VTableInfoEntry> m_vtable_info_map;
- std::mutex m_vtable_mutex;
+ ItaniumABIRuntime m_itanium_runtime;
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp
deleted file mode 100644
index e1241c0b583aa..0000000000000
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "CommonABIRuntime.h"
-
-#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Utility/LLDBLog.h"
-
-using namespace lldb;
-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 {
- Log *log = GetLog(LLDBLog::Object);
-
- TypeList class_types;
- // We know the class name is absolute, so tell FindTypes that by
- // prefixing it with the root namespace:
- std::string lookup_name("::");
- lookup_name.append(type_name.data(), type_name.size());
- ConstString const_lookup_name(lookup_name);
- // First look in the module that the vtable symbol came from and
- // look for a single exact match.
- TypeResults results;
- TypeQuery query(const_lookup_name.GetStringRef(),
- TypeQueryOptions::e_exact_match |
- TypeQueryOptions::e_strict_namespaces |
- TypeQueryOptions::e_find_one);
- if (preferred_module) {
- preferred_module->FindTypes(query, results);
- TypeSP type_sp = results.GetFirstType();
- if (type_sp)
- class_types.Insert(type_sp);
- }
-
- // If we didn't find a symbol, then move on to the entire module
- // list in the target and get as many unique matches as possible
- if (class_types.Empty()) {
- query.SetFindOne(false);
- m_process->GetTarget().GetImages().FindTypes(nullptr, query, results);
- for (const auto &type_sp : results.GetTypeMap().Types())
- class_types.Insert(type_sp);
- }
-
- lldb::TypeSP type_sp;
- if (class_types.Empty()) {
- LLDB_LOG(log, "Failed to find '{0}'", type_name);
- return {};
- }
-
- if (class_types.GetSize() == 1) {
- type_sp = class_types.GetTypeAtIndex(0);
- if (!type_sp)
- return {};
-
- if (!TypeSystemClang::IsCXXClassType(type_sp->GetForwardCompilerType()))
- return {};
- return type_sp;
- }
-
- size_t i;
- if (log) {
- LLDB_LOG(log,
- "'{0}' has multiple matching dynamic "
- "types:",
- type_name);
- for (i = 0; i < class_types.GetSize(); i++) {
- type_sp = class_types.GetTypeAtIndex(i);
- if (type_sp) {
- LLDB_LOG(log, "[{0}]: uid={1:x}, type-name='{2}'", i, type_sp->GetID(),
- type_sp->GetName());
- }
- }
- }
-
- for (i = 0; i < class_types.GetSize(); i++) {
- type_sp = class_types.GetTypeAtIndex(i);
- if (type_sp) {
- if (TypeSystemClang::IsCXXClassType(type_sp->GetForwardCompilerType())) {
- LLDB_LOG(log,
- "'{0}' has multiple matching dynamic types, "
- "picking this one: [{1}] uid={2:x}, type-name='{3}'\n",
- type_name, i, type_sp->GetID(), type_sp->GetName());
- return type_sp;
- }
- }
- }
-
- LLDB_LOG(log,
- "'{0}' has multiple matching dynamic types, didn't find a C++ match",
- type_name);
- return {};
-}
-
-TypeAndOrName
-CommonABIRuntime::GetDynamicTypeInfo(const lldb_private::Address &vtable_addr) {
- std::lock_guard<std::mutex> locker(m_mutex);
- DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr);
- if (pos == m_dynamic_type_map.end())
- return TypeAndOrName();
-
- return pos->second;
-}
-
-void CommonABIRuntime::SetDynamicTypeInfo(
- const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info) {
- std::lock_guard<std::mutex> locker(m_mutex);
- m_dynamic_type_map[vtable_addr] = type_info;
-}
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
deleted file mode 100644
index b387ff0f8da8e..0000000000000
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CommonABIRuntime.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#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>
-
-namespace lldb_private {
-
-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);
-
- lldb::TypeSP LookupTypeByName(llvm::StringRef type_name,
- lldb::ModuleSP preferred_module) const;
-
- 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;
-
-private:
- using DynamicTypeCache = std::map<Address, TypeAndOrName>;
-
- DynamicTypeCache m_dynamic_type_map;
-};
-
-} // namespace lldb_private
-
-#endif
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp
index 1fc835fa834db..4d9cf31c8904d 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.cpp
@@ -19,13 +19,7 @@ using namespace lldb_private;
static const char *vtable_demangled_prefix = "vtable for ";
-ItaniumABIRuntime::ItaniumABIRuntime(Process *process)
- : CommonABIRuntime(process) {}
-
-bool ItaniumABIRuntime::IsVTableSymbol(Mangled &mangled) const {
- return mangled.GetDemangledName().GetStringRef().starts_with(
- vtable_demangled_prefix);
-}
+ItaniumABIRuntime::ItaniumABIRuntime(Process *process) : m_process(process) {}
TypeAndOrName
ItaniumABIRuntime::GetTypeInfo(ValueObject &in_value,
@@ -55,16 +49,94 @@ ItaniumABIRuntime::GetTypeInfo(ValueObject &in_value,
lookup_name.append(class_name.data(), class_name.size());
type_info.SetName(class_name);
- TypeSP type_sp = LookupTypeByName(
- class_name, vtable_info.symbol->CalculateSymbolContextModule());
- if (type_sp) {
- LLDB_LOG(
- log,
- "static-type = '{0}' has dynamic type: uid={1:x}, type-name='{2}'",
- in_value.GetTypeName(), type_sp->GetID(), type_sp->GetName());
- type_info.SetTypeSP(std::move(type_sp));
+ ConstString const_lookup_name(lookup_name);
+ TypeList class_types;
+ ModuleSP module_sp = vtable_info.symbol->CalculateSymbolContextModule();
+ // First look in the module that the vtable symbol came from and
+ // look for a single exact match.
+ TypeResults results;
+ TypeQuery query(const_lookup_name.GetStringRef(),
+ TypeQueryOptions::e_exact_match |
+ TypeQueryOptions::e_strict_namespaces |
+ TypeQueryOptions::e_find_one);
+ if (module_sp) {
+ module_sp->FindTypes(query, results);
+ TypeSP type_sp = results.GetFirstType();
+ if (type_sp)
+ class_types.Insert(type_sp);
+ }
+
+ // If we didn't find a symbol, then move on to the entire module
+ // list in the target and get as many unique matches as possible
+ if (class_types.Empty()) {
+ query.SetFindOne(false);
+ m_process->GetTarget().GetImages().FindTypes(nullptr, query, results);
+ for (const auto &type_sp : results.GetTypeMap().Types())
+ class_types.Insert(type_sp);
}
+ lldb::TypeSP type_sp;
+ if (class_types.Empty()) {
+ LLDB_LOGF(log, "0x%16.16" PRIx64 ": is not dynamic\n",
+ in_value.GetPointerValue().address);
+ return TypeAndOrName();
+ }
+ if (class_types.GetSize() == 1) {
+ type_sp = class_types.GetTypeAtIndex(0);
+ if (type_sp) {
+ if (TypeSystemClang::IsCXXClassType(
+ type_sp->GetForwardCompilerType())) {
+ LLDB_LOGF(log,
+ "0x%16.16" PRIx64
+ ": static-type = '%s' has dynamic type: uid={0x%" PRIx64
+ "}, type-name='%s'\n",
+ in_value.GetPointerValue().address,
+ in_value.GetTypeName().AsCString(""), type_sp->GetID(),
+ type_sp->GetName().GetCString());
+ type_info.SetTypeSP(type_sp);
+ }
+ }
+ } else {
+ size_t i;
+ if (log) {
+ for (i = 0; i < class_types.GetSize(); i++) {
+ type_sp = class_types.GetTypeAtIndex(i);
+ if (type_sp) {
+ LLDB_LOGF(log,
+ "0x%16.16" PRIx64
+ ": static-type = '%s' has multiple matching dynamic "
+ "types: uid={0x%" PRIx64 "}, type-name='%s'\n",
+ in_value.GetPointerValue().address,
+ in_value.GetTypeName().AsCString(""), type_sp->GetID(),
+ type_sp->GetName().GetCString());
+ }
+ }
+ }
+
+ for (i = 0; i < class_types.GetSize(); i++) {
+ type_sp = class_types.GetTypeAtIndex(i);
+ if (type_sp) {
+ if (TypeSystemClang::IsCXXClassType(
+ type_sp->GetForwardCompilerType())) {
+ LLDB_LOGF(log,
+ "0x%16.16" PRIx64 ": static-type = '%s' has multiple "
+ "matching dynamic types, picking "
+ "this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
+ in_value.GetPointerValue().address,
+ in_value.GetTypeName().AsCString(""), type_sp->GetID(),
+ type_sp->GetName().GetCString());
+ type_info.SetTypeSP(type_sp);
+ }
+ }
+ }
+
+ LLDB_LOGF(log,
+ "0x%16.16" PRIx64
+ ": static-type = '%s' has multiple matching dynamic "
+ "types, didn't find a C++ match\n",
+ in_value.GetPointerValue().address,
+ in_value.GetTypeName().AsCString(""));
+ }
if (type_info)
SetDynamicTypeInfo(vtable_info.addr, type_info);
return type_info;
@@ -73,10 +145,114 @@ ItaniumABIRuntime::GetTypeInfo(ValueObject &in_value,
return TypeAndOrName();
}
+llvm::Error ItaniumABIRuntime::TypeHasVTable(CompilerType type) {
+ // Check to make sure the class has a vtable.
+ CompilerType original_type = type;
+ if (type.IsPointerOrReferenceType()) {
+ CompilerType pointee_type = type.GetPointeeType();
+ if (pointee_type)
+ type = pointee_type;
+ }
+
+ // Make sure this is a class or a struct first by checking the type class
+ // bitfield that gets returned.
+ if ((type.GetTypeClass() & (eTypeClassStruct | eTypeClassClass)) == 0) {
+ return llvm::createStringError(
+ std::errc::invalid_argument,
+ "type \"%s\" is not a class or struct or a pointer to one",
+ original_type.GetTypeName().AsCString("<invalid>"));
+ }
+
+ // Check if the type has virtual functions by asking it if it is polymorphic.
+ if (!type.IsPolymorphicClass()) {
+ return llvm::createStringError(std::errc::invalid_argument,
+ "type \"%s\" doesn't have a vtable",
+ type.GetTypeName().AsCString("<invalid>"));
+ }
+ return llvm::Error::success();
+}
+
+// This function can accept both pointers or references to classes as well as
+// instances of classes. If you are using this function during dynamic type
+// detection, only valid ValueObjects that return true to
+// CouldHaveDynamicValue(...) should call this function and \a check_type
+// should be set to false. This function is also used by ValueObjectVTable
+// and is can pass in instances of classes which is not suitable for dynamic
+// type detection, these cases should pass true for \a check_type.
+llvm::Expected<LanguageRuntime::VTableInfo>
+ItaniumABIRuntime::GetVTableInfo(ValueObject &in_value, bool check_type) {
+
+ CompilerType type = in_value.GetCompilerType();
+ if (check_type) {
+ if (llvm::Error err = TypeHasVTable(type))
+ return std::move(err);
+ }
+ ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process == nullptr)
+ return llvm::createStringError(std::errc::invalid_argument,
+ "invalid process");
+
+ auto [original_ptr, address_type] =
+ type.IsPointerOrReferenceType()
+ ? in_value.GetPointerValue()
+ : in_value.GetAddressOf(/*scalar_is_load_address=*/true);
+ if (original_ptr == LLDB_INVALID_ADDRESS || address_type != eAddressTypeLoad)
+ return llvm::createStringError(std::errc::invalid_argument,
+ "failed to get the address of the value");
+
+ Status error;
+ lldb::addr_t vtable_load_addr =
+ process->ReadPointerFromMemory(original_ptr, error);
+
+ if (!error.Success() || vtable_load_addr == LLDB_INVALID_ADDRESS)
+ return llvm::createStringError(
+ std::errc::invalid_argument,
+ "failed to read vtable pointer from memory at 0x%" PRIx64,
+ original_ptr);
+
+ // The vtable load address can have authentication bits with
+ // AArch64 targets on Darwin.
+ vtable_load_addr = process->FixDataAddress(vtable_load_addr);
+
+ // Find the symbol that contains the "vtable_load_addr" address
+ Address vtable_addr;
+ if (!process->GetTarget().ResolveLoadAddress(vtable_load_addr, vtable_addr))
+ return llvm::createStringError(std::errc::invalid_argument,
+ "failed to resolve vtable pointer 0x%" PRIx64
+ "to a section",
+ vtable_load_addr);
+
+ // Check our cache first to see if we already have this info
+ {
+ std::lock_guard<std::mutex> locker(m_mutex);
+ auto pos = m_vtable_info_map.find(vtable_addr);
+ if (pos != m_vtable_info_map.end())
+ return pos->second;
+ }
+
+ Symbol *symbol = vtable_addr.CalculateSymbolContextSymbol();
+ if (symbol == nullptr)
+ return llvm::createStringError(std::errc::invalid_argument,
+ "no symbol found for 0x%" PRIx64,
+ vtable_load_addr);
+ llvm::StringRef name = symbol->GetMangled().GetDemangledName().GetStringRef();
+ if (name.starts_with(vtable_demangled_prefix)) {
+ LanguageRuntime::VTableInfo info = {vtable_addr, symbol};
+ std::lock_guard<std::mutex> locker(m_mutex);
+ auto pos = m_vtable_info_map[vtable_addr] = info;
+ return info;
+ }
+ return llvm::createStringError(std::errc::invalid_argument,
+ "symbol found that contains 0x%" PRIx64
+ " is not a vtable symbol",
+ vtable_load_addr);
+}
+
bool ItaniumABIRuntime::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,
+ Value::ValueType &value_type) {
// 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
@@ -90,6 +266,14 @@ bool ItaniumABIRuntime::GetDynamicTypeAndAddress(
// want GetVTableInfo to check the type since we accept void * as a possible
// dynamic type and that won't pass the type check. We already checked the
// type above in CouldHaveDynamicValue(...).
+ llvm::Expected<LanguageRuntime::VTableInfo> vtable_info_or_err =
+ GetVTableInfo(in_value, /*check_type=*/false);
+ if (!vtable_info_or_err) {
+ llvm::consumeError(vtable_info_or_err.takeError());
+ return false;
+ }
+
+ const LanguageRuntime::VTableInfo &vtable_info = vtable_info_or_err.get();
class_type_or_name = GetTypeInfo(in_value, vtable_info);
if (!class_type_or_name)
@@ -248,3 +432,19 @@ ItaniumABIRuntime::GetExceptionObjectForThread(ThreadSP thread_sp) {
return exception;
}
+
+TypeAndOrName ItaniumABIRuntime::GetDynamicTypeInfo(
+ const lldb_private::Address &vtable_addr) {
+ std::lock_guard<std::mutex> locker(m_mutex);
+ DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr);
+ if (pos == m_dynamic_type_map.end())
+ return TypeAndOrName();
+ else
+ return pos->second;
+}
+
+void ItaniumABIRuntime::SetDynamicTypeInfo(
+ const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info) {
+ std::lock_guard<std::mutex> locker(m_mutex);
+ m_dynamic_type_map[vtable_addr] = type_info;
+}
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h
index e44e958da4067..75a8142b26d93 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABIRuntime.h
@@ -9,7 +9,6 @@
#ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_CPLUSPLUS_ITANIUMABIRUNTIME_H
#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_CPLUSPLUS_ITANIUMABIRUNTIME_H
-#include "CommonABIRuntime.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/ValueObject/ValueObject.h"
@@ -17,40 +16,47 @@
namespace lldb_private {
-class ItaniumABIRuntime : public CommonABIRuntime {
+class ItaniumABIRuntime {
public:
ItaniumABIRuntime(Process *process);
- llvm::StringRef GetName() const override { return "Itanium ABI runtime"; }
-
- bool IsVTableSymbol(Mangled &manged) const override;
-
llvm::Expected<LanguageRuntime::VTableInfo>
GetVTableInfo(ValueObject &in_value, bool check_type);
bool GetDynamicTypeAndAddress(ValueObject &in_value,
lldb::DynamicValueType use_dynamic,
- const LanguageRuntime::VTableInfo &vtable_info,
TypeAndOrName &class_type_or_name,
- Address &dynamic_address) override;
+ Address &dynamic_address,
+ Value::ValueType &value_type);
void AppendExceptionBreakpointFunctions(std::vector<const char *> &names,
bool catch_bp, bool throw_bp,
- bool for_expressions) override;
+ bool for_expressions);
void AppendExceptionBreakpointFilterModules(FileSpecList &list,
- const Target &target) override;
+ const Target &target);
- lldb::ValueObjectSP
- GetExceptionObjectForThread(lldb::ThreadSP thread_sp) override;
+ lldb::ValueObjectSP GetExceptionObjectForThread(lldb::ThreadSP thread_sp);
private:
TypeAndOrName GetTypeInfo(ValueObject &in_value,
const LanguageRuntime::VTableInfo &vtable_info);
+ llvm::Error TypeHasVTable(CompilerType type);
+
+ TypeAndOrName GetDynamicTypeInfo(const lldb_private::Address &vtable_addr);
+
+ void SetDynamicTypeInfo(const lldb_private::Address &vtable_addr,
+ const TypeAndOrName &type_info);
+
+ using DynamicTypeCache = std::map<Address, TypeAndOrName>;
using VTableInfoCache = std::map<Address, LanguageRuntime::VTableInfo>;
+ DynamicTypeCache m_dynamic_type_map;
VTableInfoCache m_vtable_info_map;
+ std::mutex m_mutex;
+
+ Process *m_process;
};
} // namespace lldb_private
More information about the lldb-commits
mailing list