From 98a0a3fcac39e32ec2420927d7b3cf5bf40691c8 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Thu, 23 Oct 2025 11:18:32 -0700 Subject: [PATCH] [RemoteMirrors] Add hook for resolving indirect addresses Adds a hook so implementations of memory reader can add logic to resolving remote addresses. This is needed because of an interaction between LLDB, which tries to read memory from files instead of process memory whenever possible and the DYLD shared cache. The shared cache will merge pointers in the GOT sections from multiple images into one location, and update the relative offsets to point to the new location. LLDB, will have initially read the offset pointing to the "old" location, which will be zeroed out in live memory. This gives LLDB the opportunity to re-read the relative offset, but from live memory, so it can return the right pointer in the shared cache. (cherry picked from commit 0f4a3ceb67a3669cd5433d5ae13fec6852876173) rdar://163652093 --- include/swift/Remote/MemoryReader.h | 14 ++++++++++++++ include/swift/Remote/MetadataReader.h | 14 +++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/swift/Remote/MemoryReader.h b/include/swift/Remote/MemoryReader.h index 88d58d1ee6e60..dc192270cd408 100644 --- a/include/swift/Remote/MemoryReader.h +++ b/include/swift/Remote/MemoryReader.h @@ -121,6 +121,20 @@ class MemoryReader { return ReadObjResult(reinterpret_cast(ptr), deleter); } + /// Resolves an indirect address at the given relative offset. + /// + /// \param address The base address which contains the relative offset. + /// \param offset The offset read. + /// \param directnessEncodedInOffset Whether the relative offset encodes the + /// directness as the last bit. Note that this is not the offset passed in as + /// a parameter, but whether the offset read at address would have the last + /// bit set. + virtual RemoteAddress + resolveIndirectAddressAtOffset(RemoteAddress address, uint64_t offset, + bool directnessEncodedInOffset) { + return address + offset; + } + /// Attempts to read 'size' bytes from the given address in the remote process. /// /// Returns a pointer to the requested data and a function that must be called to diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index d156ff67b3cf4..d8ecfbb2749a1 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -461,18 +461,20 @@ class MetadataReader { swift::Demangle::NodePointer { // Resolve the reference to a remote address. auto offsetInMangledName = - (const char *)base - mangledName.getLocalBuffer(); - auto remoteAddress = - mangledName.getRemoteAddress() + offsetInMangledName + offset; + (const char *)base - mangledName.getLocalBuffer(); + auto offsetAddress = mangledName.getRemoteAddress() + offsetInMangledName; RemoteAbsolutePointer resolved; if (directness == Directness::Indirect) { + auto remoteAddress = Reader->resolveIndirectAddressAtOffset( + offsetAddress, offset, /*directnessEncodedInOffset=*/false); if (auto indirectAddress = readPointer(remoteAddress)) { resolved = stripSignedPointer(*indirectAddress); } else { return nullptr; } } else { + auto remoteAddress = offsetAddress + offset; resolved = Reader->getSymbol(remoteAddress); } @@ -2078,17 +2080,19 @@ class MetadataReader { using SignedPointer = typename std::make_signed::type; - 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) { + RemoteAddress resultAddress = Reader->resolveIndirectAddressAtOffset( + getAddress(fieldRef), (SignedPointer)offset, + /*directnessEncodedInOffset=*/true); if (auto ptr = readPointer(resultAddress)) { return stripSignedPointer(*ptr); } return std::nullopt; } + RemoteAddress resultAddress = getAddress(fieldRef) + (SignedPointer)offset; return RemoteAbsolutePointer(resultAddress); }