//===--- MetadataReader.h - Abstract access to remote metadata --*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines operations for reading metadata from a remote process. // //===----------------------------------------------------------------------===// #ifndef SWIFT_REMOTE_METADATAREADER_H #define SWIFT_REMOTE_METADATAREADER_H #include "swift/ABI/Metadata.h" #include "swift/Runtime/Metadata.h" #include "swift/Remote/MemoryReader.h" #include "swift/Demangling/Demangler.h" #include "swift/Demangling/TypeDecoder.h" #include "swift/Basic/Defer.h" #include "swift/Basic/ExternalUnion.h" #include "swift/Basic/MathUtils.h" #include "swift/Basic/Range.h" #include "swift/Basic/LLVM.h" #include "swift/ABI/TypeIdentity.h" #include "swift/Runtime/ExistentialContainer.h" #include "swift/Runtime/HeapObject.h" #include "swift/Basic/Unreachable.h" #include #include #include namespace swift { namespace remote { template using FunctionParam = swift::Demangle::FunctionParam; template using TypeDecoder = swift::Demangle::TypeDecoder; /// The kind of mangled name to read. enum class MangledNameKind { Type, Symbol, }; /// A pointer to the local buffer of an object that also remembers the /// address at which it was stored remotely. template class RemoteRef { private: uint64_t Address; const T *LocalBuffer; public: RemoteRef() : Address(0), LocalBuffer(nullptr) {} /*implicit*/ RemoteRef(std::nullptr_t _) : RemoteRef() {} template explicit RemoteRef(StoredPointer address, const T *localBuffer) : Address((uint64_t)address), LocalBuffer(localBuffer) {} // Some versions of clang++ sometimes fail to generate the // copy constructor for this type correctly - add a workaround RemoteRef(const RemoteRef &other) : Address(other.Address), LocalBuffer(other.LocalBuffer) {} RemoteRef& operator=(const RemoteRef &other) { Address = other.Address; LocalBuffer = other.LocalBuffer; return *this; } uint64_t getAddressData() const { return Address; } const T *getLocalBuffer() const { return LocalBuffer; } explicit operator bool() const { return LocalBuffer != nullptr; } const T *operator->() const { assert(LocalBuffer); return LocalBuffer; } bool operator==(RemoteRef other) const { return Address == other.Address; } bool operator!=(RemoteRef other) const { return !operator==(other); } /// Project a reference for a field. The field must be projected from the same /// LocalBuffer pointer as this RemoteRef. template RemoteRef getField(U &field) const { auto offset = (intptr_t)&field - (intptr_t)LocalBuffer; return RemoteRef((uint64_t)(Address + (int64_t)offset), &field); } /// Resolve the remote address of a relative offset stored at the remote address. uint64_t resolveRelativeAddressData() const { int32_t offset; memcpy(&offset, LocalBuffer, sizeof(int32_t)); if (offset == 0) return 0; return Address + (int64_t)offset; } template uint64_t resolveRelativeFieldData(U &field) const { return getField(field).resolveRelativeAddressData(); } RemoteRef atByteOffset(int64_t Offset) const { return RemoteRef(Address + Offset, (const T *)((intptr_t)LocalBuffer + Offset)); } }; /// A structure, designed for use with std::unique_ptr, which destroys /// a pointer by calling free on it (and not trying to call a destructor). struct delete_with_free { void operator()(const void *memory) { free(const_cast(memory)); } }; /// A structure representing an opened existential type. struct RemoteExistential { /// The payload's concrete type metadata. RemoteAddress MetadataAddress; /// The address of the payload value. RemoteAddress PayloadAddress; /// True if this is an NSError instance transparently bridged to an Error /// existential. bool IsBridgedError; RemoteExistential(RemoteAddress MetadataAddress, RemoteAddress PayloadAddress, bool IsBridgedError=false) : MetadataAddress(MetadataAddress), PayloadAddress(PayloadAddress), IsBridgedError(IsBridgedError) {} }; /// A generic reader of metadata. /// /// BuilderType must implement a particular interface which is currently /// too fluid to allow useful documentation; consult the actual /// implementations. The chief thing is that it provides several member /// types which should obey the following constraints: /// - T() yields a value which is false when contextually converted to bool /// - a false value signals that an error occurred when building a value template class MetadataReader { public: using BuiltType = typename BuilderType::BuiltType; using BuiltTypeDecl = typename BuilderType::BuiltTypeDecl; using BuiltProtocolDecl = typename BuilderType::BuiltProtocolDecl; using BuiltRequirement = typename BuilderType::BuiltRequirement; using BuiltSubstitution = typename BuilderType::BuiltSubstitution; using BuiltSubstitutionMap = typename BuilderType::BuiltSubstitutionMap; using BuiltGenericSignature = typename BuilderType::BuiltGenericSignature; using StoredPointer = typename Runtime::StoredPointer; using StoredSignedPointer = typename Runtime::StoredSignedPointer; using StoredSize = typename Runtime::StoredSize; using TargetClassMetadata = TargetClassMetadataType; static const int defaultTypeRecursionLimit = 50; private: /// The maximum number of bytes to read when reading metadata. Anything larger /// will automatically return failure. This prevents us from reading absurd /// amounts of data when we encounter corrupt values for sizes/counts. static const uint64_t MaxMetadataSize = 1048576; // 1MB /// The dense map info for a std::pair. struct DenseMapInfoTypeCacheKey { using Pair = std::pair; using StoredPointerInfo = llvm::DenseMapInfo; static inline Pair getEmptyKey() { // Since bool doesn't have an empty key implementation, we only use the // StoredPointer's empty key. return std::make_pair(StoredPointerInfo::getEmptyKey(), false); } static inline Pair getTombstoneKey() { // Since bool doesn't have a tombstone key implementation, we only use the // StoredPointer's tombstone key. return std::make_pair(StoredPointerInfo::getTombstoneKey(), false); } static unsigned getHashValue(const Pair &PairVal) { return llvm::hash_combine(PairVal.first, PairVal.second); } static bool isEqual(const Pair &LHS, const Pair &RHS) { return LHS.first == RHS.first && LHS.second == RHS.second; } }; /// A cache of built types, keyed by the address of the type and whether the /// request ignored articial superclasses or not. llvm::DenseMap, BuiltType, DenseMapInfoTypeCacheKey> TypeCache; using MetadataRef = RemoteRef>; using OwnedMetadataRef = MemoryReader::ReadBytesResult; /// A cache of read type metadata, keyed by the address of the metadata. llvm::DenseMap MetadataCache; using ContextDescriptorRef = RemoteRef>; using OwnedContextDescriptorRef = MemoryReader::ReadBytesResult; using ShapeRef = RemoteRef>; using OwnedShapeRef = MemoryReader::ReadBytesResult; /// A reference to a context descriptor that may be in an unloaded image. class ParentContextDescriptorRef { bool IsResolved; using Payloads = ExternalUnionMembers; static typename Payloads::Index getPayloadIndex(bool IsResolved) { return IsResolved ? Payloads::template indexOf() : Payloads::template indexOf(); } ExternalUnion Payload; public: explicit ParentContextDescriptorRef(StringRef Symbol) : IsResolved(false) { Payload.template emplace(IsResolved, Symbol); } explicit ParentContextDescriptorRef(ContextDescriptorRef Resolved) : IsResolved(true) { Payload.template emplace(IsResolved, Resolved); } ParentContextDescriptorRef() : ParentContextDescriptorRef(ContextDescriptorRef()) {} ParentContextDescriptorRef(const ParentContextDescriptorRef &o) : IsResolved(o.IsResolved) { Payload.copyConstruct(IsResolved, o.Payload); } ParentContextDescriptorRef(ParentContextDescriptorRef &&o) : IsResolved(o.IsResolved) { Payload.moveConstruct(IsResolved, std::move(o.Payload)); } ~ParentContextDescriptorRef() { Payload.destruct(IsResolved); } ParentContextDescriptorRef &operator=(const ParentContextDescriptorRef &o) { Payload.copyAssign(IsResolved, o.IsResolved, o.Payload); IsResolved = o.isResolved(); return *this; } ParentContextDescriptorRef &operator=(ParentContextDescriptorRef &&o) { Payload.moveAssign(IsResolved, o.IsResolved, std::move(o.Payload)); IsResolved = o.isResolved(); return *this; } bool isResolved() const { return IsResolved; } StringRef getSymbol() const { return Payload.template get(IsResolved); } ContextDescriptorRef getResolved() const { return Payload.template get(IsResolved); } explicit operator bool() const { return !isResolved() || getResolved(); } }; /// A cache of read nominal type descriptors, keyed by the address of the /// nominal type descriptor. llvm::DenseMap ContextDescriptorCache; using OwnedProtocolDescriptorRef = std::unique_ptr, delete_with_free>; /// A cache of read extended existential shape metadata, keyed by the /// address of the shape metadata. llvm::DenseMap ShapeCache; enum class IsaEncodingKind { /// We haven't checked yet. Unknown, /// There was an error trying to find out the isa encoding. Error, /// There's no special isa encoding. None, /// There's an unconditional mask to apply to the isa pointer. /// - IsaMask stores the mask. Masked, /// Isa pointers are indexed. If applying a mask yields a magic value, /// applying a different mask and shifting yields an index into a global /// array of class pointers. Otherwise, the isa pointer is just a raw /// class pointer. /// - IsaIndexMask stores the index mask. /// - IsaIndexShift stores the index shift. /// - IsaMagicMask stores the magic value mask. /// - IsaMagicValue stores the magic value. /// - IndexedClassesPointer stores the pointer to the start of the /// indexed classes array; this is constant throughout the program. /// - IndexedClassesCountPointer stores a pointer to the number /// of elements in the indexed classes array. Indexed }; IsaEncodingKind IsaEncoding = IsaEncodingKind::Unknown; union { StoredPointer IsaMask; StoredPointer IsaIndexMask; }; StoredPointer IsaIndexShift; StoredPointer IsaMagicMask; StoredPointer IsaMagicValue; StoredPointer IndexedClassesPointer; StoredPointer IndexedClassesCountPointer; StoredPointer LastIndexedClassesCount = 0; enum class TaggedPointerEncodingKind { /// We haven't checked yet. Unknown, /// There was an error trying to find out the tagged pointer encoding. Error, /// The "extended" encoding. /// /// 1 bit: is-tagged /// 3 bits: class index (for objc_debug_taggedpointer_classes[]) /// 60 bits: payload /// /// Class index 0b111 represents 256 additional classes: /// /// 1 bit: is-tagged /// 3 bits: 0b111 /// 8 bits: extended class index (for objc_debug_taggedpointer_ext_classes[]) /// 54 bits: payload Extended }; TaggedPointerEncodingKind TaggedPointerEncoding = TaggedPointerEncodingKind::Unknown; StoredPointer TaggedPointerMask; StoredPointer TaggedPointerSlotShift; StoredPointer TaggedPointerSlotMask; StoredPointer TaggedPointerClasses; StoredPointer TaggedPointerExtendedMask; StoredPointer TaggedPointerExtendedSlotShift; StoredPointer TaggedPointerExtendedSlotMask; StoredPointer TaggedPointerExtendedClasses; StoredPointer TaggedPointerObfuscator; Demangle::NodeFactory Factory; Demangle::NodeFactory &getNodeFactory() { return Factory; } public: BuilderType Builder; BuilderType &getBuilder() { return this->Builder; } std::shared_ptr Reader; StoredPointer PtrAuthMask; StoredPointer stripSignedPointer(StoredSignedPointer P) { return P.SignedValue & PtrAuthMask; } RemoteAbsolutePointer stripSignedPointer(const RemoteAbsolutePointer &P) { if (P.isResolved()) { return RemoteAbsolutePointer("", P.getResolvedAddress().getAddressData() & PtrAuthMask); } return P; } StoredPointer queryPtrAuthMask() { StoredPointer QueryResult; if (Reader->queryDataLayout(DataLayoutQueryType::DLQ_GetPtrAuthMask, nullptr, &QueryResult)) { return QueryResult; } return ~StoredPointer(0); } template MetadataReader(std::shared_ptr reader, T &&... args) : Builder(std::forward(args)...), Reader(std::move(reader)), PtrAuthMask(queryPtrAuthMask()) { } MetadataReader(const MetadataReader &other) = delete; MetadataReader &operator=(const MetadataReader &other) = delete; /// Clear all of the caches in this reader. void clear() { TypeCache.clear(); MetadataCache.clear(); ContextDescriptorCache.clear(); } /// Demangle a mangled name that was read from the given remote address. Demangle::NodePointer demangle(RemoteRef mangledName, MangledNameKind kind, Demangler &dem, bool useOpaqueTypeSymbolicReferences = false) { // Symbolic reference resolver for the demangle operation below. auto symbolicReferenceResolver = [&](SymbolicReferenceKind kind, Directness directness, int32_t offset, const void *base) -> swift::Demangle::NodePointer { // Resolve the reference to a remote address. auto offsetInMangledName = (const char *)base - mangledName.getLocalBuffer(); auto remoteAddress = mangledName.getAddressData() + offsetInMangledName + offset; RemoteAbsolutePointer resolved; if (directness == Directness::Indirect) { if (auto indirectAddress = readPointer(remoteAddress)) { resolved = stripSignedPointer(*indirectAddress); } else { return nullptr; } } else { resolved = Reader->getSymbol(RemoteAddress(remoteAddress)); } switch (kind) { case Demangle::SymbolicReferenceKind::Context: { auto context = readContextDescriptor(resolved); if (!context) return nullptr; // Try to preserve a reference to an OpaqueTypeDescriptor // symbolically, since we'd like to read out and resolve the type ref // to the underlying type if available. if (useOpaqueTypeSymbolicReferences && context.isResolved() && context.getResolved()->getKind() == ContextDescriptorKind::OpaqueType){ return dem.createNode( Node::Kind::OpaqueTypeDescriptorSymbolicReference, context.getResolved().getAddressData()); } return buildContextMangling(context, dem); } case Demangle::SymbolicReferenceKind::AccessorFunctionReference: { // The symbolic reference points at a resolver function, but we can't // execute code in the target process to resolve it from here. return nullptr; } case Demangle::SymbolicReferenceKind::UniqueExtendedExistentialTypeShape: { // The symbolic reference points at a unique extended // existential type shape. return dem.createNode( Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference, resolved.getResolvedAddress().getAddressData()); } case Demangle::SymbolicReferenceKind::NonUniqueExtendedExistentialTypeShape: { // The symbolic reference points at a non-unique extended // existential type shape. return dem.createNode( Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference, resolved.getResolvedAddress().getAddressData()); } case Demangle::SymbolicReferenceKind::ObjectiveCProtocol: { // 'resolved' points to a struct of two relative addresses. // The second entry is a relative address to the mangled protocol // without symbolic references. // lldb might return an unresolved remote absolute pointer from its // resolvePointerAsSymbol implementation -- workaround this. if (!resolved.isResolved()) { auto remoteAddr = RemoteAddress(remoteAddress); resolved = RemoteAbsolutePointer("", remoteAddr.getAddressData()); } auto addr = resolved.getResolvedAddress().getAddressData() + sizeof(int32_t); int32_t offset; Reader->readInteger(RemoteAddress(addr), &offset); auto addrOfTypeRef = addr + offset; resolved = Reader->getSymbol(RemoteAddress(addrOfTypeRef)); // lldb might return an unresolved remote absolute pointer from its // resolvePointerAsSymbol implementation -- workaround this. if (!resolved.isResolved()) { auto remoteAddr = RemoteAddress(addrOfTypeRef); resolved = RemoteAbsolutePointer("", remoteAddr.getAddressData()); } // Dig out the protocol from the protocol list. auto protocolList = readMangledName(resolved.getResolvedAddress(), MangledNameKind::Type, dem); assert(protocolList && protocolList->getNumChildren()); if (!protocolList || !protocolList->getNumChildren()) return nullptr; auto child = protocolList->getFirstChild(); assert(child && child->getNumChildren()); if (!child || !child->getNumChildren()) return nullptr; child = child->getFirstChild(); assert(child && child->getNumChildren()); if (!child || !child->getNumChildren()) return nullptr; assert(child && child->getNumChildren()); child = child->getFirstChild(); if (!child || !child->getNumChildren()) return nullptr; child = child->getFirstChild(); assert(child && child->getKind() == Node::Kind::Protocol); if (!child || child->getKind() != Node::Kind::Protocol) return nullptr; auto protocol = child; auto protocolType = dem.createNode(Node::Kind::Type); protocolType->addChild(protocol, dem); return protocolType; } } return nullptr; }; auto mangledNameStr = Demangle::makeSymbolicMangledNameStringRef(mangledName.getLocalBuffer()); swift::Demangle::NodePointer result; switch (kind) { case MangledNameKind::Type: result = dem.demangleType(mangledNameStr, symbolicReferenceResolver); break; case MangledNameKind::Symbol: result = dem.demangleSymbol(mangledNameStr, symbolicReferenceResolver); break; } return result; } /// Demangle a mangled name from a potentially temporary std::string. The /// demangler may produce pointers into the string data, so this copies the /// string into the demangler's allocation first. Demangle::NodePointer demangle(uint64_t remoteAddress, const std::string &mangledName, MangledNameKind kind, Demangler &dem) { StringRef mangledNameCopy = dem.copyString(mangledName); return demangle(RemoteRef(remoteAddress, mangledNameCopy.data()), kind, dem); } /// Given a demangle tree, attempt to turn it into a type. TypeLookupErrorOr decodeMangledType(NodePointer Node) { return swift::Demangle::decodeMangledType(Builder, Node); } /// Get the remote process's swift_isaMask. std::optional readIsaMask() { auto encoding = getIsaEncoding(); if (encoding != IsaEncodingKind::Masked) { // Still return success if there's no isa encoding at all. if (encoding == IsaEncodingKind::None) return 0; else return std::nullopt; } return IsaMask; } /// Given a remote pointer to metadata, attempt to discover its MetadataKind. std::optional readKindFromMetadata(StoredPointer MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta) return std::nullopt; return meta->getKind(); } /// Given a remote pointer to class metadata, attempt to read its superclass. StoredPointer readSuperClassFromClassMetadata(StoredPointer MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta || meta->getKind() != MetadataKind::Class) return StoredPointer(); auto classMeta = cast(meta); return stripSignedPointer(classMeta->Superclass); } /// Given a remote pointer to class metadata, attempt to discover its class /// instance size and whether fields should use the resilient layout strategy. std::optional readInstanceStartFromClassMetadata(StoredPointer MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta || meta->getKind() != MetadataKind::Class) return std::nullopt; if (Runtime::ObjCInterop) { // The following algorithm only works on the non-fragile Apple runtime. // Grab the RO-data pointer. This part is not ABI. StoredPointer roDataPtr = readObjCRODataPtr(MetadataAddress); if (!roDataPtr) return std::nullopt; // Get the address of the InstanceStart field. auto address = roDataPtr + sizeof(uint32_t) * 1; unsigned start; if (!Reader->readInteger(RemoteAddress(address), &start)) return std::nullopt; return start; } else { // All swift class instances start with an isa pointer, // followed by the retain counts (which are the size of a long long). size_t isaAndRetainCountSize = sizeof(StoredSize) + sizeof(long long); size_t start = isaAndRetainCountSize; auto classMeta = cast(meta); while (stripSignedPointer(classMeta->Superclass)) { meta = readMetadata(stripSignedPointer(classMeta->Superclass)); if (!meta || meta->getKind() != MetadataKind::Class) return std::nullopt; classMeta = cast(meta); // Subtract the size contribution of the isa and retain counts from // the super class. start += classMeta->InstanceSize - isaAndRetainCountSize; } return start; } } /// Given a pointer to the metadata, attempt to read the value /// witness table. Note that it's not safe to access any non-mandatory /// members of the value witness table, like extra inhabitants or enum members. std::optional> readValueWitnessTable(StoredPointer MetadataAddress) { // The value witness table pointer is at offset -1 from the metadata // pointer, that is, the pointer-sized word immediately before the // pointer's referenced address. TargetValueWitnessTable VWT; auto ValueWitnessTableAddrAddr = MetadataAddress - sizeof(StoredPointer); StoredSignedPointer SignedValueWitnessTableAddr; if (!Reader->readInteger(RemoteAddress(ValueWitnessTableAddrAddr), &SignedValueWitnessTableAddr)) return std::nullopt; auto ValueWitnessTableAddr = stripSignedPointer(SignedValueWitnessTableAddr); if (!Reader->readBytes(RemoteAddress(ValueWitnessTableAddr), (uint8_t *)&VWT, sizeof(VWT))) return std::nullopt; return VWT; } /// Given a pointer to a known-error existential, attempt to discover the /// pointer to its metadata address, its value address, and whether this /// is a toll-free-bridged NSError or an actual Error existential wrapper /// around a native Swift value. std::optional readMetadataAndValueErrorExistential(RemoteAddress ExistentialAddress) { // An pointer to an error existential is always an heap object. auto MetadataAddress = readMetadataFromInstance(ExistentialAddress.getAddressData()); if (!MetadataAddress) return std::nullopt; bool isObjC = false; bool isBridged = false; auto Meta = readMetadata(*MetadataAddress); if (!Meta) return std::nullopt; if (auto ClassMeta = dyn_cast(Meta)) { if (ClassMeta->isPureObjC()) { // If we can determine the Objective-C class name, this is probably an // error existential with NSError-compatible layout. std::string ObjCClassName; if (readObjCClassName(*MetadataAddress, ObjCClassName)) { if (ObjCClassName == "__SwiftNativeNSError") isObjC = true; else isBridged = true; } } else { isBridged = true; } } if (isBridged) { // NSError instances don't need to be unwrapped. return RemoteExistential(RemoteAddress(*MetadataAddress), ExistentialAddress, isBridged); } // In addition to the isa pointer and two 32-bit reference counts, if the // error existential is layout-compatible with NSError, we also need to // skip over its three word-sized fields: the error code, the domain, // and userInfo. StoredPointer InstanceMetadataAddressAddress = ExistentialAddress.getAddressData() + (isObjC ? 5 : 2) * sizeof(StoredPointer); // We need to get the instance's alignment info so we can get the exact // offset of the start of its data in the class. auto InstanceMetadataAddress = readMetadataFromInstance(InstanceMetadataAddressAddress); if (!InstanceMetadataAddress) return std::nullopt; // Read the value witness table. auto VWT = readValueWitnessTable(*InstanceMetadataAddress); if (!VWT) return std::nullopt; // Now we need to skip over the instance metadata pointer and instance's // conformance pointer for Swift.Error. StoredPointer InstanceAddress = InstanceMetadataAddressAddress + 2 * sizeof(StoredPointer); // When built with Objective-C interop, the runtime also stores a conformance // to Hashable and the base type introducing the Hashable conformance. if (isObjC) InstanceAddress += 2 * sizeof(StoredPointer); // Round up to alignment, and we have the start address of the // instance payload. auto AlignmentMask = VWT->getAlignmentMask(); InstanceAddress = (InstanceAddress + AlignmentMask) & ~AlignmentMask; return RemoteExistential( RemoteAddress(*InstanceMetadataAddress), RemoteAddress(InstanceAddress), isBridged); } /// Given a known-opaque existential, attempt to discover the pointer to its /// metadata address and its value. std::optional readMetadataAndValueOpaqueExistential(RemoteAddress ExistentialAddress) { // OpaqueExistentialContainer is the layout of an opaque existential. // `Type` is the pointer to the metadata. TargetOpaqueExistentialContainer Container; if (!Reader->readBytes(RemoteAddress(ExistentialAddress), (uint8_t *)&Container, sizeof(Container))) return std::nullopt; auto MetadataAddress = static_cast(Container.Type); auto Metadata = readMetadata(MetadataAddress); if (!Metadata) return std::nullopt; auto VWT = readValueWitnessTable(MetadataAddress); if (!VWT) return std::nullopt; // Inline representation (the value fits in the existential container). // So, the value starts at the first word of the container. if (VWT->isValueInline()) return RemoteExistential(RemoteAddress(MetadataAddress), ExistentialAddress); // Non-inline (box'ed) representation. // The first word of the container stores the address to the box. StoredPointer BoxAddress; if (!Reader->readInteger(ExistentialAddress, &BoxAddress)) return std::nullopt; auto AlignmentMask = VWT->getAlignmentMask(); auto Offset = (sizeof(HeapObject) + AlignmentMask) & ~AlignmentMask; auto StartOfValue = BoxAddress + Offset; return RemoteExistential(RemoteAddress(MetadataAddress), RemoteAddress(StartOfValue)); } /// Given a known-opaque existential, discover if its value is inlined in /// the existential container. std::optional isValueInlinedInExistentialContainer(RemoteAddress ExistentialAddress) { // OpaqueExistentialContainer is the layout of an opaque existential. // `Type` is the pointer to the metadata. TargetOpaqueExistentialContainer Container; if (!Reader->readBytes(RemoteAddress(ExistentialAddress), (uint8_t *)&Container, sizeof(Container))) return std::nullopt; auto MetadataAddress = static_cast(Container.Type); auto Metadata = readMetadata(MetadataAddress); if (!Metadata) return std::nullopt; auto VWT = readValueWitnessTable(MetadataAddress); if (!VWT) return std::nullopt; return VWT->isValueInline(); } /// Read a protocol from a reference to said protocol. template typename Resolver::Result readProtocol( const TargetProtocolDescriptorRef &ProtocolAddress, Demangler &dem, Resolver resolver) { #if SWIFT_OBJC_INTEROP if (Runtime::ObjCInterop) { // Check whether we have an Objective-C protocol. if (ProtocolAddress.isObjC()) { auto Name = readObjCProtocolName(ProtocolAddress.getObjCProtocol()); StringRef NameStr(Name); // If this is a Swift-defined protocol, demangle it. if (NameStr.starts_with("_TtP")) { auto Demangled = dem.demangleSymbol(NameStr); if (!Demangled) return resolver.failure(); // FIXME: This appears in _swift_buildDemanglingForMetadata(). while (Demangled->getKind() == Node::Kind::Global || Demangled->getKind() == Node::Kind::TypeMangling || Demangled->getKind() == Node::Kind::Type || Demangled->getKind() == Node::Kind::ProtocolList || Demangled->getKind() == Node::Kind::TypeList || Demangled->getKind() == Node::Kind::Type) { if (Demangled->getNumChildren() != 1) return resolver.failure(); Demangled = Demangled->getFirstChild(); } return resolver.swiftProtocol(Demangled); } // Otherwise, this is an imported protocol. return resolver.objcProtocol(NameStr); } } #endif // Swift-native protocol. auto Demangled = readDemanglingForContextDescriptor( stripSignedPointer({ProtocolAddress.getSwiftProtocol()}), dem); if (!Demangled) return resolver.failure(); return resolver.swiftProtocol(Demangled); } /// Given a remote pointer to metadata, attempt to turn it into a type. BuiltType readTypeFromMetadata(StoredPointer MetadataAddress, bool skipArtificialSubclasses = false, int recursion_limit = defaultTypeRecursionLimit) { std::pair TypeCacheKey(MetadataAddress, skipArtificialSubclasses); auto Cached = TypeCache.find(TypeCacheKey); if (Cached != TypeCache.end()) return Cached->second; if (recursion_limit <= 0) { return nullptr; } // readTypeFromMetadata calls out to various other functions which can call // back to readTypeFromMetadata. We only want to bump the recursion limit // down here, not in the other functions, so that we're only counting // recursive calls to readTypeFromMetadata. This decrement is the only place // where we'll subtract 1. recursion_limit--; // If we see garbage data in the process of building a BuiltType, and get // the same metadata address again, we will hit an infinite loop. // Insert a negative result into the cache now so that, if we recur with // the same address, we will return the negative result with the check // just above. TypeCache.insert({TypeCacheKey, BuiltType()}); auto Meta = readMetadata(MetadataAddress); if (!Meta) return BuiltType(); switch (Meta->getKind()) { case MetadataKind::Class: return readNominalTypeFromClassMetadata(Meta, recursion_limit, skipArtificialSubclasses); case MetadataKind::Struct: case MetadataKind::Enum: case MetadataKind::Optional: return readNominalTypeFromMetadata(Meta, recursion_limit); case MetadataKind::Tuple: { auto tupleMeta = cast>(Meta); std::vector elementTypes; elementTypes.reserve(tupleMeta->NumElements); for (unsigned i = 0, n = tupleMeta->NumElements; i != n; ++i) { auto &element = tupleMeta->getElement(i); if (auto elementType = readTypeFromMetadata(element.Type, false, recursion_limit)) elementTypes.push_back(elementType); else return BuiltType(); } // Read the labels string. std::string labelStr; if (tupleMeta->Labels && !Reader->readString(RemoteAddress(tupleMeta->Labels), labelStr)) return BuiltType(); std::vector labels; std::string::size_type end, start = 0; while (true) { end = labelStr.find(' ', start); if (end == std::string::npos) break; labels.push_back(llvm::StringRef(labelStr.data() + start, end - start)); start = end + 1; } // Pad the vector with empty labels. for (unsigned i = labels.size(); i < elementTypes.size(); ++i) labels.push_back(StringRef()); auto BuiltTuple = Builder.createTupleType(elementTypes, labels); TypeCache[TypeCacheKey] = BuiltTuple; return BuiltTuple; } case MetadataKind::Function: { auto Function = cast>(Meta); std::vector> Parameters; for (unsigned i = 0, n = Function->getNumParameters(); i != n; ++i) { auto ParamTypeRef = readTypeFromMetadata(Function->getParameter(i), false, recursion_limit); if (!ParamTypeRef) return BuiltType(); FunctionParam Param; Param.setType(ParamTypeRef); Param.setFlags(Function->getParameterFlags(i)); Parameters.push_back(std::move(Param)); } auto Result = readTypeFromMetadata(Function->ResultType, false, recursion_limit); if (!Result) return BuiltType(); auto flags = FunctionTypeFlags::fromIntValue(Function->Flags.getIntValue()); auto extFlags = ExtendedFunctionTypeFlags(); if (flags.hasExtendedFlags()) extFlags = ExtendedFunctionTypeFlags::fromIntValue( Function->getExtendedFlags().getIntValue()); BuiltType globalActor = BuiltType(); if (Function->hasGlobalActor()) { globalActor = readTypeFromMetadata(Function->getGlobalActor(), false, recursion_limit); if (!globalActor) return BuiltType(); } FunctionMetadataDifferentiabilityKind diffKind; switch (Function->getDifferentiabilityKind().Value) { #define CASE(X) \ case TargetFunctionMetadataDifferentiabilityKind< \ typename Runtime::StoredSize>::X: \ diffKind = FunctionMetadataDifferentiabilityKind::X; \ break; CASE(NonDifferentiable) CASE(Forward) CASE(Reverse) CASE(Normal) CASE(Linear) #undef CASE } BuiltType thrownError = BuiltType(); if (Function->hasThrownError()) { thrownError = readTypeFromMetadata(Function->getThrownError(), false, recursion_limit); if (!thrownError) return BuiltType(); } auto BuiltFunction = Builder.createFunctionType( Parameters, Result, flags, extFlags, diffKind, globalActor, thrownError); TypeCache[TypeCacheKey] = BuiltFunction; return BuiltFunction; } case MetadataKind::Existential: { auto Exist = cast>(Meta); bool HasExplicitAnyObject = false; if (Exist->isClassBounded()) HasExplicitAnyObject = true; BuiltType SuperclassType = BuiltType(); if (Exist->Flags.hasSuperclassConstraint()) { // The superclass is stored after the list of protocols. SuperclassType = readTypeFromMetadata(Exist->getSuperclassConstraint(), false, recursion_limit); if (!SuperclassType) return BuiltType(); HasExplicitAnyObject = true; } /// Resolver to turn a protocol reference into a protocol declaration. struct ProtocolResolver { using Result = BuiltProtocolDecl; BuilderType &builder; BuiltProtocolDecl failure() const { return BuiltProtocolDecl(); } BuiltProtocolDecl swiftProtocol(Demangle::Node *node) { return builder.createProtocolDecl(node); } #if SWIFT_OBJC_INTEROP BuiltProtocolDecl objcProtocol(StringRef name) { return builder.createObjCProtocolDecl(name.str()); } #endif } resolver{Builder}; Demangler dem; std::vector Protocols; for (auto ProtocolAddress : Exist->getProtocols()) { if (auto Protocol = readProtocol(ProtocolAddress, dem, resolver)) Protocols.push_back(Protocol); else return BuiltType(); } auto BuiltExist = Builder.createProtocolCompositionType( Protocols, SuperclassType, HasExplicitAnyObject); TypeCache[TypeCacheKey] = BuiltExist; return BuiltExist; } case MetadataKind::ExtendedExistential: { auto Exist = cast>(Meta); // Read the shape for this existential. StoredPointer shapeAddress = stripSignedPointer(Exist->Shape); ShapeRef Shape = readShape(shapeAddress); if (!Shape) return BuiltType(); const unsigned shapeArgumentCount = Shape->getGenSigArgumentLayoutSizeInWords(); // Pull out the arguments to the generalization signature. assert(Shape->hasGeneralizationSignature()); std::vector builtArgs; for (unsigned i = 0; i < shapeArgumentCount; ++i) { auto remoteArg = Exist->getGeneralizationArguments()[i]; auto builtArg = readTypeFromMetadata(remoteArg, false, recursion_limit); if (!builtArg) return BuiltType(); builtArgs.push_back(builtArg); } // Pull out the existential type from the mangled type name. Demangler dem; auto mangledExistentialAddr = resolveRelativeField(Shape, Shape->ExistentialType); auto node = readMangledName(RemoteAddress(mangledExistentialAddr), MangledNameKind::Type, dem); if (!node) return BuiltType(); BuiltType builtProto = decodeMangledType(node).getType(); if (!builtProto) return BuiltType(); // Build up a substitution map for the generalized signature. BuiltGenericSignature sig = decodeRuntimeGenericSignature(Shape, Shape->getGeneralizationSignature()) .getType(); if (!sig) return BuiltType(); BuiltSubstitutionMap subst = Builder.createSubstitutionMap(sig, builtArgs); if (subst.empty()) return BuiltType(); builtProto = Builder.subst(builtProto, subst); if (!builtProto) return BuiltType(); // Read the type expression to build up any remaining layers of // existential metatype. if (Shape->Flags.hasTypeExpression()) { Demangler dem; // Read the mangled name. auto mangledContextName = Shape->getTypeExpression(); auto mangledNameAddress = resolveRelativeField(Shape, mangledContextName->name); auto node = readMangledName(RemoteAddress(mangledNameAddress), MangledNameKind::Type, dem); if (!node) return BuiltType(); while (node->getKind() == Demangle::Node::Kind::Type && node->getNumChildren() && node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype && node->getChild(0)->getNumChildren()) { builtProto = Builder.createExistentialMetatypeType(builtProto); node = node->getChild(0)->getChild(0); } } TypeCache[TypeCacheKey] = builtProto; return builtProto; } case MetadataKind::Metatype: { auto Metatype = cast>(Meta); auto Instance = readTypeFromMetadata(Metatype->InstanceType, false, recursion_limit); if (!Instance) return BuiltType(); auto BuiltMetatype = Builder.createMetatypeType(Instance); TypeCache[TypeCacheKey] = BuiltMetatype; return BuiltMetatype; } case MetadataKind::ObjCClassWrapper: { auto objcWrapper = cast>(Meta); auto classAddress = objcWrapper->Class; std::string className; if (!readObjCClassName(classAddress, className)) return BuiltType(); auto BuiltObjCClass = Builder.createObjCClassType(std::move(className)); TypeCache[TypeCacheKey] = BuiltObjCClass; return BuiltObjCClass; } case MetadataKind::ExistentialMetatype: { auto Exist = cast>(Meta); auto Instance = readTypeFromMetadata(Exist->InstanceType, false, recursion_limit); if (!Instance) return BuiltType(); auto BuiltExist = Builder.createExistentialMetatypeType(Instance); TypeCache[TypeCacheKey] = BuiltExist; return BuiltExist; } case MetadataKind::ForeignReferenceType: case MetadataKind::ForeignClass: { auto descriptorAddr = readAddressOfNominalTypeDescriptor(Meta); if (!descriptorAddr) return BuiltType(); auto descriptor = readContextDescriptor(descriptorAddr); if (!descriptor) return BuiltType(); // Build the demangling tree from the context tree. Demangler dem; auto node = buildContextMangling(descriptor, dem); if (!node || node->getKind() != Node::Kind::Type) return BuiltType(); auto mangling = Demangle::mangleNode(node, Mangle::ManglingFlavor::Default); if (!mangling.isSuccess()) return BuiltType(); auto name = mangling.result(); auto BuiltForeign = Builder.createForeignClassType(std::move(name)); TypeCache[TypeCacheKey] = BuiltForeign; return BuiltForeign; } case MetadataKind::HeapLocalVariable: case MetadataKind::HeapGenericLocalVariable: case MetadataKind::ErrorObject: // Treat these all as Builtin.NativeObject for type lowering purposes. return Builder.createBuiltinType("Builtin.NativeObject", "Bo"); case MetadataKind::Opaque: default: { auto BuiltOpaque = Builder.getOpaqueType(); TypeCache[TypeCacheKey] = BuiltOpaque; return BuiltOpaque; } } swift_unreachable("Unhandled MetadataKind in switch"); } TypeLookupErrorOr decodeRuntimeGenericSignature(ShapeRef contextRef, const RuntimeGenericSignature &Sig) { std::vector params; for (unsigned sigIdx : indices(Sig.getParams())) { auto param = Builder.createGenericTypeParameterType(/*depth*/ 0, /*index*/ sigIdx); if (!param) return TypeLookupError("Failed to read generic parameter type in " "runtime generic signature."); params.push_back(param); } std::vector reqs; for (auto &req : Sig.getRequirements()) { if (!req.hasKnownKind()) { return TypeLookupError("unknown kind"); } Demangler ldem; auto lhsTypeNode = ldem.demangleType(req.getParam()); if (!lhsTypeNode) { return TypeLookupError("Failed to read subject type in requirement of " "runtime generic signature."); } BuiltType subjectType = decodeMangledType(lhsTypeNode).getType(); if (!subjectType) return TypeLookupError("Failed to read subject type in requirement of " "runtime generic signature."); switch (req.Flags.getKind()) { case GenericRequirementKind::SameType: { Demangler rdem; auto demangledConstraint = demangle(RemoteRef(req.getMangledTypeName().data(), req.getMangledTypeName().data()), MangledNameKind::Type, rdem); auto constraintType = decodeMangledType(demangledConstraint); if (auto *error = constraintType.getError()) { return *error; } reqs.push_back(BuiltRequirement(RequirementKind::SameType, subjectType, constraintType.getType())); break; } case GenericRequirementKind::Protocol: { /// Resolver to turn a protocol reference into an existential type. struct ProtocolReferenceResolver { using Result = BuiltType; BuilderType &builder; BuiltType failure() const { return BuiltType(); } BuiltType swiftProtocol(Demangle::Node *node) { auto decl = builder.createProtocolDecl(node); if (!decl) return failure(); return builder.createProtocolTypeFromDecl(decl); } #if SWIFT_OBJC_INTEROP BuiltType objcProtocol(StringRef name) { auto decl = builder.createObjCProtocolDecl(name.str()); if (!decl) return failure(); return builder.createProtocolTypeFromDecl(decl); } #endif } resolver{Builder}; Demangler dem; auto protocolAddress = resolveRelativeIndirectProtocol(contextRef, req.Protocol); auto protocol = readProtocol(protocolAddress, dem, resolver); if (!protocol) { return TypeLookupError("Failed to read protocol type in conformance " "requirement of runtime generic signature."); } reqs.push_back(BuiltRequirement(RequirementKind::Conformance, subjectType, protocol)); break; } case GenericRequirementKind::BaseClass: { Demangler rdem; auto demangledConstraint = demangle(RemoteRef(req.getMangledTypeName().data(), req.getMangledTypeName().data()), MangledNameKind::Type, rdem); auto constraintType = decodeMangledType(demangledConstraint); if (auto *error = constraintType.getError()) { return *error; } reqs.push_back(BuiltRequirement(RequirementKind::Superclass, subjectType, constraintType.getType())); break; } case GenericRequirementKind::SameConformance: return TypeLookupError("Unexpected same conformance requirement in " "runtime generic signature"); case GenericRequirementKind::Layout: return TypeLookupError( "Unexpected layout requirement in runtime generic signature"); case GenericRequirementKind::SameShape: return TypeLookupError( "Unexpected same-shape requirement in runtime generic signature"); case GenericRequirementKind::InvertedProtocols: return TypeLookupError( "Unexpected invertible protocol in runtime generic signature"); } } return Builder.createGenericSignature(params, reqs); } TypeLookupErrorOr readTypeFromMangledName(const char *MangledTypeName, size_t Length) { Demangle::Demangler Dem; Demangle::NodePointer Demangled = Dem.demangleSymbol(StringRef(MangledTypeName, Length)); return decodeMangledType(Demangled); } /// Given the address of a context descriptor, attempt to read it, or /// represent it symbolically. ParentContextDescriptorRef readContextDescriptor(const RemoteAbsolutePointer &address) { // Map an unresolved pointer to an unresolved context ref. if (!address.isResolved()) { // We can only handle references to a symbol without an offset currently. if (address.getOffset() != 0) { return ParentContextDescriptorRef(); } return ParentContextDescriptorRef(address.getSymbol()); } return ParentContextDescriptorRef( readContextDescriptor(address.getResolvedAddress().getAddressData())); } ShapeRef readShape(StoredPointer address) { if (address == 0) return nullptr; auto cached = ShapeCache.find(address); if (cached != ShapeCache.end()) return ShapeRef(address, reinterpret_cast *>( cached->second.get())); ExtendedExistentialTypeShapeFlags flags; if (!Reader->readBytes(RemoteAddress(address), (uint8_t*)&flags, sizeof(flags))) return nullptr; // Read the size of the requirement signature. uint64_t reqSigGenericSize = 0; uint64_t genericHeaderSize = sizeof(GenericContextDescriptorHeader); { GenericContextDescriptorHeader header; auto headerAddr = address + sizeof(flags); if (!Reader->readBytes(RemoteAddress(headerAddr), (uint8_t*)&header, sizeof(header))) return nullptr; reqSigGenericSize = reqSigGenericSize + (header.NumParams + 3u & ~3u) + header.NumRequirements * sizeof(TargetGenericRequirementDescriptor); } uint64_t typeExprSize = flags.hasTypeExpression() ? sizeof(StoredPointer) : 0; uint64_t suggestedVWSize = flags.hasSuggestedValueWitnesses() ? sizeof(StoredPointer) : 0; uint64_t size = sizeof(ExtendedExistentialTypeShapeFlags) + sizeof(TargetRelativeDirectPointer) + genericHeaderSize + typeExprSize + suggestedVWSize + reqSigGenericSize; if (size > MaxMetadataSize) return nullptr; auto readResult = Reader->readBytes(RemoteAddress(address), size); if (!readResult) return nullptr; auto descriptor = reinterpret_cast *>( readResult.get()); ShapeCache.insert( std::make_pair(address, std::move(readResult))); return ShapeRef(address, descriptor); } /// Given the address of a context descriptor, attempt to read it. ContextDescriptorRef readContextDescriptor(StoredPointer address) { if (address == 0) return nullptr; auto remoteAddress = RemoteAddress(address); auto ptr = Reader->readBytes(remoteAddress, sizeof(TargetContextDescriptor)); if (!ptr) return nullptr; auto cached = ContextDescriptorCache.find(address); if (cached != ContextDescriptorCache.end()) return ContextDescriptorRef( address, reinterpret_cast *>( cached->second.get())); bool success = false; switch ( reinterpret_cast *>(ptr.get()) ->getKind()) { case ContextDescriptorKind::Module: ptr = Reader->readBytes(remoteAddress, sizeof(TargetModuleContextDescriptor)); success = ptr != nullptr; break; case ContextDescriptorKind::Extension: success = readFullContextDescriptor>( remoteAddress, ptr); break; case ContextDescriptorKind::Anonymous: success = readFullContextDescriptor>( remoteAddress, ptr); break; case ContextDescriptorKind::Class: success = readFullContextDescriptor>( remoteAddress, ptr); break; case ContextDescriptorKind::Enum: success = readFullContextDescriptor>( remoteAddress, ptr); break; case ContextDescriptorKind::Struct: success = readFullContextDescriptor>( remoteAddress, ptr); break; case ContextDescriptorKind::Protocol: success = readFullContextDescriptor>( remoteAddress, ptr); break; case ContextDescriptorKind::OpaqueType: success = readFullContextDescriptor>( remoteAddress, ptr); break; default: // We don't know about this kind of context. return nullptr; } if (!success) return nullptr; auto *descriptor = reinterpret_cast *>(ptr.get()); ContextDescriptorCache.insert(std::make_pair(address, std::move(ptr))); return ContextDescriptorRef(address, descriptor); } template bool readFullContextDescriptor(RemoteAddress address, MemoryReader::ReadBytesResult &ptr) { // Read the full base descriptor if it's bigger than what we have so far. if (sizeof(DescriptorTy) > sizeof(TargetContextDescriptor)) { ptr = Reader->readObj(address); if (!ptr) return false; } // We don't know how much memory we need to read to get all the trailing // objects, but we need to read the memory to figure out how much memory we // need to read. Handle this by reading incrementally. // // We rely on the fact that each trailing object's count depends only on // that comes before it. If we've read the first N trailing objects, then we // can safely compute the size with N+1 trailing objects. If that size is // bigger than what we've read so far, re-read the descriptor with the new // size. Once we've walked through all the trailing objects, we've read // everything. size_t sizeSoFar = sizeof(DescriptorTy); for (size_t i = 0; i < DescriptorTy::trailingTypeCount(); i++) { const DescriptorTy *descriptorSoFar = reinterpret_cast(ptr.get()); size_t thisSize = descriptorSoFar->sizeWithTrailingTypeCount(i); if (thisSize > sizeSoFar) { ptr = Reader->readBytes(address, thisSize); if (!ptr) return false; sizeSoFar = thisSize; } } return true; } /// Demangle the entity represented by a symbolic reference to a given symbol name. Demangle::NodePointer buildContextManglingForSymbol(StringRef symbol, Demangler &dem) { auto demangledSymbol = dem.demangleSymbol(symbol); if (demangledSymbol->getKind() == Demangle::Node::Kind::Global) { demangledSymbol = demangledSymbol->getChild(0); } switch (demangledSymbol->getKind()) { // Pointers to nominal type or protocol descriptors would demangle to // the type they represent. case Demangle::Node::Kind::NominalTypeDescriptor: case Demangle::Node::Kind::ProtocolDescriptor: demangledSymbol = demangledSymbol->getChild(0); assert(demangledSymbol->getKind() == Demangle::Node::Kind::Type); break; // Pointers to opaque type descriptors demangle to the name of the opaque // type declaration. case Demangle::Node::Kind::OpaqueTypeDescriptor: demangledSymbol = demangledSymbol->getChild(0); break; // We don't handle pointers to other symbols yet. default: return nullptr; } return demangledSymbol; } Demangle::NodePointer buildContextManglingForSymbol(const std::string &symbol, Demangler &dem) { return buildContextManglingForSymbol(dem.copyString(symbol), dem); } /// Given a read context descriptor, attempt to build a demangling tree /// for it. Demangle::NodePointer buildContextMangling(const ParentContextDescriptorRef &descriptor, Demangler &dem) { if (descriptor.isResolved()) { return buildContextMangling(descriptor.getResolved(), dem); } // Try to demangle the symbol name to figure out what context it would // point to. return buildContextManglingForSymbol(descriptor.getSymbol(), dem); } /// Given a read context descriptor, attempt to build a demangling tree /// for it. Demangle::NodePointer buildContextMangling(ContextDescriptorRef descriptor, Demangler &dem) { auto demangling = buildContextDescriptorMangling(descriptor, dem, 50); if (!demangling) return nullptr; Demangle::NodePointer top; // References to type nodes behave as types in the mangling. if (isa>(descriptor.getLocalBuffer()) || isa>(descriptor.getLocalBuffer())) { top = dem.createNode(Node::Kind::Type); top->addChild(demangling, dem); } else { top = demangling; } return top; } /// Read a context descriptor from the given address and build a mangling /// tree representing it. Demangle::NodePointer readDemanglingForContextDescriptor(StoredPointer contextAddress, Demangler &Dem) { auto context = readContextDescriptor(contextAddress); if (!context) return nullptr; return buildContextMangling(context, Dem); } /// Read the mangled underlying type from an opaque type descriptor. Demangle::NodePointer readUnderlyingTypeManglingForOpaqueTypeDescriptor(StoredPointer contextAddr, unsigned ordinal, Demangler &Dem) { auto context = readContextDescriptor(contextAddr); if (!context) return nullptr; if (context->getKind() != ContextDescriptorKind::OpaqueType) return nullptr; auto opaqueType = reinterpret_cast *>( context.getLocalBuffer()); if (ordinal >= opaqueType->getNumUnderlyingTypeArguments()) return nullptr; auto nameAddr = resolveRelativeField(context, opaqueType->getUnderlyingTypeArgumentMangledName(ordinal)); return readMangledName(RemoteAddress(nameAddr), MangledNameKind::Type, Dem); } TypeLookupErrorOr readUnderlyingTypeForOpaqueTypeDescriptor(StoredPointer contextAddr, unsigned ordinal) { Demangle::Demangler Dem; auto node = readUnderlyingTypeManglingForOpaqueTypeDescriptor(contextAddr, ordinal, Dem); if (!node) return TypeLookupError("Failed to read type mangling for descriptor."); return decodeMangledType(node); } bool isTaggedPointer(StoredPointer objectAddress) { if (getTaggedPointerEncoding() != TaggedPointerEncodingKind::Extended) return false; return (objectAddress ^ TaggedPointerObfuscator) & TaggedPointerMask; } /// Read the isa pointer of an Object-C tagged pointer value. std::optional readMetadataFromTaggedPointer(StoredPointer objectAddress) { auto readArrayElement = [&](StoredPointer base, StoredPointer tag) -> std::optional { StoredPointer addr = base + tag * sizeof(StoredPointer); StoredPointer isa; if (!Reader->readInteger(RemoteAddress(addr), &isa)) return std::nullopt; return isa; }; // Extended pointers have a tag of 0b111, using 8 additional bits // to specify the class. if (TaggedPointerExtendedMask != 0 && (((objectAddress ^ TaggedPointerObfuscator) & TaggedPointerExtendedMask) == TaggedPointerExtendedMask)) { auto tag = ((objectAddress >> TaggedPointerExtendedSlotShift) & TaggedPointerExtendedSlotMask); return readArrayElement(TaggedPointerExtendedClasses, tag); } // Basic tagged pointers use a 3 bit tag to specify the class. auto tag = ((objectAddress >> TaggedPointerSlotShift) & TaggedPointerSlotMask); return readArrayElement(TaggedPointerClasses, tag); } /// Read the isa pointer of a class or closure context instance and apply /// the isa mask. std::optional readMetadataFromInstance(StoredPointer objectAddress) { if (isTaggedPointer(objectAddress)) return readMetadataFromTaggedPointer(objectAddress); StoredPointer isa; if (!Reader->readInteger(RemoteAddress(objectAddress), &isa)) return std::nullopt; switch (getIsaEncoding()) { case IsaEncodingKind::Unknown: case IsaEncodingKind::Error: return std::nullopt; case IsaEncodingKind::None: return isa; case IsaEncodingKind::Masked: return isa & IsaMask; case IsaEncodingKind::Indexed: { // If applying the magic mask doesn't give us the magic value, // it's not an indexed isa. if ((isa & IsaMagicMask) != IsaMagicValue) return isa; // Extract the index. auto classIndex = (isa & IsaIndexMask) >> IsaIndexShift; // 0 is never a valid index. if (classIndex == 0) { return std::nullopt; // If the index is out of range, it's an error; but check for an // update first. (This will also trigger the first time because // we initialize LastIndexedClassesCount to 0). } else if (classIndex >= LastIndexedClassesCount) { StoredPointer count; if (!Reader->readInteger(RemoteAddress(IndexedClassesCountPointer), &count)) { return std::nullopt; } LastIndexedClassesCount = count; if (classIndex >= count) { return std::nullopt; } } // Find the address of the appropriate array element. RemoteAddress eltPointer = RemoteAddress(IndexedClassesPointer + classIndex * sizeof(StoredPointer)); StoredPointer metadataPointer; if (!Reader->readInteger(eltPointer, &metadataPointer)) { return std::nullopt; } return metadataPointer; } } swift_unreachable("Unhandled IsaEncodingKind in switch."); } /// Read the offset of the generic parameters of a class from the nominal /// type descriptor. If the class has a resilient superclass, we also /// have to read the superclass size and add that to the offset. /// /// The offset is in units of words, from the start of the class's /// metadata. std::optional readGenericArgsOffset(MetadataRef metadata, ContextDescriptorRef descriptor) { switch (descriptor->getKind()) { case ContextDescriptorKind::Class: { auto type = cast>(descriptor); if (!type->hasResilientSuperclass()) return type->getNonResilientGenericArgumentOffset(); auto bounds = computeMetadataBoundsFromSuperclass(descriptor); if (!bounds) return std::nullopt; return bounds->ImmediateMembersOffset / sizeof(StoredPointer); } case ContextDescriptorKind::Enum: { auto type = cast>(descriptor); return type->getGenericArgumentOffset(); } case ContextDescriptorKind::Struct: { auto type = cast>(descriptor); return type->getGenericArgumentOffset(); } default: return std::nullopt; } } using ClassMetadataBounds = TargetClassMetadataBounds; // This follows getMetadataBounds in ABI/Metadata.h. std::optional getClassMetadataBounds(ContextDescriptorRef classRef) { auto classDescriptor = cast>(classRef); if (!classDescriptor->hasResilientSuperclass()) { auto nonResilientImmediateMembersOffset = classDescriptor->areImmediateMembersNegative() ? -int32_t(classDescriptor->MetadataNegativeSizeInWords) : int32_t(classDescriptor->MetadataPositiveSizeInWords - classDescriptor->NumImmediateMembers); typename Runtime::StoredPointerDifference immediateMembersOffset = nonResilientImmediateMembersOffset * sizeof(StoredPointer); ClassMetadataBounds bounds{immediateMembersOffset, classDescriptor->MetadataNegativeSizeInWords, classDescriptor->MetadataPositiveSizeInWords}; return bounds; } return computeMetadataBoundsFromSuperclass(classRef); } // This follows computeMetadataBoundsFromSuperclass in Metadata.cpp. std::optional computeMetadataBoundsFromSuperclass(ContextDescriptorRef subclassRef) { auto subclass = cast>(subclassRef); std::optional bounds; if (!subclass->hasResilientSuperclass()) { bounds = ClassMetadataBounds::forSwiftRootClass(); } else { auto rawSuperclass = resolveRelativeField(subclassRef, subclass->getResilientSuperclass()); if (!rawSuperclass) { return std::nullopt; } bounds = forTypeReference( subclass->getResilientSuperclassReferenceKind(), rawSuperclass, [&](ContextDescriptorRef superclass) -> std::optional { if (!isa>(superclass)) return std::nullopt; return getClassMetadataBounds(superclass); }, [&](MetadataRef metadata) -> std::optional { auto cls = dyn_cast(metadata); if (!cls) return std::nullopt; return cls->getClassBoundsAsSwiftSuperclass(); }, [](StoredPointer objcClassName) -> std::optional { // We have no ability to look up an ObjC class by name. // FIXME: add a query for this; clients may have a way to do it. return std::nullopt; }); } if (!bounds) { return std::nullopt; } bounds->adjustForSubclass(subclass->areImmediateMembersNegative(), subclass->NumImmediateMembers); return bounds; } template std::optional forTypeReference(TypeReferenceKind refKind, StoredPointer ref, const DescriptorFn &descriptorFn, const MetadataFn &metadataFn, const ClassNameFn &classNameFn) { switch (refKind) { case TypeReferenceKind::IndirectTypeDescriptor: { StoredSignedPointer descriptorAddress; if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress)) { return std::nullopt; } ref = stripSignedPointer(descriptorAddress); LLVM_FALLTHROUGH; } case TypeReferenceKind::DirectTypeDescriptor: { auto descriptor = readContextDescriptor(ref); if (!descriptor) return std::nullopt; return descriptorFn(descriptor); } case TypeReferenceKind::DirectObjCClassName: return classNameFn(ref); case TypeReferenceKind::IndirectObjCClass: { StoredPointer classRef = 0; if (!Reader->readInteger(RemoteAddress(ref), &classRef)) return std::nullopt; auto metadata = readMetadata(classRef); if (!metadata) return std::nullopt; return metadataFn(metadata); } } return std::nullopt; } /// Read a single generic type argument from a bound generic type /// metadata. std::optional readGenericArgFromMetadata(StoredPointer metadata, unsigned index) { auto Meta = readMetadata(metadata); if (!Meta) return std::nullopt; auto descriptorAddress = readAddressOfNominalTypeDescriptor(Meta); if (!descriptorAddress) return std::nullopt; // Read the nominal type descriptor. auto descriptor = readContextDescriptor(descriptorAddress); if (!descriptor) return std::nullopt; auto generics = descriptor->getGenericContext(); if (!generics) return std::nullopt; auto offsetToGenericArgs = readGenericArgsOffset(Meta, descriptor); if (!offsetToGenericArgs) return std::nullopt; auto addressOfGenericArgAddress = (getAddress(Meta) + *offsetToGenericArgs * sizeof(StoredPointer) + index * sizeof(StoredPointer)); if (index >= generics->getGenericContextHeader().getNumArguments()) return std::nullopt; StoredPointer genericArgAddress; if (!Reader->readInteger(RemoteAddress(addressOfGenericArgAddress), &genericArgAddress)) return std::nullopt; return genericArgAddress; } /// Given the address of a nominal type descriptor, attempt to resolve /// its nominal type declaration. BuiltTypeDecl readNominalTypeFromDescriptor(StoredPointer address) { auto descriptor = readContextDescriptor(address); if (!descriptor) return BuiltTypeDecl(); return buildNominalTypeDecl(descriptor); } /// Try to read the offset of a tuple element from a tuple metadata. bool readTupleElementOffset(StoredPointer metadataAddress, unsigned eltIndex, StoredSize *offset) { // Read the metadata. auto metadata = readMetadata(metadataAddress); if (!metadata) return false; // Ensure that the metadata actually is tuple metadata. auto tupleMetadata = dyn_cast>(metadata); if (!tupleMetadata) return false; // Ensure that the element is in-bounds. if (eltIndex >= tupleMetadata->NumElements) return false; // Read the offset. const auto &element = tupleMetadata->getElement(eltIndex); *offset = element.Offset; return true; } /// Given a remote pointer to class metadata, attempt to read its superclass. std::optional readOffsetToFirstCaptureFromMetadata(StoredPointer MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta || meta->getKind() != MetadataKind::HeapLocalVariable) return std::nullopt; auto heapMeta = cast>(meta); return heapMeta->OffsetToFirstCapture; } std::optional readPointer(StoredPointer address) { return Reader->readPointer(RemoteAddress(address), sizeof(StoredPointer)); } std::optional readResolvedPointerValue(StoredPointer address) { if (auto pointer = readPointer(address)) { if (!pointer->isResolved()) return std::nullopt; return (StoredPointer)pointer->getResolvedAddress().getAddressData(); } return std::nullopt; } template RemoteAbsolutePointer resolvePointerField(RemoteRef base, const U &field) { auto pointerRef = base.getField(field); return Reader->resolvePointer(RemoteAddress(getAddress(pointerRef)), *pointerRef.getLocalBuffer()); } /// Given a remote pointer to class metadata, attempt to read its superclass. std::optional readCaptureDescriptorFromMetadata(StoredPointer MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta || meta->getKind() != MetadataKind::HeapLocalVariable) return std::nullopt; auto heapMeta = cast>(meta); return resolvePointerField(meta, heapMeta->CaptureDescription); } protected: template StoredPointer getAddress(RemoteRef base) { return (StoredPointer)base.getAddressData(); } template StoredPointer resolveRelativeField( RemoteRef base, const Field &field) { return (StoredPointer)base.resolveRelativeFieldData(field); } template std::optional resolveRelativeIndirectableField(RemoteRef base, const Field &field) { auto fieldRef = base.getField(field); int32_t offset; memcpy(&offset, fieldRef.getLocalBuffer(), sizeof(int32_t)); if (offset == 0) return std::optional(nullptr); bool indirect = offset & 1; offset &= ~1u; using SignedPointer = typename std::make_signed::type; StoredPointer resultAddress = getAddress(fieldRef) + (SignedPointer)offset; // Low bit set in the offset indicates that the offset leads to the absolute // address in memory. if (indirect) { if (auto ptr = readPointer(resultAddress)) { return stripSignedPointer(*ptr); } return std::nullopt; } return RemoteAbsolutePointer("", resultAddress); } /// Given a pointer to an Objective-C class, try to read its class name. bool readObjCClassName(StoredPointer classAddress, std::string &className) { // The following algorithm only works on the non-fragile Apple runtime. // Grab the RO-data pointer. This part is not ABI. StoredPointer roDataPtr = readObjCRODataPtr(classAddress); if (!roDataPtr) return false; // This is ABI. static constexpr auto OffsetToName = roundUpToAlignment(size_t(12), sizeof(StoredPointer)) + sizeof(StoredPointer); // Read the name pointer. StoredPointer namePtr; if (!Reader->readInteger(RemoteAddress(roDataPtr + OffsetToName), &namePtr)) return false; // If the name pointer is null, treat that as an error. if (!namePtr) return false; return Reader->readString(RemoteAddress(namePtr), className); } MetadataRef readMetadata(StoredPointer address) { auto cached = MetadataCache.find(address); if (cached != MetadataCache.end()) return MetadataRef(address, reinterpret_cast *>( cached->second.get())); StoredPointer KindValue = 0; if (!Reader->readInteger(RemoteAddress(address), &KindValue)) return nullptr; switch (getEnumeratedMetadataKind(KindValue)) { case MetadataKind::Class: return _readMetadata(address); case MetadataKind::Enum: return _readMetadata(address); case MetadataKind::ErrorObject: return _readMetadata(address); case MetadataKind::Existential: { StoredPointer flagsAddress = address + sizeof(StoredPointer); ExistentialTypeFlags::int_type flagsData; if (!Reader->readInteger(RemoteAddress(flagsAddress), &flagsData)) return nullptr; ExistentialTypeFlags flags(flagsData); StoredPointer numProtocolsAddress = flagsAddress + sizeof(flagsData); uint32_t numProtocols; if (!Reader->readInteger(RemoteAddress(numProtocolsAddress), &numProtocols)) return nullptr; // Make sure the number of protocols is reasonable if (numProtocols >= 256) return nullptr; auto totalSize = sizeof(TargetExistentialTypeMetadata) + numProtocols * sizeof(ConstTargetMetadataPointer); if (flags.hasSuperclassConstraint()) totalSize += sizeof(StoredPointer); return _readMetadata(address, totalSize); } case MetadataKind::ExistentialMetatype: return _readMetadata(address); case MetadataKind::ExtendedExistential: { // We need to read the shape in order to figure out how large // the generalization arguments are. StoredPointer shapeAddress = address + sizeof(StoredPointer); StoredSignedPointer signedShapePtr; if (!Reader->readInteger(RemoteAddress(shapeAddress), &signedShapePtr)) return nullptr; auto shapePtr = stripSignedPointer(signedShapePtr); auto shape = readShape(shapePtr); if (!shape) return nullptr; auto totalSize = sizeof(TargetExtendedExistentialTypeMetadata) + shape->getGeneralizationSignature().getArgumentLayoutSizeInWords() * sizeof(StoredPointer); return _readMetadata(address, totalSize); } case MetadataKind::ForeignClass: return _readMetadata(address); case MetadataKind::ForeignReferenceType: return _readMetadata(address); case MetadataKind::Function: { StoredSize flagsValue; auto flagsAddr = address + TargetFunctionTypeMetadata::OffsetToFlags; if (!Reader->readInteger(RemoteAddress(flagsAddr), &flagsValue)) return nullptr; auto flags = TargetFunctionTypeFlags::fromIntValue(flagsValue); auto totalSize = sizeof(TargetFunctionTypeMetadata) + flags.getNumParameters() * sizeof(FunctionTypeMetadata::Parameter); if (flags.hasParameterFlags()) totalSize += flags.getNumParameters() * sizeof(uint32_t); if (flags.isDifferentiable()) totalSize = roundUpToAlignment(totalSize, sizeof(StoredPointer)) + sizeof(TargetFunctionMetadataDifferentiabilityKind< typename Runtime::StoredSize>); return _readMetadata(address, roundUpToAlignment(totalSize, sizeof(StoredPointer))); } case MetadataKind::HeapGenericLocalVariable: return _readMetadata(address); case MetadataKind::HeapLocalVariable: return _readMetadata(address); case MetadataKind::Metatype: return _readMetadata(address); case MetadataKind::ObjCClassWrapper: return _readMetadata(address); case MetadataKind::Optional: return _readMetadata(address); case MetadataKind::Struct: return _readMetadata(address); case MetadataKind::Tuple: { auto numElementsAddress = address + TargetTupleTypeMetadata::getOffsetToNumElements(); StoredSize numElements; if (!Reader->readInteger(RemoteAddress(numElementsAddress), &numElements)) return nullptr; auto totalSize = sizeof(TargetTupleTypeMetadata) + numElements * sizeof(TupleTypeMetadata::Element); // Make sure the number of elements is reasonable if (numElements >= 256) return nullptr; return _readMetadata(address, totalSize); } case MetadataKind::Opaque: default: return _readMetadata(address); } // We can fall out here if the value wasn't actually a valid // MetadataKind. return nullptr; } StoredPointer readAddressOfNominalTypeDescriptor(MetadataRef &metadata, bool skipArtificialSubclasses = false) { switch (metadata->getKind()) { case MetadataKind::Class: { auto classMeta = cast(metadata); while (true) { if (!classMeta->isTypeMetadata()) return 0; StoredSignedPointer descriptorAddressSigned = classMeta->getDescriptionAsSignedPointer(); StoredPointer descriptorAddress = stripSignedPointer(descriptorAddressSigned); // If this class has a null descriptor, it's artificial, // and we need to skip it upon request. Otherwise, we're done. if (descriptorAddress || !skipArtificialSubclasses) return static_cast(descriptorAddress); auto superclassMetadataAddress = stripSignedPointer(classMeta->Superclass); if (!superclassMetadataAddress) return 0; auto superMeta = readMetadata(superclassMetadataAddress); if (!superMeta) return 0; auto superclassMeta = dyn_cast(superMeta); if (!superclassMeta) return 0; classMeta = superclassMeta; metadata = superMeta; } } case MetadataKind::Struct: case MetadataKind::Optional: case MetadataKind::Enum: { auto valueMeta = cast>(metadata); StoredSignedPointer descriptorAddressSigned = valueMeta->getDescriptionAsSignedPointer(); StoredPointer descriptorAddress = stripSignedPointer(descriptorAddressSigned); return descriptorAddress; } case MetadataKind::ForeignClass: { auto foreignMeta = cast>(metadata); StoredSignedPointer descriptorAddressSigned = foreignMeta->getDescriptionAsSignedPointer(); StoredPointer descriptorAddress = stripSignedPointer(descriptorAddressSigned); return descriptorAddress; } case MetadataKind::ForeignReferenceType: { auto foreignMeta = cast>(metadata); StoredSignedPointer descriptorAddressSigned = foreignMeta->getDescriptionAsSignedPointer(); StoredPointer descriptorAddress = stripSignedPointer(descriptorAddressSigned); return descriptorAddress; } default: return 0; } } private: template