[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.

rdar://160837587
This commit is contained in:
Augusto Noronha
2025-10-23 11:18:32 -07:00
parent c4af8bf74d
commit 266adaf1ea
2 changed files with 23 additions and 5 deletions

View File

@@ -192,6 +192,20 @@ public:
return ReadObjResult<T>(reinterpret_cast<const T *>(ptr), deleter); return ReadObjResult<T>(reinterpret_cast<const T *>(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. /// 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 /// Returns a pointer to the requested data and a function that must be called to

View File

@@ -457,18 +457,20 @@ public:
swift::Demangle::NodePointer { swift::Demangle::NodePointer {
// Resolve the reference to a remote address. // Resolve the reference to a remote address.
auto offsetInMangledName = auto offsetInMangledName =
(const char *)base - mangledName.getLocalBuffer(); (const char *)base - mangledName.getLocalBuffer();
auto remoteAddress = auto offsetAddress = mangledName.getRemoteAddress() + offsetInMangledName;
mangledName.getRemoteAddress() + offsetInMangledName + offset;
RemoteAbsolutePointer resolved; RemoteAbsolutePointer resolved;
if (directness == Directness::Indirect) { if (directness == Directness::Indirect) {
auto remoteAddress = Reader->resolveIndirectAddressAtOffset(
offsetAddress, offset, /*directnessEncodedInOffset=*/false);
if (auto indirectAddress = readPointer(remoteAddress)) { if (auto indirectAddress = readPointer(remoteAddress)) {
resolved = stripSignedPointer(*indirectAddress); resolved = stripSignedPointer(*indirectAddress);
} else { } else {
return nullptr; return nullptr;
} }
} else { } else {
auto remoteAddress = offsetAddress + offset;
resolved = Reader->getSymbol(remoteAddress); resolved = Reader->getSymbol(remoteAddress);
} }
@@ -2084,17 +2086,19 @@ protected:
using SignedPointer = typename std::make_signed<StoredPointer>::type; using SignedPointer = typename std::make_signed<StoredPointer>::type;
RemoteAddress resultAddress = getAddress(fieldRef) + (SignedPointer)offset;
// Low bit set in the offset indicates that the offset leads to the absolute // Low bit set in the offset indicates that the offset leads to the absolute
// address in memory. // address in memory.
if (indirect) { if (indirect) {
RemoteAddress resultAddress = Reader->resolveIndirectAddressAtOffset(
getAddress(fieldRef), (SignedPointer)offset,
/*directnessEncodedInOffset=*/true);
if (auto ptr = readPointer(resultAddress)) { if (auto ptr = readPointer(resultAddress)) {
return stripSignedPointer(*ptr); return stripSignedPointer(*ptr);
} }
return std::nullopt; return std::nullopt;
} }
RemoteAddress resultAddress = getAddress(fieldRef) + (SignedPointer)offset;
return RemoteAbsolutePointer(resultAddress); return RemoteAbsolutePointer(resultAddress);
} }