From bfb026cb9e7ceb1c3571def827a70773c34cc697 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 17 Jun 2025 16:57:19 -0700 Subject: [PATCH 1/4] [RemoteInspection] Change RemoteAbsolutePointer (NFC) This patch changes RemoteAbsolutePointer to store both the symbol and the resolved address. This allows us to retire some ugly workarounds to deal with non-symbolic addresses and it fixes code paths that would need these workarounds, but haven't implemented them yet (i.e., the pack shape handling in the symbolicReferenceResolver in MetadatyaReader. Addresses parts of rdar://146273066. rdar://153687085 (cherry picked from commit 9381a54c67a0df88a266a0a0e45f95d065eb7eaf) (cherry picked from commit a6eafcb311d1d9d42081cf189a402586c658bfb9) --- include/swift/Remote/MemoryReader.h | 4 +- include/swift/Remote/MetadataReader.h | 44 +++++-------------- include/swift/Remote/RemoteAddress.h | 41 ++++++++--------- .../RemoteInspection/ReflectionContext.h | 2 +- .../swift/RemoteInspection/TypeRefBuilder.h | 14 +++--- lib/StaticMirror/ObjectFileContext.cpp | 11 ++--- 6 files changed, 46 insertions(+), 70 deletions(-) diff --git a/include/swift/Remote/MemoryReader.h b/include/swift/Remote/MemoryReader.h index 7e077a5f7d068..772bcfbdfbc3e 100644 --- a/include/swift/Remote/MemoryReader.h +++ b/include/swift/Remote/MemoryReader.h @@ -147,7 +147,7 @@ class MemoryReader { virtual RemoteAbsolutePointer resolvePointer(RemoteAddress address, uint64_t readValue) { // Default implementation returns the read value as is. - return RemoteAbsolutePointer("", readValue); + return RemoteAbsolutePointer(RemoteAddress(readValue)); } /// Performs the inverse operation of \ref resolvePointer. @@ -166,7 +166,7 @@ class MemoryReader { virtual RemoteAbsolutePointer getSymbol(RemoteAddress address) { if (auto symbol = resolvePointerAsSymbol(address)) return *symbol; - return RemoteAbsolutePointer("", address.getAddressData()); + return RemoteAbsolutePointer(address); } /// Lookup a dynamic symbol name (ie dynamic loader binding) for the given diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index a7d9485e6ad03..ee4dc8e0cdc16 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -416,11 +416,9 @@ class MetadataReader { } RemoteAbsolutePointer stripSignedPointer(const RemoteAbsolutePointer &P) { - if (P.isResolved()) { - return RemoteAbsolutePointer("", - P.getResolvedAddress().getAddressData() & PtrAuthMask); - } - return P; + return RemoteAbsolutePointer( + P.getSymbol(), P.getOffset(), + RemoteAddress(P.getResolvedAddress().getAddressData() & PtrAuthMask)); } StoredPointer queryPtrAuthMask() { @@ -519,14 +517,6 @@ class MetadataReader { // 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; @@ -534,14 +524,6 @@ class MetadataReader { 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); @@ -1379,12 +1361,10 @@ class MetadataReader { ParentContextDescriptorRef readContextDescriptor(const RemoteAbsolutePointer &address) { // Map an unresolved pointer to an unresolved context ref. - if (!address.isResolved()) { + if (!address.getSymbol().empty()) { // We can only handle references to a symbol without an offset currently. - if (address.getOffset() != 0) { - return ParentContextDescriptorRef(); - } - return ParentContextDescriptorRef(address.getSymbol()); + if (address.getOffset() == 0) + return ParentContextDescriptorRef(address.getSymbol()); } return ParentContextDescriptorRef( @@ -2016,7 +1996,7 @@ class MetadataReader { std::optional readResolvedPointerValue(StoredPointer address) { if (auto pointer = readPointer(address)) { - if (!pointer->isResolved()) + if (!pointer->getResolvedAddress()) return std::nullopt; return (StoredPointer)pointer->getResolvedAddress().getAddressData(); } @@ -2079,7 +2059,7 @@ class MetadataReader { return std::nullopt; } - return RemoteAbsolutePointer("", resultAddress); + return RemoteAbsolutePointer(RemoteAddress(resultAddress)); } /// Given a pointer to an Objective-C class, try to read its class name. @@ -2335,13 +2315,11 @@ class MetadataReader { auto parentAddress = resolveRelativeIndirectableField(base, base->Parent); if (!parentAddress) return std::nullopt; - if (!parentAddress->isResolved()) { + if (!parentAddress->getSymbol().empty()) { // Currently we can only handle references directly to a symbol without // an offset. - if (parentAddress->getOffset() != 0) { - return std::nullopt; - } - return ParentContextDescriptorRef(parentAddress->getSymbol()); + if (parentAddress->getOffset() == 0) + return ParentContextDescriptorRef(parentAddress->getSymbol()); } auto addr = parentAddress->getResolvedAddress(); if (!addr) diff --git a/include/swift/Remote/RemoteAddress.h b/include/swift/Remote/RemoteAddress.h index 15c10aa23c216..611234f205cfe 100644 --- a/include/swift/Remote/RemoteAddress.h +++ b/include/swift/Remote/RemoteAddress.h @@ -63,35 +63,30 @@ class RemoteAddress { /// A symbolic relocated absolute pointer value. class RemoteAbsolutePointer { - /// The symbol name that the pointer refers to. Empty if the value is absolute. + /// The symbol name that the pointer refers to. Empty if only an absolute + /// address is available. std::string Symbol; - /// The offset from the symbol, or the resolved remote address if \c Symbol is empty. - int64_t Offset; + /// The offset from the symbol. + int64_t Offset = 0; + /// The resolved remote address. + RemoteAddress Address = RemoteAddress{(uint64_t)0}; public: - RemoteAbsolutePointer() - : Symbol(), Offset(0) - {} - - RemoteAbsolutePointer(std::nullptr_t) - : RemoteAbsolutePointer() - {} - - RemoteAbsolutePointer(llvm::StringRef Symbol, int64_t Offset) - : Symbol(Symbol), Offset(Offset) - {} - - bool isResolved() const { return Symbol.empty(); } + RemoteAbsolutePointer() = default; + RemoteAbsolutePointer(std::nullptr_t) : RemoteAbsolutePointer() {} + + RemoteAbsolutePointer(llvm::StringRef Symbol, int64_t Offset, + RemoteAddress Address) + : Symbol(Symbol), Offset(Offset), Address(Address) {} + RemoteAbsolutePointer(RemoteAddress Address) : Address(Address) {} + llvm::StringRef getSymbol() const { return Symbol; } int64_t getOffset() const { return Offset; } - - RemoteAddress getResolvedAddress() const { - assert(isResolved()); - return RemoteAddress(Offset); - } - + + RemoteAddress getResolvedAddress() const { return Address; } + explicit operator bool() const { - return Offset != 0 || !Symbol.empty(); + return Address || !Symbol.empty(); } }; diff --git a/include/swift/RemoteInspection/ReflectionContext.h b/include/swift/RemoteInspection/ReflectionContext.h index be6bd27670d41..32b7bc83a8095 100644 --- a/include/swift/RemoteInspection/ReflectionContext.h +++ b/include/swift/RemoteInspection/ReflectionContext.h @@ -1020,7 +1020,7 @@ class ReflectionContext auto CDAddr = this->readCaptureDescriptorFromMetadata(*MetadataAddress); if (!CDAddr) return nullptr; - if (!CDAddr->isResolved()) + if (!CDAddr->getResolvedAddress()) return nullptr; // FIXME: Non-generic SIL boxes also use the HeapLocalVariable metadata diff --git a/include/swift/RemoteInspection/TypeRefBuilder.h b/include/swift/RemoteInspection/TypeRefBuilder.h index 63d2f4dc1719a..960536977a9a1 100644 --- a/include/swift/RemoteInspection/TypeRefBuilder.h +++ b/include/swift/RemoteInspection/TypeRefBuilder.h @@ -1871,7 +1871,7 @@ class TypeRefBuilder { if (auto symbol = OpaquePointerReader( remote::RemoteAddress(adjustedProtocolDescriptorTarget), PointerSize)) { - if (!symbol->getSymbol().empty()) { + if (!symbol->getSymbol().empty() && symbol->getOffset() == 0) { Demangle::Context Ctx; auto demangledRoot = Ctx.demangleSymbolAsNode(symbol->getSymbol().str()); @@ -1882,7 +1882,8 @@ class TypeRefBuilder { nodeToString(demangledRoot->getChild(0)->getChild(0)); } else { // This is an absolute address of a protocol descriptor - auto protocolDescriptorAddress = (uintptr_t)symbol->getOffset(); + auto protocolDescriptorAddress = + (uintptr_t)symbol->getResolvedAddress().getAddressData(); protocolName = readFullyQualifiedProtocolNameFromProtocolDescriptor( protocolDescriptorAddress); } @@ -2026,7 +2027,7 @@ class TypeRefBuilder { if (auto symbol = OpaquePointerReader( remote::RemoteAddress(adjustedParentTargetAddress), PointerSize)) { - if (!symbol->getSymbol().empty()) { + if (!symbol->getSymbol().empty() && symbol->getOffset() == 0) { Demangle::Context Ctx; auto demangledRoot = Ctx.demangleSymbolAsNode(symbol->getSymbol().str()); @@ -2264,7 +2265,7 @@ class TypeRefBuilder { // external, check that first if (auto symbol = OpaqueDynamicSymbolResolver( remote::RemoteAddress(contextTypeDescriptorAddress))) { - if (!symbol->isResolved()) { + if (!symbol->getSymbol().empty() && symbol->getOffset() == 0) { Demangle::Context Ctx; auto demangledRoot = Ctx.demangleSymbolAsNode(symbol->getSymbol().str()); @@ -2283,10 +2284,11 @@ class TypeRefBuilder { mangledTypeName = typeMangling.result(); return std::make_pair(mangledTypeName, typeName); - } else if (symbol->getOffset()) { + } else if (symbol->getResolvedAddress()) { // If symbol is empty and has an offset, this is the resolved remote // address - contextTypeDescriptorAddress = symbol->getOffset(); + contextTypeDescriptorAddress = + symbol->getResolvedAddress().getAddressData(); } } diff --git a/lib/StaticMirror/ObjectFileContext.cpp b/lib/StaticMirror/ObjectFileContext.cpp index 397321d8254c1..a2bca9bcc0d77 100644 --- a/lib/StaticMirror/ObjectFileContext.cpp +++ b/lib/StaticMirror/ObjectFileContext.cpp @@ -322,9 +322,9 @@ Image::resolvePointer(uint64_t Addr, uint64_t pointerValue) const { // 32 bits. if (isMachOWithPtrAuth()) { return remote::RemoteAbsolutePointer( - "", HeaderAddress + (pointerValue & 0xffffffffull)); + remote::RemoteAddress(HeaderAddress + (pointerValue & 0xffffffffull))); } else { - return remote::RemoteAbsolutePointer("", pointerValue); + return remote::RemoteAbsolutePointer(remote::RemoteAddress(pointerValue)); } } @@ -333,7 +333,8 @@ remote::RemoteAbsolutePointer Image::getDynamicSymbol(uint64_t Addr) const { if (found == DynamicRelocations.end()) return nullptr; return remote::RemoteAbsolutePointer(found->second.Symbol, - found->second.Offset); + found->second.Offset, + remote::RemoteAddress((uint64_t)0)); } std::pair @@ -526,8 +527,8 @@ ObjectMemoryReader::resolvePointer(reflection::RemoteAddress Addr, // Mix in the image index again to produce a remote address pointing into the // same image. return remote::RemoteAbsolutePointer( - "", encodeImageIndexAndAddress( - image, resolved.getResolvedAddress().getAddressData())); + remote::RemoteAddress(encodeImageIndexAndAddress( + image, resolved.getResolvedAddress().getAddressData()))); } remote::RemoteAbsolutePointer From 9e85b88d9d914aa67dc25dd1eb266974d1b58d38 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Fri, 11 Jul 2025 16:33:19 -0700 Subject: [PATCH 2/4] [RemoteMirrors] Fix losing the remote address on StaticMirror The Offset field of a DynamicRelocation is either an offset or a remote address, but was being treated only as a remote address on getDynamicSymbol. --- include/swift/StaticMirror/ObjectFileContext.h | 6 +++++- lib/StaticMirror/ObjectFileContext.cpp | 10 +++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/swift/StaticMirror/ObjectFileContext.h b/include/swift/StaticMirror/ObjectFileContext.h index 5c259eb40e73a..d37338df86860 100644 --- a/include/swift/StaticMirror/ObjectFileContext.h +++ b/include/swift/StaticMirror/ObjectFileContext.h @@ -39,8 +39,12 @@ class Image { uint64_t HeaderAddress; std::vector Segments; struct DynamicRelocation { + /// The symbol name that the pointer refers to. Empty if only an absolute + /// address is available. StringRef Symbol; - uint64_t Offset; + // The offset (if the symbol is available), or the resolved remote address + // if the symbol is empty. + uint64_t OffsetOrAddress; }; llvm::DenseMap DynamicRelocations; diff --git a/lib/StaticMirror/ObjectFileContext.cpp b/lib/StaticMirror/ObjectFileContext.cpp index a2bca9bcc0d77..47513d977ddcf 100644 --- a/lib/StaticMirror/ObjectFileContext.cpp +++ b/lib/StaticMirror/ObjectFileContext.cpp @@ -332,9 +332,13 @@ remote::RemoteAbsolutePointer Image::getDynamicSymbol(uint64_t Addr) const { auto found = DynamicRelocations.find(Addr); if (found == DynamicRelocations.end()) return nullptr; - return remote::RemoteAbsolutePointer(found->second.Symbol, - found->second.Offset, - remote::RemoteAddress((uint64_t)0)); + if (!found->second.Symbol.empty()) + return remote::RemoteAbsolutePointer(found->second.Symbol, + found->second.OffsetOrAddress, + remote::RemoteAddress()); + return remote::RemoteAbsolutePointer( + remote::RemoteAddress(found->second.OffsetOrAddress, + remote::RemoteAddress::DefaultAddressSpace)); } std::pair From e2c8b761cd916cb2c9d92356647422d54f63a1f8 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Wed, 9 Jul 2025 14:52:42 -0700 Subject: [PATCH 3/4] [NFC][RemoteInspection] Add an opaque AddressSpace field to RemoteAddress Add an extra opaque field to AddressSpace, which can be used by clients of RemoteInspection to distinguish between different address spaces. LLDB employs an optimization where it reads memory from files instead of the running process whenever it can to speed up memory reads (these can be slow when debugging something over a network). To do this, it needs to keep track whether an address originated from a process or a file. It currently distinguishes addresses by setting an unused high bit on the address, but because of pointer authentication this is not a reliable solution. In order to keep this optimization working, this patch adds an extra opaque AddressSpace field to RemoteAddress, which LLDB can use on its own implementation of MemoryReader to distinguish between addresses. This patch is NFC for the other RemoteInspection clients, as it adds extra information to RemoteAddress, which is entirely optional and if unused should not change the behavior of the library. Although this patch is quite big the changes are largely mechanical, replacing threading StoredPointer with RemoteAddress. rdar://148361743 (cherry picked from commit 58df5534d2917ca545463b40ca738e5c54c40c89) (cherry picked from commit 8f3862b5e758fa7348760e772e6fcf95c52b06ab) --- include/swift/Basic/RelativePointer.h | 3 + include/swift/Remote/CMemoryReader.h | 14 +- include/swift/Remote/Failure.h | 2 +- include/swift/Remote/InProcessMemoryReader.h | 6 +- include/swift/Remote/MemoryReader.h | 25 +- include/swift/Remote/MetadataReader.h | 636 +++++++++--------- include/swift/Remote/RemoteAddress.h | 201 +++++- .../RemoteInspection/ReflectionContext.h | 285 ++++---- .../swift/RemoteInspection/TypeRefBuilder.h | 237 +++---- .../swift/StaticMirror/ObjectFileContext.h | 11 +- lib/RemoteAST/InProcessMemoryReader.cpp | 2 +- lib/RemoteAST/RemoteAST.cpp | 36 +- lib/StaticMirror/ObjectFileContext.cpp | 54 +- .../public/RemoteInspection/TypeLowering.cpp | 3 +- .../RemoteInspection/TypeRefBuilder.cpp | 35 +- .../SwiftRemoteMirror/SwiftRemoteMirror.cpp | 94 ++- .../swift-reflection-fuzzer.cpp | 9 +- .../swift-remoteast-test.cpp | 23 +- 18 files changed, 969 insertions(+), 707 deletions(-) diff --git a/include/swift/Basic/RelativePointer.h b/include/swift/Basic/RelativePointer.h index a42801d0d7400..4d53652a949e7 100644 --- a/include/swift/Basic/RelativePointer.h +++ b/include/swift/Basic/RelativePointer.h @@ -132,7 +132,10 @@ #ifndef SWIFT_BASIC_RELATIVEPOINTER_H #define SWIFT_BASIC_RELATIVEPOINTER_H +#include #include +#include +#include namespace swift { diff --git a/include/swift/Remote/CMemoryReader.h b/include/swift/Remote/CMemoryReader.h index 3805b76c7cdad..6cb8b7f277a02 100644 --- a/include/swift/Remote/CMemoryReader.h +++ b/include/swift/Remote/CMemoryReader.h @@ -69,7 +69,7 @@ class CMemoryReader final : public MemoryReader { // that we're likely failing to strip a signed pointer when reading from it. bool hasSignatureBits(RemoteAddress address) { return false; - uint64_t addressData = address.getAddressData(); + uint64_t addressData = address.getRawAddress(); return addressData != (addressData & getPtrauthMask()); } @@ -89,13 +89,12 @@ class CMemoryReader final : public MemoryReader { RemoteAddress getSymbolAddress(const std::string &name) override { auto addressData = Impl.getSymbolAddress(Impl.reader_context, name.c_str(), name.size()); - return RemoteAddress(addressData); + return RemoteAddress(addressData, RemoteAddress::DefaultAddressSpace); } uint64_t getStringLength(RemoteAddress address) { assert(!hasSignatureBits(address)); - return Impl.getStringLength(Impl.reader_context, - address.getAddressData()); + return Impl.getStringLength(Impl.reader_context, address.getRawAddress()); } bool readString(RemoteAddress address, std::string &dest) override { @@ -120,7 +119,7 @@ class CMemoryReader final : public MemoryReader { ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override { assert(!hasSignatureBits(address)); void *FreeContext; - auto Ptr = Impl.readBytes(Impl.reader_context, address.getAddressData(), + auto Ptr = Impl.readBytes(Impl.reader_context, address.getRawAddress(), size, &FreeContext); auto Free = Impl.free; @@ -134,8 +133,7 @@ class CMemoryReader final : public MemoryReader { return ReadBytesResult(Ptr, freeLambda); } }; - -} -} +} // namespace remote +} // namespace swift #endif diff --git a/include/swift/Remote/Failure.h b/include/swift/Remote/Failure.h index 908e6357c0261..916c74892928d 100644 --- a/include/swift/Remote/Failure.h +++ b/include/swift/Remote/Failure.h @@ -288,7 +288,7 @@ class Failure { case ArgStorageKind::Address: { result += '0'; result += 'x'; - uint64_t address = Args[argIndex].Address.getAddressData(); + uint64_t address = Args[argIndex].Address.getRawAddress(); unsigned max = ((address >> 32) != 0 ? 16 : 8); for (unsigned i = 0; i != max; ++i) { result += "0123456789abcdef"[(address >> (max - 1 - i) * 4) & 0xF]; diff --git a/include/swift/Remote/InProcessMemoryReader.h b/include/swift/Remote/InProcessMemoryReader.h index 9fa78a28308d6..dbe7351317a62 100644 --- a/include/swift/Remote/InProcessMemoryReader.h +++ b/include/swift/Remote/InProcessMemoryReader.h @@ -105,8 +105,8 @@ class InProcessMemoryReader final : public MemoryReader { return ReadBytesResult(address.getLocalPointer(), [](const void *) {}); } }; - -} -} + +} // namespace remote +} // namespace swift #endif diff --git a/include/swift/Remote/MemoryReader.h b/include/swift/Remote/MemoryReader.h index 772bcfbdfbc3e..fddcc495d0834 100644 --- a/include/swift/Remote/MemoryReader.h +++ b/include/swift/Remote/MemoryReader.h @@ -57,13 +57,31 @@ class MemoryReader { /// /// Returns false if the operation failed. virtual bool readString(RemoteAddress address, std::string &dest) = 0; - + + /// Attempts to read a remote address from the given address in the remote + /// process. + /// + /// Returns false if the operator failed. + template + bool readRemoteAddress(RemoteAddress address, RemoteAddress &out) { + IntegerType buf; + if (!readInteger(address, &buf)) + return false; + + out = RemoteAddress((uint64_t)buf, address.getAddressSpace()); + return true; + } + /// Attempts to read an integer from the given address in the remote /// process. /// /// Returns false if the operation failed. template bool readInteger(RemoteAddress address, IntegerType *dest) { + static_assert(!std::is_same(), + "RemoteAddress cannot be read in directly, use " + "readRemoteAddress instead."); + return readBytes(address, reinterpret_cast(dest), sizeof(IntegerType)); } @@ -147,7 +165,8 @@ class MemoryReader { virtual RemoteAbsolutePointer resolvePointer(RemoteAddress address, uint64_t readValue) { // Default implementation returns the read value as is. - return RemoteAbsolutePointer(RemoteAddress(readValue)); + return RemoteAbsolutePointer( + RemoteAddress(readValue, address.getAddressSpace())); } /// Performs the inverse operation of \ref resolvePointer. @@ -263,7 +282,7 @@ class MemoryReader { virtual ~MemoryReader() = default; }; -} // end namespace reflection +} // end namespace remote } // end namespace swift #endif // SWIFT_REFLECTION_READER_H diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index ee4dc8e0cdc16..5c682f9233a51 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -58,19 +58,17 @@ enum class MangledNameKind { template class RemoteRef { private: - uint64_t Address; + RemoteAddress Address; const T *LocalBuffer; public: - RemoteRef() - : Address(0), LocalBuffer(nullptr) {} + RemoteRef() : Address(), LocalBuffer(nullptr) {} /*implicit*/ RemoteRef(std::nullptr_t _) : RemoteRef() {} - template - explicit RemoteRef(StoredPointer address, const T *localBuffer) - : Address((uint64_t)address), LocalBuffer(localBuffer) {} + explicit RemoteRef(RemoteAddress address, const T *localBuffer) + : Address(address), LocalBuffer(localBuffer) {} // Some versions of clang++ sometimes fail to generate the // copy constructor for this type correctly - add a workaround @@ -83,9 +81,7 @@ class RemoteRef { return *this; } - uint64_t getAddressData() const { - return Address; - } + RemoteAddress getRemoteAddress() const { return Address; } const T *getLocalBuffer() const { return LocalBuffer; @@ -113,23 +109,23 @@ class RemoteRef { template RemoteRef getField(U &field) const { auto offset = (intptr_t)&field - (intptr_t)LocalBuffer; - return RemoteRef((uint64_t)(Address + (int64_t)offset), &field); + return RemoteRef((Address + (int64_t)offset), &field); } /// Resolve the remote address of a relative offset stored at the remote address. - uint64_t resolveRelativeAddressData() const { + RemoteAddress resolveRelativeAddressData() const { int32_t offset; memcpy(&offset, LocalBuffer, sizeof(int32_t)); if (offset == 0) - return 0; + return RemoteAddress(); return Address + (int64_t)offset; } - - template - uint64_t resolveRelativeFieldData(U &field) const { + + template + RemoteAddress resolveRelativeFieldData(U &field) const { return getField(field).resolveRelativeAddressData(); } - + RemoteRef atByteOffset(int64_t Offset) const { return RemoteRef(Address + Offset, (const T *)((intptr_t)LocalBuffer + Offset)); @@ -195,10 +191,10 @@ class MetadataReader { /// 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. + /// The dense map info for a std::pair. struct DenseMapInfoTypeCacheKey { - using Pair = std::pair; - using StoredPointerInfo = llvm::DenseMapInfo; + 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 @@ -223,7 +219,7 @@ class MetadataReader { /// A cache of built types, keyed by the address of the type and whether the /// request ignored articial superclasses or not. - llvm::DenseMap, BuiltType, + llvm::DenseMap, BuiltType, DenseMapInfoTypeCacheKey> TypeCache; @@ -231,7 +227,7 @@ class MetadataReader { using OwnedMetadataRef = MemoryReader::ReadBytesResult; /// A cache of read type metadata, keyed by the address of the metadata. - llvm::DenseMap MetadataCache; + llvm::DenseMap MetadataCache; using ContextDescriptorRef = RemoteRef>; @@ -313,14 +309,14 @@ class MetadataReader { /// A cache of read nominal type descriptors, keyed by the address of the /// nominal type descriptor. - llvm::DenseMap + 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; + llvm::DenseMap ShapeCache; enum class IsaEncodingKind { /// We haven't checked yet. @@ -359,8 +355,8 @@ class MetadataReader { StoredPointer IsaIndexShift; StoredPointer IsaMagicMask; StoredPointer IsaMagicValue; - StoredPointer IndexedClassesPointer; - StoredPointer IndexedClassesCountPointer; + RemoteAddress IndexedClassesPointer; + RemoteAddress IndexedClassesCountPointer; StoredPointer LastIndexedClassesCount = 0; enum class TaggedPointerEncodingKind { @@ -389,11 +385,11 @@ class MetadataReader { StoredPointer TaggedPointerMask; StoredPointer TaggedPointerSlotShift; StoredPointer TaggedPointerSlotMask; - StoredPointer TaggedPointerClasses; + RemoteAddress TaggedPointerClasses; StoredPointer TaggedPointerExtendedMask; StoredPointer TaggedPointerExtendedSlotShift; StoredPointer TaggedPointerExtendedSlotMask; - StoredPointer TaggedPointerExtendedClasses; + RemoteAddress TaggedPointerExtendedClasses; StoredPointer TaggedPointerObfuscator; Demangle::NodeFactory Factory; @@ -411,14 +407,21 @@ class MetadataReader { StoredPointer PtrAuthMask; - StoredPointer stripSignedPointer(StoredSignedPointer P) { - return P.SignedValue & PtrAuthMask; + RemoteAddress stripSignedPointer(RemoteAddress P) { + // Only pointers in the default address space are signed. + if (P.getAddressSpace() == RemoteAddress::DefaultAddressSpace) + return P & PtrAuthMask; + return P; + } + + RemoteAddress stripSignedPointer(StoredSignedPointer P) { + return RemoteAddress(P.SignedValue & PtrAuthMask, + RemoteAddress::DefaultAddressSpace); } RemoteAbsolutePointer stripSignedPointer(const RemoteAbsolutePointer &P) { - return RemoteAbsolutePointer( - P.getSymbol(), P.getOffset(), - RemoteAddress(P.getResolvedAddress().getAddressData() & PtrAuthMask)); + auto Stripped = stripSignedPointer(P.getResolvedAddress()); + return RemoteAbsolutePointer(P.getSymbol(), P.getOffset(), Stripped); } StoredPointer queryPtrAuthMask() { @@ -431,11 +434,9 @@ class MetadataReader { } template - MetadataReader(std::shared_ptr reader, T &&... args) - : Builder(std::forward(args)...), - Reader(std::move(reader)), - PtrAuthMask(queryPtrAuthMask()) { - } + 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; @@ -462,7 +463,7 @@ class MetadataReader { auto offsetInMangledName = (const char *)base - mangledName.getLocalBuffer(); auto remoteAddress = - mangledName.getAddressData() + offsetInMangledName + offset; + mangledName.getRemoteAddress() + offsetInMangledName + offset; RemoteAbsolutePointer resolved; if (directness == Directness::Indirect) { @@ -472,7 +473,7 @@ class MetadataReader { return nullptr; } } else { - resolved = Reader->getSymbol(RemoteAddress(remoteAddress)); + resolved = Reader->getSymbol(remoteAddress); } switch (kind) { @@ -486,9 +487,13 @@ class MetadataReader { if (useOpaqueTypeSymbolicReferences && context.isResolved() && context.getResolved()->getKind() == ContextDescriptorKind::OpaqueType){ + // FIXME: this loses the address space. This can be fixed by adding an + // opaque field in Node that can store the address space. This + // wouldn't degrade performance as Node's address is part of an union + // which is 16 bytes longs return dem.createNode( - Node::Kind::OpaqueTypeDescriptorSymbolicReference, - context.getResolved().getAddressData()); + Node::Kind::OpaqueTypeDescriptorSymbolicReference, + context.getResolved().getRemoteAddress().getRawAddress()); } return buildContextMangling(context, dem); @@ -502,27 +507,27 @@ class MetadataReader { // The symbolic reference points at a unique extended // existential type shape. return dem.createNode( - Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference, - resolved.getResolvedAddress().getAddressData()); + Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference, + resolved.getResolvedAddress().getRawAddress()); } case Demangle::SymbolicReferenceKind::NonUniqueExtendedExistentialTypeShape: { // The symbolic reference points at a non-unique extended // existential type shape. + // FIXME: this loses the address space. return dem.createNode( - Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference, - resolved.getResolvedAddress().getAddressData()); + Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference, + resolved.getResolvedAddress().getRawAddress()); } 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. - auto addr = - resolved.getResolvedAddress().getAddressData() + sizeof(int32_t); + auto addr = resolved.getResolvedAddress() + sizeof(int32_t); int32_t offset; - Reader->readInteger(RemoteAddress(addr), &offset); + Reader->readInteger(addr, &offset); auto addrOfTypeRef = addr + offset; - resolved = Reader->getSymbol(RemoteAddress(addrOfTypeRef)); + resolved = Reader->getSymbol(addrOfTypeRef); // Dig out the protocol from the protocol list. auto protocolList = readMangledName(resolved.getResolvedAddress(), @@ -576,10 +581,9 @@ class MetadataReader { /// 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, + Demangle::NodePointer demangle(RemoteAddress remoteAddress, const std::string &mangledName, - MangledNameKind kind, - Demangler &dem) { + MangledNameKind kind, Demangler &dem) { StringRef mangledNameCopy = dem.copyString(mangledName); return demangle(RemoteRef(remoteAddress, mangledNameCopy.data()), kind, dem); @@ -607,7 +611,7 @@ class MetadataReader { /// Given a remote pointer to metadata, attempt to discover its MetadataKind. std::optional - readKindFromMetadata(StoredPointer MetadataAddress) { + readKindFromMetadata(RemoteAddress MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta) return std::nullopt; @@ -616,11 +620,10 @@ class MetadataReader { } /// Given a remote pointer to class metadata, attempt to read its superclass. - StoredPointer - readSuperClassFromClassMetadata(StoredPointer MetadataAddress) { + RemoteAddress readSuperClassFromClassMetadata(RemoteAddress MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta || meta->getKind() != MetadataKind::Class) - return StoredPointer(); + return RemoteAddress(); auto classMeta = cast(meta); return stripSignedPointer(classMeta->Superclass); @@ -629,7 +632,7 @@ class MetadataReader { /// 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) { + readInstanceStartFromClassMetadata(RemoteAddress MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta || meta->getKind() != MetadataKind::Class) return std::nullopt; @@ -638,7 +641,7 @@ class MetadataReader { // 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); + RemoteAddress roDataPtr = readObjCRODataPtr(MetadataAddress); if (!roDataPtr) return std::nullopt; @@ -646,7 +649,7 @@ class MetadataReader { auto address = roDataPtr + sizeof(uint32_t) * 1; unsigned start; - if (!Reader->readInteger(RemoteAddress(address), &start)) + if (!Reader->readInteger(address, &start)) return std::nullopt; return start; @@ -676,19 +679,19 @@ class MetadataReader { /// 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) { + readValueWitnessTable(RemoteAddress 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), + if (!Reader->readInteger(ValueWitnessTableAddrAddr, &SignedValueWitnessTableAddr)) return std::nullopt; - auto ValueWitnessTableAddr = stripSignedPointer(SignedValueWitnessTableAddr); - if (!Reader->readBytes(RemoteAddress(ValueWitnessTableAddr), - (uint8_t *)&VWT, sizeof(VWT))) + auto ValueWitnessTableAddr = + stripSignedPointer(SignedValueWitnessTableAddr); + if (!Reader->readBytes(ValueWitnessTableAddr, (uint8_t *)&VWT, sizeof(VWT))) return std::nullopt; return VWT; } @@ -700,8 +703,7 @@ class MetadataReader { std::optional readMetadataAndValueErrorExistential(RemoteAddress ExistentialAddress) { // An pointer to an error existential is always an heap object. - auto MetadataAddress = - readMetadataFromInstance(ExistentialAddress.getAddressData()); + auto MetadataAddress = readMetadataFromInstance(ExistentialAddress); if (!MetadataAddress) return std::nullopt; @@ -730,18 +732,15 @@ class MetadataReader { if (isBridged) { // NSError instances don't need to be unwrapped. - return RemoteExistential(RemoteAddress(*MetadataAddress), - ExistentialAddress, - isBridged); + return RemoteExistential(*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); + RemoteAddress InstanceMetadataAddressAddress = + ExistentialAddress + (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. @@ -757,7 +756,7 @@ class MetadataReader { // Now we need to skip over the instance metadata pointer and instance's // conformance pointer for Swift.Error. - StoredPointer InstanceAddress = + RemoteAddress InstanceAddress = InstanceMetadataAddressAddress + 2 * sizeof(StoredPointer); // When built with Objective-C interop, the runtime also stores a conformance @@ -770,10 +769,8 @@ class MetadataReader { auto AlignmentMask = VWT->getAlignmentMask(); InstanceAddress = (InstanceAddress + AlignmentMask) & ~AlignmentMask; - return RemoteExistential( - RemoteAddress(*InstanceMetadataAddress), - RemoteAddress(InstanceAddress), - isBridged); + return RemoteExistential(*InstanceMetadataAddress, InstanceAddress, + isBridged); } /// Given a known-opaque existential, attempt to discover the pointer to its @@ -783,10 +780,11 @@ class MetadataReader { // 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))) + if (!Reader->readBytes(ExistentialAddress, (uint8_t *)&Container, + sizeof(Container))) return std::nullopt; - auto MetadataAddress = static_cast(Container.Type); + auto MetadataAddress = + RemoteAddress(Container.Type, ExistentialAddress.getAddressSpace()); auto Metadata = readMetadata(MetadataAddress); if (!Metadata) return std::nullopt; @@ -798,20 +796,19 @@ class MetadataReader { // 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); + return RemoteExistential(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)) + RemoteAddress BoxAddress; + if (!Reader->readRemoteAddress(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)); + return RemoteExistential(MetadataAddress, StartOfValue); } /// Given a known-opaque existential, discover if its value is inlined in @@ -821,10 +818,12 @@ class MetadataReader { // 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))) + if (!Reader->readBytes(ExistentialAddress, (uint8_t *)&Container, + sizeof(Container))) return std::nullopt; - auto MetadataAddress = static_cast(Container.Type); + auto MetadataAddress = + RemoteAddress(Container.Type, ExistentialAddress.getAddressSpace()); + auto Metadata = readMetadata(MetadataAddress); if (!Metadata) return std::nullopt; @@ -837,11 +836,10 @@ class MetadataReader { } /// Read a protocol from a reference to said protocol. - template + template typename Resolver::Result readProtocol( - const TargetProtocolDescriptorRef &ProtocolAddress, - Demangler &dem, - Resolver resolver) { + const RemoteTargetProtocolDescriptorRef &ProtocolAddress, + Demangler &dem, Resolver resolver) { #if SWIFT_OBJC_INTEROP if (Runtime::ObjCInterop) { // Check whether we have an Objective-C protocol. @@ -877,8 +875,7 @@ class MetadataReader { #endif // Swift-native protocol. - auto Demangled = - readDemanglingForContextDescriptor( + auto Demangled = readDemanglingForContextDescriptor( stripSignedPointer({ProtocolAddress.getSwiftProtocol()}), dem); if (!Demangled) return resolver.failure(); @@ -888,10 +885,10 @@ class MetadataReader { /// Given a remote pointer to metadata, attempt to turn it into a type. BuiltType - readTypeFromMetadata(StoredPointer MetadataAddress, + readTypeFromMetadata(RemoteAddress MetadataAddress, bool skipArtificialSubclasses = false, int recursion_limit = defaultTypeRecursionLimit) { - std::pair TypeCacheKey(MetadataAddress, + std::pair TypeCacheKey(MetadataAddress, skipArtificialSubclasses); auto Cached = TypeCache.find(TypeCacheKey); if (Cached != TypeCache.end()) @@ -934,17 +931,20 @@ class MetadataReader { for (unsigned i = 0, n = tupleMeta->NumElements; i != n; ++i) { auto &element = tupleMeta->getElement(i); - if (auto elementType = - readTypeFromMetadata(element.Type, false, recursion_limit)) + auto elementTypeAddress = + RemoteAddress(element.Type, MetadataAddress.getAddressSpace()); + if (auto elementType = readTypeFromMetadata(elementTypeAddress, false, + recursion_limit)) elementTypes.push_back(elementType); else return BuiltType(); } // Read the labels string. + auto labelAddress = + RemoteAddress(tupleMeta->Labels, MetadataAddress.getAddressSpace()); std::string labelStr; - if (tupleMeta->Labels && - !Reader->readString(RemoteAddress(tupleMeta->Labels), labelStr)) + if (labelAddress && !Reader->readString(labelAddress, labelStr)) return BuiltType(); std::vector labels; @@ -970,8 +970,10 @@ class MetadataReader { std::vector> Parameters; for (unsigned i = 0, n = Function->getNumParameters(); i != n; ++i) { - auto ParamTypeRef = readTypeFromMetadata(Function->getParameter(i), - false, recursion_limit); + auto paramAddress = RemoteAddress(Function->getParameter(i), + MetadataAddress.getAddressSpace()); + auto ParamTypeRef = + readTypeFromMetadata(paramAddress, false, recursion_limit); if (!ParamTypeRef) return BuiltType(); @@ -981,8 +983,10 @@ class MetadataReader { Parameters.push_back(std::move(Param)); } + auto resultTypeAddress = RemoteAddress(Function->ResultType, + MetadataAddress.getAddressSpace()); auto Result = - readTypeFromMetadata(Function->ResultType, false, recursion_limit); + readTypeFromMetadata(resultTypeAddress, false, recursion_limit); if (!Result) return BuiltType(); @@ -994,8 +998,10 @@ class MetadataReader { BuiltType globalActor = BuiltType(); if (Function->hasGlobalActor()) { - globalActor = readTypeFromMetadata(Function->getGlobalActor(), false, - recursion_limit); + auto globalActorAddress = RemoteAddress( + Function->getGlobalActor(), MetadataAddress.getAddressSpace()); + globalActor = + readTypeFromMetadata(globalActorAddress, false, recursion_limit); if (!globalActor) return BuiltType(); } @@ -1017,8 +1023,10 @@ class MetadataReader { BuiltType thrownError = BuiltType(); if (Function->hasThrownError()) { - thrownError = readTypeFromMetadata(Function->getThrownError(), false, - recursion_limit); + auto thrownErrorAddress = RemoteAddress( + Function->getThrownError(), MetadataAddress.getAddressSpace()); + thrownError = + readTypeFromMetadata(thrownErrorAddress, false, recursion_limit); if (!thrownError) return BuiltType(); } @@ -1037,9 +1045,12 @@ class MetadataReader { BuiltType SuperclassType = BuiltType(); if (Exist->Flags.hasSuperclassConstraint()) { + auto superclassContraintAddress = + RemoteAddress(Exist->getSuperclassConstraint(), + MetadataAddress.getAddressSpace()); // The superclass is stored after the list of protocols. - SuperclassType = readTypeFromMetadata(Exist->getSuperclassConstraint(), - false, recursion_limit); + SuperclassType = readTypeFromMetadata(superclassContraintAddress, false, + recursion_limit); if (!SuperclassType) return BuiltType(); HasExplicitAnyObject = true; @@ -1069,7 +1080,10 @@ class MetadataReader { Demangler dem; std::vector Protocols; for (auto ProtocolAddress : Exist->getProtocols()) { - if (auto Protocol = readProtocol(ProtocolAddress, dem, resolver)) + auto ProtocolRef = RemoteTargetProtocolDescriptorRef( + RemoteAddress(ProtocolAddress.getRawData(), + MetadataAddress.getAddressSpace())); + if (auto Protocol = readProtocol(ProtocolRef, dem, resolver)) Protocols.push_back(Protocol); else return BuiltType(); @@ -1083,7 +1097,7 @@ class MetadataReader { auto Exist = cast>(Meta); // Read the shape for this existential. - StoredPointer shapeAddress = stripSignedPointer(Exist->Shape); + RemoteAddress shapeAddress = stripSignedPointer(Exist->Shape); ShapeRef Shape = readShape(shapeAddress); if (!Shape) return BuiltType(); @@ -1095,7 +1109,10 @@ class MetadataReader { std::vector builtArgs; for (unsigned i = 0; i < shapeArgumentCount; ++i) { auto remoteArg = Exist->getGeneralizationArguments()[i]; - auto builtArg = readTypeFromMetadata(remoteArg, false, recursion_limit); + auto remoteArgAddress = + RemoteAddress(remoteArg, MetadataAddress.getAddressSpace()); + auto builtArg = + readTypeFromMetadata(remoteArgAddress, false, recursion_limit); if (!builtArg) return BuiltType(); builtArgs.push_back(builtArg); @@ -1105,8 +1122,8 @@ class MetadataReader { Demangler dem; auto mangledExistentialAddr = resolveRelativeField(Shape, Shape->ExistentialType); - auto node = readMangledName(RemoteAddress(mangledExistentialAddr), - MangledNameKind::Type, dem); + auto node = + readMangledName(mangledExistentialAddr, MangledNameKind::Type, dem); if (!node) return BuiltType(); @@ -1140,8 +1157,8 @@ class MetadataReader { auto mangledContextName = Shape->getTypeExpression(); auto mangledNameAddress = resolveRelativeField(Shape, mangledContextName->name); - auto node = readMangledName(RemoteAddress(mangledNameAddress), - MangledNameKind::Type, dem); + auto node = + readMangledName(mangledNameAddress, MangledNameKind::Type, dem); if (!node) return BuiltType(); @@ -1160,8 +1177,10 @@ class MetadataReader { case MetadataKind::Metatype: { auto Metatype = cast>(Meta); + auto InstanceTypeAddress = RemoteAddress( + Metatype->InstanceType, MetadataAddress.getAddressSpace()); auto Instance = - readTypeFromMetadata(Metatype->InstanceType, false, recursion_limit); + readTypeFromMetadata(InstanceTypeAddress, false, recursion_limit); if (!Instance) return BuiltType(); auto BuiltMetatype = Builder.createMetatypeType(Instance); TypeCache[TypeCacheKey] = BuiltMetatype; @@ -1169,7 +1188,8 @@ class MetadataReader { } case MetadataKind::ObjCClassWrapper: { auto objcWrapper = cast>(Meta); - auto classAddress = objcWrapper->Class; + auto classAddress = + RemoteAddress(objcWrapper->Class, MetadataAddress.getAddressSpace()); std::string className; if (!readObjCClassName(classAddress, className)) @@ -1181,8 +1201,10 @@ class MetadataReader { } case MetadataKind::ExistentialMetatype: { auto Exist = cast>(Meta); + auto classAddress = + RemoteAddress(Exist->InstanceType, MetadataAddress.getAddressSpace()); auto Instance = - readTypeFromMetadata(Exist->InstanceType, false, recursion_limit); + readTypeFromMetadata(classAddress, false, recursion_limit); if (!Instance) return BuiltType(); auto BuiltExist = Builder.createExistentialMetatypeType(Instance); TypeCache[TypeCacheKey] = BuiltExist; @@ -1263,8 +1285,13 @@ class MetadataReader { switch (req.Flags.getKind()) { case GenericRequirementKind::SameType: { Demangler rdem; + // FIXME: This should not work since the mangled name pointer is on the + // local process. + auto mangledNameAddress = + RemoteAddress((uint64_t)req.getMangledTypeName().data(), + RemoteAddress::DefaultAddressSpace); auto demangledConstraint = - demangle(RemoteRef(req.getMangledTypeName().data(), + demangle(RemoteRef(mangledNameAddress, req.getMangledTypeName().data()), MangledNameKind::Type, rdem); auto constraintType = decodeMangledType(demangledConstraint); @@ -1305,7 +1332,9 @@ class MetadataReader { Demangler dem; auto protocolAddress = resolveRelativeIndirectProtocol(contextRef, req.Protocol); - auto protocol = readProtocol(protocolAddress, dem, resolver); + auto protocolRef = + RemoteTargetProtocolDescriptorRef(protocolAddress); + auto protocol = readProtocol(protocolRef, dem, resolver); if (!protocol) { return TypeLookupError("Failed to read protocol type in conformance " "requirement of runtime generic signature."); @@ -1317,8 +1346,13 @@ class MetadataReader { } case GenericRequirementKind::BaseClass: { Demangler rdem; + // FIXME: This should not work since the mangled name pointer is on the + // local process. + auto mangledNameAddress = + RemoteAddress((uint64_t)req.getMangledTypeName().data(), + RemoteAddress::DefaultAddressSpace); auto demangledConstraint = - demangle(RemoteRef(req.getMangledTypeName().data(), + demangle(RemoteRef(mangledNameAddress, req.getMangledTypeName().data()), MangledNameKind::Type, rdem); auto constraintType = decodeMangledType(demangledConstraint); @@ -1366,14 +1400,13 @@ class MetadataReader { if (address.getOffset() == 0) return ParentContextDescriptorRef(address.getSymbol()); } - + return ParentContextDescriptorRef( - readContextDescriptor(address.getResolvedAddress().getAddressData())); + readContextDescriptor(address.getResolvedAddress())); } - ShapeRef - readShape(StoredPointer address) { - if (address == 0) + ShapeRef readShape(RemoteAddress address) { + if (!address) return nullptr; auto cached = ShapeCache.find(address); @@ -1383,8 +1416,7 @@ class MetadataReader { cached->second.get())); ExtendedExistentialTypeShapeFlags flags; - if (!Reader->readBytes(RemoteAddress(address), (uint8_t*)&flags, - sizeof(flags))) + if (!Reader->readBytes(address, (uint8_t *)&flags, sizeof(flags))) return nullptr; // Read the size of the requirement signature. @@ -1394,8 +1426,7 @@ class MetadataReader { GenericContextDescriptorHeader header; auto headerAddr = address + sizeof(flags); - if (!Reader->readBytes(RemoteAddress(headerAddr), - (uint8_t*)&header, sizeof(header))) + if (!Reader->readBytes(headerAddr, (uint8_t *)&header, sizeof(header))) return nullptr; reqSigGenericSize = reqSigGenericSize @@ -1413,7 +1444,7 @@ class MetadataReader { reqSigGenericSize; if (size > MaxMetadataSize) return nullptr; - auto readResult = Reader->readBytes(RemoteAddress(address), size); + auto readResult = Reader->readBytes(address, size); if (!readResult) return nullptr; @@ -1427,22 +1458,21 @@ class MetadataReader { } /// Given the address of a context descriptor, attempt to read it. - ContextDescriptorRef - readContextDescriptor(StoredPointer address) { - if (address == 0) + ContextDescriptorRef readContextDescriptor(RemoteAddress remoteAddress) { + if (!remoteAddress) return nullptr; - auto remoteAddress = RemoteAddress(address); auto ptr = Reader->readBytes(remoteAddress, sizeof(TargetContextDescriptor)); if (!ptr) return nullptr; - auto cached = ContextDescriptorCache.find(address); + auto cached = ContextDescriptorCache.find(remoteAddress); if (cached != ContextDescriptorCache.end()) return ContextDescriptorRef( - address, reinterpret_cast *>( - cached->second.get())); + remoteAddress, + reinterpret_cast *>( + cached->second.get())); bool success = false; switch ( @@ -1492,8 +1522,9 @@ class MetadataReader { auto *descriptor = reinterpret_cast *>(ptr.get()); - ContextDescriptorCache.insert(std::make_pair(address, std::move(ptr))); - return ContextDescriptorRef(address, descriptor); + ContextDescriptorCache.insert( + std::make_pair(remoteAddress, std::move(ptr))); + return ContextDescriptorRef(remoteAddress, descriptor); } template @@ -1606,19 +1637,17 @@ class MetadataReader { /// Read a context descriptor from the given address and build a mangling /// tree representing it. Demangle::NodePointer - readDemanglingForContextDescriptor(StoredPointer contextAddress, + readDemanglingForContextDescriptor(RemoteAddress 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) { + Demangle::NodePointer readUnderlyingTypeManglingForOpaqueTypeDescriptor( + RemoteAddress contextAddr, unsigned ordinal, Demangler &Dem) { auto context = readContextDescriptor(contextAddr); if (!context) return nullptr; @@ -1634,13 +1663,12 @@ class MetadataReader { auto nameAddr = resolveRelativeField(context, opaqueType->getUnderlyingTypeArgumentMangledName(ordinal)); - - return readMangledName(RemoteAddress(nameAddr), - MangledNameKind::Type, Dem); + + return readMangledName(nameAddr, MangledNameKind::Type, Dem); } TypeLookupErrorOr - readUnderlyingTypeForOpaqueTypeDescriptor(StoredPointer contextAddr, + readUnderlyingTypeForOpaqueTypeDescriptor(RemoteAddress contextAddr, unsigned ordinal) { Demangle::Demangler Dem; auto node = readUnderlyingTypeManglingForOpaqueTypeDescriptor(contextAddr, @@ -1650,31 +1678,33 @@ class MetadataReader { return decodeMangledType(node); } - bool isTaggedPointer(StoredPointer objectAddress) { + bool isTaggedPointer(RemoteAddress objectAddress) { if (getTaggedPointerEncoding() != TaggedPointerEncodingKind::Extended) return false; - - return (objectAddress ^ TaggedPointerObfuscator) & TaggedPointerMask; + + return (bool)((objectAddress ^ TaggedPointerObfuscator) & + TaggedPointerMask); } /// Read the isa pointer of an Object-C tagged pointer value. - std::optional - readMetadataFromTaggedPointer(StoredPointer objectAddress) { + std::optional + readMetadataFromTaggedPointer(RemoteAddress objectAddress) { auto readArrayElement = - [&](StoredPointer base, - StoredPointer tag) -> std::optional { - StoredPointer addr = base + tag * sizeof(StoredPointer); - StoredPointer isa; - if (!Reader->readInteger(RemoteAddress(addr), &isa)) + [&](RemoteAddress base, + StoredPointer tag) -> std::optional { + RemoteAddress addr = base + tag * sizeof(StoredPointer); + RemoteAddress isa; + if (!Reader->readRemoteAddress(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)) { + if (TaggedPointerExtendedMask && + ((((StoredPointer)objectAddress.getRawAddress() ^ + TaggedPointerObfuscator) & + TaggedPointerExtendedMask) == TaggedPointerExtendedMask)) { auto tag = ((objectAddress >> TaggedPointerExtendedSlotShift) & TaggedPointerExtendedSlotMask); return readArrayElement(TaggedPointerExtendedClasses, tag); @@ -1688,13 +1718,13 @@ class MetadataReader { /// Read the isa pointer of a class or closure context instance and apply /// the isa mask. - std::optional - readMetadataFromInstance(StoredPointer objectAddress) { + std::optional + readMetadataFromInstance(RemoteAddress objectAddress) { if (isTaggedPointer(objectAddress)) return readMetadataFromTaggedPointer(objectAddress); - StoredPointer isa; - if (!Reader->readInteger(RemoteAddress(objectAddress), &isa)) + RemoteAddress isa; + if (!Reader->readRemoteAddress(objectAddress, isa)) return std::nullopt; switch (getIsaEncoding()) { @@ -1711,11 +1741,12 @@ class MetadataReader { 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) + if (((StoredPointer)(isa & IsaMagicMask).getRawAddress()) != + IsaMagicValue) return isa; // Extract the index. - auto classIndex = (isa & IsaIndexMask) >> IsaIndexShift; + StoredPointer classIndex = (isa & IsaIndexMask) >> IsaIndexShift; // 0 is never a valid index. if (classIndex == 0) { @@ -1741,10 +1772,10 @@ class MetadataReader { RemoteAddress eltPointer = RemoteAddress(IndexedClassesPointer + classIndex * sizeof(StoredPointer)); - StoredPointer metadataPointer; - if (!Reader->readInteger(eltPointer, &metadataPointer)) { + RemoteAddress metadataPointer; + if (!Reader->readRemoteAddress(eltPointer, + metadataPointer)) return std::nullopt; - } return metadataPointer; } @@ -1845,7 +1876,7 @@ class MetadataReader { return cls->getClassBoundsAsSwiftSuperclass(); }, - [](StoredPointer objcClassName) + [](RemoteAddress 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. @@ -1863,14 +1894,14 @@ class MetadataReader { template std::optional forTypeReference(TypeReferenceKind refKind, - StoredPointer ref, + RemoteAddress ref, const DescriptorFn &descriptorFn, const MetadataFn &metadataFn, const ClassNameFn &classNameFn) { switch (refKind) { case TypeReferenceKind::IndirectTypeDescriptor: { StoredSignedPointer descriptorAddress; - if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress)) { + if (!Reader->readInteger(ref, &descriptorAddress)) { return std::nullopt; } @@ -1890,8 +1921,8 @@ class MetadataReader { return classNameFn(ref); case TypeReferenceKind::IndirectObjCClass: { - StoredPointer classRef = 0; - if (!Reader->readInteger(RemoteAddress(ref), &classRef)) + RemoteAddress classRef; + if (!Reader->readRemoteAddress(ref, classRef)) return std::nullopt; auto metadata = readMetadata(classRef); @@ -1907,8 +1938,8 @@ class MetadataReader { /// Read a single generic type argument from a bound generic type /// metadata. - std::optional - readGenericArgFromMetadata(StoredPointer metadata, unsigned index) { + std::optional + readGenericArgFromMetadata(RemoteAddress metadata, unsigned index) { auto Meta = readMetadata(metadata); if (!Meta) return std::nullopt; @@ -1938,9 +1969,9 @@ class MetadataReader { if (index >= generics->getGenericContextHeader().getNumArguments()) return std::nullopt; - StoredPointer genericArgAddress; - if (!Reader->readInteger(RemoteAddress(addressOfGenericArgAddress), - &genericArgAddress)) + RemoteAddress genericArgAddress; + if (!Reader->readRemoteAddress(addressOfGenericArgAddress, + genericArgAddress)) return std::nullopt; return genericArgAddress; @@ -1948,7 +1979,7 @@ class MetadataReader { /// Given the address of a nominal type descriptor, attempt to resolve /// its nominal type declaration. - BuiltTypeDecl readNominalTypeFromDescriptor(StoredPointer address) { + BuiltTypeDecl readNominalTypeFromDescriptor(RemoteAddress address) { auto descriptor = readContextDescriptor(address); if (!descriptor) return BuiltTypeDecl(); @@ -1957,7 +1988,7 @@ class MetadataReader { } /// Try to read the offset of a tuple element from a tuple metadata. - bool readTupleElementOffset(StoredPointer metadataAddress, unsigned eltIndex, + bool readTupleElementOffset(RemoteAddress metadataAddress, unsigned eltIndex, StoredSize *offset) { // Read the metadata. auto metadata = readMetadata(metadataAddress); @@ -1981,7 +2012,7 @@ class MetadataReader { /// Given a remote pointer to class metadata, attempt to read its superclass. std::optional - readOffsetToFirstCaptureFromMetadata(StoredPointer MetadataAddress) { + readOffsetToFirstCaptureFromMetadata(RemoteAddress MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta || meta->getKind() != MetadataKind::HeapLocalVariable) return std::nullopt; @@ -1990,15 +2021,15 @@ class MetadataReader { return heapMeta->OffsetToFirstCapture; } - std::optional readPointer(StoredPointer address) { - return Reader->readPointer(RemoteAddress(address), sizeof(StoredPointer)); + std::optional readPointer(RemoteAddress address) { + return Reader->readPointer(address, sizeof(StoredPointer)); } - std::optional readResolvedPointerValue(StoredPointer address) { + std::optional readResolvedPointerValue(RemoteAddress address) { if (auto pointer = readPointer(address)) { if (!pointer->getResolvedAddress()) return std::nullopt; - return (StoredPointer)pointer->getResolvedAddress().getAddressData(); + return pointer->getResolvedAddress(); } return std::nullopt; } @@ -2007,13 +2038,13 @@ class MetadataReader { RemoteAbsolutePointer resolvePointerField(RemoteRef base, const U &field) { auto pointerRef = base.getField(field); - return Reader->resolvePointer(RemoteAddress(getAddress(pointerRef)), + return Reader->resolvePointer(getAddress(pointerRef), *pointerRef.getLocalBuffer()); } /// Given a remote pointer to class metadata, attempt to read its superclass. std::optional - readCaptureDescriptorFromMetadata(StoredPointer MetadataAddress) { + readCaptureDescriptorFromMetadata(RemoteAddress MetadataAddress) { auto meta = readMetadata(MetadataAddress); if (!meta || meta->getKind() != MetadataKind::HeapLocalVariable) return std::nullopt; @@ -2023,15 +2054,14 @@ class MetadataReader { } protected: - template - StoredPointer getAddress(RemoteRef base) { - return (StoredPointer)base.getAddressData(); + template + RemoteAddress getAddress(RemoteRef base) { + return base.getRemoteAddress(); } - - template - StoredPointer resolveRelativeField( - RemoteRef base, const Field &field) { - return (StoredPointer)base.resolveRelativeFieldData(field); + + template + RemoteAddress resolveRelativeField(RemoteRef base, const Field &field) { + return base.resolveRelativeFieldData(field); } template @@ -2047,9 +2077,9 @@ class MetadataReader { offset &= ~1u; using SignedPointer = typename std::make_signed::type; - - StoredPointer resultAddress = getAddress(fieldRef) + (SignedPointer)offset; - + + RemoteAddress resultAddress = getAddress(fieldRef) + (SignedPointer)offset; + // Low bit set in the offset indicates that the offset leads to the absolute // address in memory. if (indirect) { @@ -2058,16 +2088,16 @@ class MetadataReader { } return std::nullopt; } - - return RemoteAbsolutePointer(RemoteAddress(resultAddress)); + + return RemoteAbsolutePointer(resultAddress); } /// Given a pointer to an Objective-C class, try to read its class name. - bool readObjCClassName(StoredPointer classAddress, std::string &className) { + bool readObjCClassName(RemoteAddress 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); + RemoteAddress roDataPtr = readObjCRODataPtr(classAddress); if (!roDataPtr) return false; // This is ABI. @@ -2076,18 +2106,19 @@ class MetadataReader { + sizeof(StoredPointer); // Read the name pointer. - StoredPointer namePtr; - if (!Reader->readInteger(RemoteAddress(roDataPtr + OffsetToName), &namePtr)) + RemoteAddress namePtr; + if (!Reader->readRemoteAddress(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); + return Reader->readString(namePtr, className); } - MetadataRef readMetadata(StoredPointer address) { + MetadataRef readMetadata(RemoteAddress address) { auto cached = MetadataCache.find(address); if (cached != MetadataCache.end()) return MetadataRef(address, @@ -2095,7 +2126,7 @@ class MetadataReader { cached->second.get())); StoredPointer KindValue = 0; - if (!Reader->readInteger(RemoteAddress(address), &KindValue)) + if (!Reader->readInteger(address, &KindValue)) return nullptr; switch (getEnumeratedMetadataKind(KindValue)) { @@ -2108,20 +2139,17 @@ class MetadataReader { case MetadataKind::ErrorObject: return _readMetadata(address); case MetadataKind::Existential: { - StoredPointer flagsAddress = address + - sizeof(StoredPointer); + RemoteAddress flagsAddress = address + sizeof(StoredPointer); ExistentialTypeFlags::int_type flagsData; - if (!Reader->readInteger(RemoteAddress(flagsAddress), - &flagsData)) + if (!Reader->readInteger(flagsAddress, &flagsData)) return nullptr; ExistentialTypeFlags flags(flagsData); - StoredPointer numProtocolsAddress = flagsAddress + sizeof(flagsData); + RemoteAddress numProtocolsAddress = flagsAddress + sizeof(flagsData); uint32_t numProtocols; - if (!Reader->readInteger(RemoteAddress(numProtocolsAddress), - &numProtocols)) + if (!Reader->readInteger(numProtocolsAddress, &numProtocols)) return nullptr; // Make sure the number of protocols is reasonable @@ -2142,9 +2170,10 @@ class MetadataReader { 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)) + RemoteAddress shapeAddress = address + sizeof(StoredPointer); + RemoteAddress signedShapePtr; + if (!Reader->readRemoteAddress(shapeAddress, + signedShapePtr)) return nullptr; auto shapePtr = stripSignedPointer(signedShapePtr); @@ -2166,7 +2195,7 @@ class MetadataReader { StoredSize flagsValue; auto flagsAddr = address + TargetFunctionTypeMetadata::OffsetToFlags; - if (!Reader->readInteger(RemoteAddress(flagsAddr), &flagsValue)) + if (!Reader->readInteger(flagsAddr, &flagsValue)) return nullptr; auto flags = @@ -2203,8 +2232,7 @@ class MetadataReader { auto numElementsAddress = address + TargetTupleTypeMetadata::getOffsetToNumElements(); StoredSize numElements; - if (!Reader->readInteger(RemoteAddress(numElementsAddress), - &numElements)) + if (!Reader->readInteger(numElementsAddress, &numElements)) return nullptr; auto totalSize = sizeof(TargetTupleTypeMetadata) + numElements * sizeof(TupleTypeMetadata::Element); @@ -2225,7 +2253,7 @@ class MetadataReader { return nullptr; } - StoredPointer + RemoteAddress readAddressOfNominalTypeDescriptor(MetadataRef &metadata, bool skipArtificialSubclasses = false) { switch (metadata->getKind()) { @@ -2233,28 +2261,29 @@ class MetadataReader { auto classMeta = cast(metadata); while (true) { if (!classMeta->isTypeMetadata()) - return 0; + return RemoteAddress(); StoredSignedPointer descriptorAddressSigned = classMeta->getDescriptionAsSignedPointer(); - StoredPointer descriptorAddress = stripSignedPointer(descriptorAddressSigned); + RemoteAddress 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); + return descriptorAddress; auto superclassMetadataAddress = stripSignedPointer(classMeta->Superclass); if (!superclassMetadataAddress) - return 0; + return RemoteAddress(); auto superMeta = readMetadata(superclassMetadataAddress); if (!superMeta) - return 0; + return RemoteAddress(); auto superclassMeta = dyn_cast(superMeta); if (!superclassMeta) - return 0; + return RemoteAddress(); classMeta = superclassMeta; metadata = superMeta; @@ -2266,39 +2295,42 @@ class MetadataReader { case MetadataKind::Enum: { auto valueMeta = cast>(metadata); StoredSignedPointer descriptorAddressSigned = valueMeta->getDescriptionAsSignedPointer(); - StoredPointer descriptorAddress = stripSignedPointer(descriptorAddressSigned); + RemoteAddress descriptorAddress = + stripSignedPointer(descriptorAddressSigned); return descriptorAddress; } case MetadataKind::ForeignClass: { auto foreignMeta = cast>(metadata); StoredSignedPointer descriptorAddressSigned = foreignMeta->getDescriptionAsSignedPointer(); - StoredPointer descriptorAddress = stripSignedPointer(descriptorAddressSigned); + RemoteAddress descriptorAddress = + stripSignedPointer(descriptorAddressSigned); return descriptorAddress; } case MetadataKind::ForeignReferenceType: { auto foreignMeta = cast>(metadata); StoredSignedPointer descriptorAddressSigned = foreignMeta->getDescriptionAsSignedPointer(); - StoredPointer descriptorAddress = stripSignedPointer(descriptorAddressSigned); + RemoteAddress descriptorAddress = + stripSignedPointer(descriptorAddressSigned); return descriptorAddress; } default: - return 0; + return RemoteAddress(); } } private: template