diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp index d4fdb4c5cf739..19d7165882c25 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp @@ -412,7 +412,7 @@ static bool HasReflectionInfo(ObjectFile *obj_file) { return hasReflectionSection; } -SwiftLanguageRuntimeImpl::NativeReflectionContext * +SwiftLanguageRuntimeImpl::ReflectionContextInterface * SwiftLanguageRuntimeImpl::GetReflectionContext() { if (!m_initialized_reflection_ctx) SetupReflection(); @@ -438,7 +438,21 @@ void SwiftLanguageRuntimeImpl::SetupReflection() { if (m_initialized_reflection_ctx) return; - m_reflection_ctx.reset(new NativeReflectionContext(this->GetMemoryReader())); + auto &target = m_process.GetTarget(); + if (auto exe_module = target.GetExecutableModule()) { + auto &triple = exe_module->GetArchitecture().GetTriple(); + if (triple.isArch64Bit()) + m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext64( + this->GetMemoryReader()); + else if (triple.isArch32Bit()) + m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext32( + this->GetMemoryReader()); + else { + LLDB_LOGF(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES), + "Could not initialize reflection context for \"%s\"", + triple.str().c_str()); + } + } m_initialized_reflection_ctx = true; // Add all defered modules to reflection context that were added to diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 12f56a94df70d..fd26155589228 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -250,6 +250,142 @@ lldb::addr_t SwiftLanguageRuntime::MaybeMaskNonTrivialReferencePointer( return addr; } +namespace { + +/// An implementation of the generic ReflectionContextInterface that +/// is templatized on target pointer width and specialized to either +/// 32-bit or 64-bit pointers. +template +class TargetReflectionContext + : public SwiftLanguageRuntimeImpl::ReflectionContextInterface { + using ReflectionContext = swift::reflection::ReflectionContext< + swift::External>>; + ReflectionContext m_reflection_ctx; + +public: + TargetReflectionContext( + std::shared_ptr reader) + : m_reflection_ctx(reader) {} + + bool addImage( + llvm::function_ref, uint64_t>( + swift::ReflectionSectionKind)> + find_section) override { + return m_reflection_ctx.addImage(find_section); + } + + bool addImage(swift::remote::RemoteAddress image_start) override { + return m_reflection_ctx.addImage(image_start); + } + + bool readELF(swift::remote::RemoteAddress ImageStart, + llvm::Optional FileBuffer) override { + return m_reflection_ctx.readELF(ImageStart, FileBuffer); + } + + const swift::reflection::TypeInfo * + getTypeInfo(const swift::reflection::TypeRef *type_ref, + swift::remote::TypeInfoProvider *provider) override { + return m_reflection_ctx.getTypeInfo(type_ref, provider); + } + + swift::reflection::MemoryReader &getReader() override { + return m_reflection_ctx.getReader(); + } + + bool ForEachSuperClassType( + LLDBTypeInfoProvider *tip, lldb::addr_t pointer, + std::function fn) + override { + auto md_ptr = m_reflection_ctx.readMetadataFromInstance(pointer); + if (!md_ptr) + return false; + + // Class object. + LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES), + "found RecordTypeInfo for instance"); + while (md_ptr && *md_ptr) { + // Reading metadata is potentially expensive since (in a remote + // debugging scenario it may even incur network traffic) so we + // just return closures that the caller can use to query details + // if they need them.' + auto metadata = *md_ptr; + if (fn({[=]() -> const swift::reflection::RecordTypeInfo * { + auto *ti = m_reflection_ctx.getMetadataTypeInfo(metadata, tip); + return llvm::dyn_cast_or_null< + swift::reflection::RecordTypeInfo>(ti); + }, + [=]() -> const swift::reflection::TypeRef * { + return m_reflection_ctx.readTypeFromMetadata(metadata); + }})) + return true; + + // Continue with the base class. + md_ptr = m_reflection_ctx.readSuperClassFromClassMetadata(metadata); + } + return false; + } + + llvm::Optional> + projectExistentialAndUnwrapClass( + swift::reflection::RemoteAddress existential_address, + const swift::reflection::TypeRef &existential_tr) override { + return m_reflection_ctx.projectExistentialAndUnwrapClass( + existential_address, existential_tr); + } + + const swift::reflection::TypeRef * + readTypeFromMetadata(lldb::addr_t metadata_address, + bool skip_artificial_subclasses) override { + return m_reflection_ctx.readTypeFromMetadata(metadata_address, + skip_artificial_subclasses); + } + + const swift::reflection::TypeRef * + readTypeFromInstance(lldb::addr_t instance_address, + bool skip_artificial_subclasses) override { + auto metadata_address = + m_reflection_ctx.readMetadataFromInstance(instance_address); + if (!metadata_address) { + LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES), + "could not read heap metadata for object at %llu\n", + instance_address); + return nullptr; + } + + return m_reflection_ctx.readTypeFromMetadata(*metadata_address, + skip_artificial_subclasses); + } + + swift::reflection::TypeRefBuilder &getBuilder() override { + return m_reflection_ctx.getBuilder(); + } + + llvm::Optional isValueInlinedInExistentialContainer( + swift::remote::RemoteAddress existential_address) override { + return m_reflection_ctx.isValueInlinedInExistentialContainer( + existential_address); + } +}; + +} // namespace + +std::unique_ptr +SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext32( + std::shared_ptr reader) { + return std::make_unique>(reader); +} + +std::unique_ptr +SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext64( + std::shared_ptr reader) { + return std::make_unique>(reader); +} + +SwiftLanguageRuntimeImpl::ReflectionContextInterface:: + ~ReflectionContextInterface() {} + const CompilerType &SwiftLanguageRuntimeImpl::GetBoxMetadataType() { if (m_box_metadata_type.IsValid()) return m_box_metadata_type; @@ -634,6 +770,8 @@ class ASTVerifier : public swift::ASTWalker { } }; +} // namespace + class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { SwiftLanguageRuntimeImpl &m_runtime; TypeSystemSwift &m_typesystem; @@ -712,7 +850,8 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { if (is_bitfield_ptr) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); if (log) - log->Printf("[LLDBTypeInfoProvider] bitfield support is not yet implemented"); + log->Printf("[LLDBTypeInfoProvider] bitfield support is not yet " + "implemented"); continue; } swift::reflection::FieldInfo field_info = { @@ -725,8 +864,6 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { } }; -} // namespace - llvm::Optional SwiftLanguageRuntimeImpl::lookupClangTypeInfo(CompilerType clang_type) { std::lock_guard locker(m_clang_type_info_mutex); @@ -1574,35 +1711,9 @@ bool SwiftLanguageRuntimeImpl::ForEachSuperClassType( if (!ts) return false; + LLDBTypeInfoProvider tip(*this, *ts); lldb::addr_t pointer = instance.GetPointerValue(); - auto md_ptr = reflection_ctx->readMetadataFromInstance(pointer); - if (!md_ptr) - return false; - - // Class object. - LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES), - "found RecordTypeInfo for instance"); - while (md_ptr && *md_ptr) { - // Reading metadata is potentially expensive since (in a remote - // debugging scenario it may even incur network traffic) so we - // just return closures that the caller can use to query details - // if they need them. - auto metadata = *md_ptr; - if (fn({[=]() -> const swift::reflection::RecordTypeInfo * { - LLDBTypeInfoProvider tip(*this, *ts); - auto *ti = reflection_ctx->getMetadataTypeInfo(metadata, &tip); - return llvm::dyn_cast_or_null( - ti); - }, - [=]() -> const swift::reflection::TypeRef * { - return reflection_ctx->readTypeFromMetadata(metadata); - }})) - return true; - - // Continue with the base class. - md_ptr = reflection_ctx->readSuperClassFromClassMetadata(metadata); - } - return false; + return reflection_ctx->ForEachSuperClassType(&tip, pointer, fn); } bool SwiftLanguageRuntime::IsSelf(Variable &variable) { @@ -1673,8 +1784,8 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class( lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address) { AddressType address_type; - lldb::addr_t class_metadata_ptr = in_value.GetPointerValue(&address_type); - if (class_metadata_ptr == LLDB_INVALID_ADDRESS || class_metadata_ptr == 0) + lldb::addr_t instance_ptr = in_value.GetPointerValue(&address_type); + if (instance_ptr == LLDB_INVALID_ADDRESS || instance_ptr == 0) return false; CompilerType static_type = in_value.GetCompilerType(); @@ -1682,7 +1793,7 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class( llvm::dyn_cast_or_null(static_type.GetTypeSystem()); if (!tss) return false; - address.SetRawAddress(class_metadata_ptr); + address.SetRawAddress(instance_ptr); auto &ts = tss->GetTypeSystemSwiftTypeRef(); // Ask the Objective-C runtime about Objective-C types. if (tss->IsImportedType(static_type.GetOpaqueQualType(), nullptr)) @@ -1712,19 +1823,7 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class( } Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); auto *reflection_ctx = GetReflectionContext(); - swift::remote::RemoteAddress instance_address(class_metadata_ptr); - auto metadata_address = - reflection_ctx->readMetadataFromInstance(class_metadata_ptr); - if (!metadata_address) { - if (log) - log->Printf("could not read heap metadata for object at %llu\n", - class_metadata_ptr); - return false; - } - - const auto *typeref = - reflection_ctx->readTypeFromMetadata(*metadata_address, - /*skipArtificial=*/false); + const auto *typeref = reflection_ctx->readTypeFromInstance(instance_ptr); if (!typeref) return false; swift::Demangle::Demangler dem; @@ -1733,8 +1832,8 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class( #ifndef NDEBUG auto &remote_ast = GetRemoteASTContext(scratch_ctx); - auto remote_ast_metadata_address = - remote_ast.getHeapMetadataForObject(instance_address); + auto remote_ast_metadata_address = remote_ast.getHeapMetadataForObject( + swift::remote::RemoteAddress(instance_ptr)); if (remote_ast_metadata_address) { auto instance_type = remote_ast.getTypeForRemoteTypeMetadata( remote_ast_metadata_address.getValue(), @@ -1748,9 +1847,8 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class( << "\n"; } else { if (log) { - log->Printf( - "could not get type metadata from address %" PRIu64 " : %s\n", - *metadata_address, instance_type.getFailure().render().c_str()); + log->Printf("could not get type metadata: %s\n", + instance_type.getFailure().render().c_str()); } } } diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h index 7474ab2516600..711c36941495b 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h @@ -15,6 +15,7 @@ #include "SwiftLanguageRuntime.h" #include "swift/Reflection/TypeLowering.h" +#include "llvm/Support/Memory.h" namespace swift { namespace reflection { @@ -24,6 +25,7 @@ class TypeRef; namespace lldb_private { class Process; +class LLDBTypeInfoProvider; /// A full LLDB language runtime backed by the Swift runtime library /// in the process. @@ -177,15 +179,6 @@ class SwiftLanguageRuntimeImpl { bool IsABIStable(); -protected: - using NativeReflectionContext = swift::reflection::ReflectionContext< - swift::External>>; - - /// Use the reflection context to build a TypeRef object. - const swift::reflection::TypeRef * - GetTypeRef(CompilerType type, TypeSystemSwiftTypeRef *module_holder, - SwiftASTContext *swift_ast_context); - /// Returned by \ref ForEachSuperClassType. Not every user of \p /// ForEachSuperClassType needs all of these. By returning this /// object we call into the runtime only when needed. @@ -194,6 +187,62 @@ class SwiftLanguageRuntimeImpl { std::function get_record_type_info; std::function get_typeref; }; + + /// An abstract interface to swift::reflection::ReflectionContext + /// objects of varying pointer sizes. This class encapsulates all + /// traffic to ReflectionContext and abstracts the detail that + /// ReflectionContext is a template that needs to be specialized for + /// a specific pointer width. + class ReflectionContextInterface { + public: + /// Return a 32-bit reflection context. + static std::unique_ptr + CreateReflectionContext32( + std::shared_ptr reader); + + /// Return a 64-bit reflection context. + static std::unique_ptr + CreateReflectionContext64( + std::shared_ptr reader); + + virtual ~ReflectionContextInterface(); + + virtual bool addImage( + llvm::function_ref, uint64_t>( + swift::ReflectionSectionKind)> + find_section); + virtual bool addImage(swift::remote::RemoteAddress image_start) = 0; + virtual bool readELF(swift::remote::RemoteAddress ImageStart, + llvm::Optional FileBuffer) = 0; + virtual const swift::reflection::TypeInfo * + getTypeInfo(const swift::reflection::TypeRef *type_ref, + swift::remote::TypeInfoProvider *provider) = 0; + virtual swift::remote::MemoryReader &getReader() = 0; + virtual bool + ForEachSuperClassType(LLDBTypeInfoProvider *tip, lldb::addr_t pointer, + std::function fn) = 0; + virtual llvm::Optional> + projectExistentialAndUnwrapClass( + swift::remote::RemoteAddress existential_addess, + const swift::reflection::TypeRef &existential_tr) = 0; + virtual const swift::reflection::TypeRef * + readTypeFromMetadata(lldb::addr_t metadata_address, + bool skip_artificial_subclasses = false) = 0; + virtual const swift::reflection::TypeRef * + readTypeFromInstance(lldb::addr_t instance_address, + bool skip_artificial_subclasses = false) = 0; + virtual swift::reflection::TypeRefBuilder &getBuilder() = 0; + virtual llvm::Optional isValueInlinedInExistentialContainer( + swift::remote::RemoteAddress existential_address) = 0; + }; + +protected: + /// Use the reflection context to build a TypeRef object. + const swift::reflection::TypeRef * + GetTypeRef(CompilerType type, TypeSystemSwiftTypeRef *module_holder, + SwiftASTContext *swift_ast_context); + /// If \p instance points to a Swift object, retrieve its /// RecordTypeInfo and pass it to the callback \p fn. Repeat the /// process with all superclasses. If \p fn returns \p true, early @@ -301,7 +350,7 @@ class SwiftLanguageRuntimeImpl { llvm::Optional GetDynamicExclusivityFlagAddr(); /// Lazily initialize the reflection context. Return \p nullptr on failure. - NativeReflectionContext *GetReflectionContext(); + ReflectionContextInterface *GetReflectionContext(); /// Lazily initialize and return \p m_SwiftNativeNSErrorISA. llvm::Optional GetSwiftNativeNSErrorISA(); @@ -321,7 +370,7 @@ class SwiftLanguageRuntimeImpl { /// Reflection context. /// \{ - std::unique_ptr m_reflection_ctx; + std::unique_ptr m_reflection_ctx; /// Record modules added through ModulesDidLoad, which are to be /// added to the reflection context once it's being initialized.