From 00ef0a7c117caeec33b3fcceb5ef0c9e97eca9e3 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 7 Mar 2025 12:55:34 -0800 Subject: [PATCH 1/3] [lldb] Resolve Swift-implemented Objective-C classes using Swift runtime if the Objective-C runtime fails. This is a minimally invasive patch for the swift/release/6.1 branch to fix a problem with some versions of the Objective-C runtime. If an Objective-C class is lazy, the Objective-C runtie may not have materialized class metadata for it. However, if the class is actually implemented in Swift, we can still resolve it using the Swift runtime. We should probably also add the same logic to the Objective-C runtime, but I don't want risk adding an inifinite recursion this late in the release. --- .../Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 24fbb01a1b97e..8551d88daac8b 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -1985,7 +1985,8 @@ bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Class( }); return found; } - return false; + // Fall through. Swift-implemented Objective-C types may still + // be resolvable through the Swift class metadata. } Log *log(GetLog(LLDBLog::Types)); // Scope reflection_ctx to minimize its lock scope. From 5535de05bf212dee193ff9e181859f550df2ce0f Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 7 Mar 2025 17:18:08 -0800 Subject: [PATCH 2/3] WIP --- ...ftLanguageRuntimeDynamicTypeResolution.cpp | 60 ++++++++++++++----- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 8551d88daac8b..75bcc49baab03 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -1951,15 +1951,30 @@ bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Class( if (!error.Success()) return false; + bool is_clang_type = false; auto tss = class_type.GetTypeSystem().dyn_cast_or_null(); + if (!tss) { + is_clang_type = true; + if (auto module_sp = in_value.GetModule()) { + auto type_system_or_err = + module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeSwift); + if (!type_system_or_err) { + llvm::consumeError(type_system_or_err.takeError()); + return false; + } + auto ts_sp = *type_system_or_err; + tss = + llvm::cast(ts_sp.get())->GetTypeSystemSwiftTypeRef(); + } + } if (!tss) return false; + address.SetRawAddress(instance_ptr); auto ts = tss->GetTypeSystemSwiftTypeRef(); if (!ts) return false; - // Ask the Objective-C runtime about Objective-C types. - if (tss->IsImportedType(class_type.GetOpaqueQualType(), nullptr)) + auto resolve_objc = [&]() { if (auto *objc_runtime = SwiftLanguageRuntime::GetObjCRuntime(GetProcess())) { Value::ValueType value_type; @@ -1985,12 +2000,12 @@ bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Class( }); return found; } - // Fall through. Swift-implemented Objective-C types may still - // be resolvable through the Swift class metadata. } - Log *log(GetLog(LLDBLog::Types)); - // Scope reflection_ctx to minimize its lock scope. - { + return false; + }; + + auto resolve_swift = [&]() { + // Scope reflection_ctx to minimize its lock scope. ThreadSafeReflectionContext reflection_ctx = GetReflectionContext(); if (!reflection_ctx) return false; @@ -2034,10 +2049,19 @@ bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Class( return false; } } - - LLDB_LOG(log, "dynamic type of instance_ptr {0:x} is {1}", instance_ptr, + LLDB_LOG(GetLog(LLDBLog::Types), + "dynamic type of instance_ptr {0:x} is {1}", instance_ptr, class_type.GetMangledTypeName()); class_type_or_name.SetCompilerType(dynamic_type); + return true; + }; + + if (!resolve_swift()) { + // Ask the Objective-C runtime about Objective-C types. + if (is_clang_type || !tss->IsImportedType(class_type.GetOpaqueQualType(), nullptr)) + if (resolve_objc()) + return true; + return false; } #ifndef NDEBUG @@ -3018,22 +3042,28 @@ bool SwiftLanguageRuntime::GetDynamicTypeAndAddress( return false; LLDB_SCOPED_TIMER(); + CompilerType val_type(in_value.GetCompilerType()); + Value::ValueType static_value_type = Value::ValueType::Invalid; // Try to import a Clang type into Swift. - if (in_value.GetObjectRuntimeLanguage() == eLanguageTypeObjC) - return GetDynamicTypeAndAddress_ClangType(in_value, use_dynamic, - class_type_or_name, address, - value_type, local_buffer); + if (in_value.GetObjectRuntimeLanguage() == eLanguageTypeObjC) { + if (GetDynamicTypeAndAddress_ClangType(in_value, use_dynamic, + class_type_or_name, address, + value_type, local_buffer)) + return true; + else + return GetDynamicTypeAndAddress_Class(in_value, val_type, use_dynamic, + class_type_or_name, address, + static_value_type, local_buffer); + } if (!CouldHaveDynamicValue(in_value)) return false; - CompilerType val_type(in_value.GetCompilerType()); Flags type_info(val_type.GetTypeInfo()); if (!type_info.AnySet(eTypeIsSwift)) return false; - Value::ValueType static_value_type = Value::ValueType::Invalid; bool success = false; bool is_indirect_enum_case = IsIndirectEnumCase(in_value); // Type kinds with instance metadata don't need generic type resolution. From f7cdee50a4c9e7561fc091c7ff9b144e803bf2a6 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 24 Apr 2025 19:23:14 -0700 Subject: [PATCH 3/3] WIP --- .../ExpressionParser/Swift/SwiftREPL.cpp | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp b/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp index 53e8df708720b..dbccdb0d0a7ee 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp @@ -501,13 +501,27 @@ bool SwiftREPL::PrintOneVariable(Debugger &debugger, StreamFileSP &output_sp, options.SetRevealEmptyAggregates(false); options.SetHidePointerValue(true); options.SetVariableFormatDisplayLanguage(lldb::eLanguageTypeSwift); - options.SetDeclPrintingHelper([](ConstString type_name, - ConstString var_name, - const DumpValueObjectOptions &options, - Stream &stream) -> bool { + options.SetDeclPrintingHelper([&](ConstString type_name, + ConstString var_name, + const DumpValueObjectOptions &options, + Stream &stream) -> bool { if (!type_name || !var_name) return false; + // Try to get the SwiftASTContext representation of the type. It + // will hide Objective-C implemention details that are not + // publicly declared in the SDK. + if (valobj_sp) + if (auto dyn_valobj_sp = + valobj_sp->GetDynamicValue(lldb::eDynamicCanRunTarget)) { + CompilerType dyn_type = dyn_valobj_sp->GetCompilerType(); + Status error; + if (SwiftASTContext *ast_context = getSwiftASTContext()) { + CompilerType ast_type = ast_context->ImportType(dyn_type, error); + if (ast_type && error.Success()) + type_name = ast_type.GetDisplayTypeName(); + } + } std::string type_name_str(type_name ? type_name.GetCString() : ""); for (auto iter = type_name_str.find(" *"); iter != std::string::npos; iter = type_name_str.find(" *")) {