MetadataReader: Add an API for reading absolute pointers.

Pointer data in some remote reflection targets may required relocation, or may not be
fully resolvable, such as when we're dumping info from a single image on disk that
references other dynamic libraries. Add a `RemoteAbsolutePointer` type that can hold a
symbol, offset, or combination of both, and add APIs to `MemoryReader` and `MetadataReader`
for reading pointers that can get unresolved relocation info from an image, or apply
relocations to pointer information. MetadataReader can use the symbol name information to
fill in demanglings of symbolic-reference-bearing mangled names by using the information
from the symbol name to fill in the name even though the context descriptors are not
available.

For now, this is NFC (MemoryReader::resolvePointer just forwards the pointer data), but
lays the groundwork for implementation of relocation in ObjectMemoryReader.
This commit is contained in:
Joe Groff
2019-09-28 16:53:34 -07:00
parent 11b2c29125
commit 4012a207c8
6 changed files with 305 additions and 95 deletions

View File

@@ -433,27 +433,27 @@ struct MembersHelper<> {
LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_ALWAYS_INLINE
static void copyConstruct(void *self, int index, const void *other) { static void copyConstruct(void *self, int index, const void *other) {
llvm_unreachable("bad index"); assert(false && "bad index");
} }
LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_ALWAYS_INLINE
static void moveConstruct(void *self, int index, void *other) { static void moveConstruct(void *self, int index, void *other) {
llvm_unreachable("bad index"); assert(false && "bad index");
} }
LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_ALWAYS_INLINE
static void copyAssignSame(int index, void *self, const void *other) { static void copyAssignSame(int index, void *self, const void *other) {
llvm_unreachable("bad index"); assert(false && "bad index");
} }
LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_ALWAYS_INLINE
static void moveAssignSame(int index, void *self, void *other) { static void moveAssignSame(int index, void *self, void *other) {
llvm_unreachable("bad index"); assert(false && "bad index");
} }
LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_ALWAYS_INLINE
static void destruct(int index, void *self) { static void destruct(int index, void *self) {
llvm_unreachable("bad index"); assert(false && "bad index");
} }
}; };

View File

@@ -608,6 +608,8 @@ public:
auto CDAddr = this->readCaptureDescriptorFromMetadata(*MetadataAddress); auto CDAddr = this->readCaptureDescriptorFromMetadata(*MetadataAddress);
if (!CDAddr) if (!CDAddr)
return nullptr; return nullptr;
if (!CDAddr->isResolved())
return nullptr;
// FIXME: Non-generic SIL boxes also use the HeapLocalVariable metadata // FIXME: Non-generic SIL boxes also use the HeapLocalVariable metadata
// kind, but with a null capture descriptor right now (see // kind, but with a null capture descriptor right now (see
@@ -615,7 +617,8 @@ public:
// //
// Non-generic SIL boxes share metadata among types with compatible // Non-generic SIL boxes share metadata among types with compatible
// layout, but we need some way to get an outgoing pointer map for them. // layout, but we need some way to get an outgoing pointer map for them.
auto CD = getBuilder().getCaptureDescriptor(*CDAddr); auto CD = getBuilder().getCaptureDescriptor(
CDAddr->getResolvedAddress().getAddressData());
if (CD == nullptr) if (CD == nullptr)
return nullptr; return nullptr;

View File

@@ -69,7 +69,7 @@ public:
/// NOTE: subclasses MUST override at least one of the readBytes functions. The default /// NOTE: subclasses MUST override at least one of the readBytes functions. The default
/// implementation calls through to the other one. /// implementation calls through to the other one.
virtual ReadBytesResult virtual ReadBytesResult
readBytes(RemoteAddress address, uint64_t size) { readBytes(RemoteAddress address, uint64_t size) {
auto *Buf = malloc(size); auto *Buf = malloc(size);
ReadBytesResult Result(Buf, [](const void *ptr) { ReadBytesResult Result(Buf, [](const void *ptr) {
free(const_cast<void *>(ptr)); free(const_cast<void *>(ptr));
@@ -96,6 +96,34 @@ public:
memcpy(dest, Ptr.get(), size); memcpy(dest, Ptr.get(), size);
return true; return true;
} }
/// Attempts to resolve a pointer value read from the given remote address.
virtual RemoteAbsolutePointer resolvePointer(RemoteAddress address,
uint64_t readValue) {
// Default implementation returns the read value as is.
return RemoteAbsolutePointer("", readValue);
}
/// Attempt to read and resolve a pointer value at the given remote address.
llvm::Optional<RemoteAbsolutePointer> readPointer(RemoteAddress address,
unsigned pointerSize) {
auto result = readBytes(address, pointerSize);
if (!result)
return llvm::None;
uint64_t pointerData;
if (pointerSize == 4) {
uint32_t theData;
memcpy(&theData, result.get(), 4);
pointerData = theData;
} else if (pointerSize == 8) {
memcpy(&pointerData, result.get(), 8);
} else {
return llvm::None;
}
return resolvePointer(address, pointerData);
}
virtual ~MemoryReader() = default; virtual ~MemoryReader() = default;
}; };

View File

@@ -22,6 +22,7 @@
#include "swift/Demangling/Demangler.h" #include "swift/Demangling/Demangler.h"
#include "swift/Demangling/TypeDecoder.h" #include "swift/Demangling/TypeDecoder.h"
#include "swift/Basic/Defer.h" #include "swift/Basic/Defer.h"
#include "swift/Basic/ExternalUnion.h"
#include "swift/Basic/Range.h" #include "swift/Basic/Range.h"
#include "swift/Basic/LLVM.h" #include "swift/Basic/LLVM.h"
#include "swift/ABI/TypeIdentity.h" #include "swift/ABI/TypeIdentity.h"
@@ -181,6 +182,75 @@ private:
std::unique_ptr<const TargetContextDescriptor<Runtime>, std::unique_ptr<const TargetContextDescriptor<Runtime>,
delete_with_free>; delete_with_free>;
/// A reference to a context descriptor that may be in an unloaded image.
class ParentContextDescriptorRef {
bool IsResolved;
using Payloads = ExternalUnionMembers<std::string, ContextDescriptorRef>;
static typename Payloads::Index getPayloadIndex(bool IsResolved) {
return IsResolved ? Payloads::template indexOf<ContextDescriptorRef>()
: Payloads::template indexOf<std::string>();
}
ExternalUnion<bool, Payloads, getPayloadIndex> Payload;
public:
explicit ParentContextDescriptorRef(StringRef Symbol)
: IsResolved(false)
{
Payload.template emplace<std::string>(IsResolved, Symbol);
}
explicit ParentContextDescriptorRef(ContextDescriptorRef Resolved)
: IsResolved(true)
{
Payload.template emplace<ContextDescriptorRef>(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<std::string>(IsResolved);
}
ContextDescriptorRef getResolved() const {
return Payload.template get<ContextDescriptorRef>(IsResolved);
}
explicit operator bool() const {
return !isResolved() || getResolved();
}
};
/// A cache of read nominal type descriptors, keyed by the address of the /// A cache of read nominal type descriptors, keyed by the address of the
/// nominal type descriptor. /// nominal type descriptor.
std::unordered_map<StoredPointer, OwnedContextDescriptorRef> std::unordered_map<StoredPointer, OwnedContextDescriptorRef>
@@ -310,30 +380,34 @@ public:
auto remoteAddress = auto remoteAddress =
mangledName.getAddressData() + offsetInMangledName + offset; mangledName.getAddressData() + offsetInMangledName + offset;
RemoteAbsolutePointer resolved;
if (directness == Directness::Indirect) { if (directness == Directness::Indirect) {
if (auto indirectAddress = readPointerValue(remoteAddress)) { if (auto indirectAddress = readPointer(remoteAddress)) {
remoteAddress = *indirectAddress; resolved = *indirectAddress;
} else { } else {
return nullptr; return nullptr;
} }
} else {
resolved = RemoteAbsolutePointer("", remoteAddress);
} }
switch (kind) { switch (kind) {
case Demangle::SymbolicReferenceKind::Context: { case Demangle::SymbolicReferenceKind::Context: {
auto context = readContextDescriptor(remoteAddress); auto context = readContextDescriptor(resolved);
if (!context) if (!context)
return nullptr; return nullptr;
// Try to preserve a reference to an OpaqueTypeDescriptor // Try to preserve a reference to an OpaqueTypeDescriptor
// symbolically, since we'd like to read out and resolve the type ref // symbolically, since we'd like to read out and resolve the type ref
// to the underlying type if available. // to the underlying type if available.
if (useOpaqueTypeSymbolicReferences if (useOpaqueTypeSymbolicReferences
&& context->getKind() == ContextDescriptorKind::OpaqueType) { && context.isResolved()
return dem.createNode( && context.getResolved()->getKind() == ContextDescriptorKind::OpaqueType){
Node::Kind::OpaqueTypeDescriptorSymbolicReference, return dem.createNode(
context.getAddressData()); Node::Kind::OpaqueTypeDescriptorSymbolicReference,
} context.getResolved().getAddressData());
}
return buildContextMangling(context, dem);
return buildContextMangling(context, dem);
} }
case Demangle::SymbolicReferenceKind::AccessorFunctionReference: { case Demangle::SymbolicReferenceKind::AccessorFunctionReference: {
// The symbolic reference points at a resolver function, but we can't // The symbolic reference points at a resolver function, but we can't
@@ -426,14 +500,6 @@ public:
return start; return start;
} }
/// Given a pointer to an address, attemp to read the pointer value.
Optional<StoredPointer> readPointerValue(StoredPointer Address) {
StoredPointer PointerVal;
if (!Reader->readInteger(RemoteAddress(Address), &PointerVal))
return None;
return Optional<StoredPointer>(PointerVal);
}
/// Given a pointer to the metadata, attempt to read the value /// Given a pointer to the metadata, attempt to read the value
/// witness table. Note that it's not safe to access any non-mandatory /// 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. /// members of the value witness table, like extra inhabitants or enum members.
@@ -821,6 +887,23 @@ public:
Dem.demangleSymbol(StringRef(MangledTypeName, Length)); Dem.demangleSymbol(StringRef(MangledTypeName, Length));
return decodeMangledType(Demangled); 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()));
}
/// Given the address of a context descriptor, attempt to read it. /// Given the address of a context descriptor, attempt to read it.
ContextDescriptorRef ContextDescriptorRef
@@ -954,6 +1037,44 @@ public:
return ContextDescriptorRef(address, descriptor); return ContextDescriptorRef(address, descriptor);
} }
/// 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;
// We don't handle pointers to other symbols yet.
// TODO: Opaque type descriptors could be useful.
default:
return nullptr;
}
return demangledSymbol;
}
/// 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 /// Given a read context descriptor, attempt to build a demangling tree
/// for it. /// for it.
Demangle::NodePointer Demangle::NodePointer
@@ -1331,47 +1452,40 @@ public:
auto heapMeta = cast<TargetHeapLocalVariableMetadata<Runtime>>(meta); auto heapMeta = cast<TargetHeapLocalVariableMetadata<Runtime>>(meta);
return heapMeta->OffsetToFirstCapture; return heapMeta->OffsetToFirstCapture;
} }
Optional<RemoteAbsolutePointer> readPointer(StoredPointer address) {
return Reader->readPointer(RemoteAddress(address), sizeof(StoredPointer));
}
Optional<StoredPointer> readResolvedPointerValue(StoredPointer address) {
if (auto pointer = readPointer(address)) {
if (!pointer->isResolved())
return None;
return (StoredPointer)pointer->getResolvedAddress().getAddressData();
}
return None;
}
template<typename T, typename U>
RemoteAbsolutePointer resolvePointerField(RemoteRef<T> 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. /// Given a remote pointer to class metadata, attempt to read its superclass.
Optional<StoredPointer> Optional<RemoteAbsolutePointer>
readCaptureDescriptorFromMetadata(StoredPointer MetadataAddress) { readCaptureDescriptorFromMetadata(StoredPointer MetadataAddress) {
auto meta = readMetadata(MetadataAddress); auto meta = readMetadata(MetadataAddress);
if (!meta || meta->getKind() != MetadataKind::HeapLocalVariable) if (!meta || meta->getKind() != MetadataKind::HeapLocalVariable)
return None; return None;
auto heapMeta = cast<TargetHeapLocalVariableMetadata<Runtime>>(meta); auto heapMeta = cast<TargetHeapLocalVariableMetadata<Runtime>>(meta);
return heapMeta->CaptureDescription; return resolvePointerField(meta, heapMeta->CaptureDescription);
} }
protected: protected:
template<typename Offset>
Optional<StoredPointer>
resolveNullableRelativeIndirectableOffset(StoredPointer targetAddress) {
Offset relative;
if (!Reader->readInteger(RemoteAddress(targetAddress), &relative))
return None;
if (relative == 0)
return 0;
bool indirect = relative & 1;
relative &= ~1u;
using SignedOffset = typename std::make_signed<Offset>::type;
using SignedPointer = typename std::make_signed<StoredPointer>::type;
auto signext = (SignedPointer)(SignedOffset)relative;
StoredPointer resultAddress = targetAddress + signext;
// Low bit set in the offset indicates that the offset leads to the absolute
// address in memory.
if (indirect) {
if (!Reader->readBytes(RemoteAddress(resultAddress),
(uint8_t *)&resultAddress,
sizeof(StoredPointer)))
return None;
}
return resultAddress;
}
template<typename Base> template<typename Base>
StoredPointer getAddress(RemoteRef<Base> base) { StoredPointer getAddress(RemoteRef<Base> base) {
return (StoredPointer)base.getAddressData(); return (StoredPointer)base.getAddressData();
@@ -1384,14 +1498,14 @@ protected:
} }
template<typename Base, typename Field> template<typename Base, typename Field>
Optional<StoredPointer> resolveRelativeIndirectableField( Optional<RemoteAbsolutePointer> resolveRelativeIndirectableField(
RemoteRef<Base> base, const Field &field) { RemoteRef<Base> base, const Field &field) {
auto fieldRef = base.getField(field); auto fieldRef = base.getField(field);
int32_t offset; int32_t offset;
memcpy(&offset, fieldRef.getLocalBuffer(), sizeof(int32_t)); memcpy(&offset, fieldRef.getLocalBuffer(), sizeof(int32_t));
if (offset == 0) if (offset == 0)
return 0; return Optional<RemoteAbsolutePointer>(nullptr);
bool indirect = offset & 1; bool indirect = offset & 1;
offset &= ~1u; offset &= ~1u;
@@ -1402,14 +1516,10 @@ protected:
// 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) {
if (!Reader->readBytes(RemoteAddress(resultAddress), return readPointer(resultAddress);
(uint8_t *)&resultAddress,
sizeof(StoredPointer))) {
return None;
}
} }
return resultAddress; return RemoteAbsolutePointer("", resultAddress);
} }
/// Given a pointer to an Objective-C class, try to read its class name. /// Given a pointer to an Objective-C class, try to read its class name.
@@ -1612,17 +1722,26 @@ private:
} }
} }
/// Returns Optional(nullptr) if there's no parent descriptor. /// Returns Optional(ParentContextDescriptorRef()) if there's no parent descriptor.
/// Returns None if there was an error reading the parent descriptor. /// Returns None if there was an error reading the parent descriptor.
Optional<ContextDescriptorRef> Optional<ParentContextDescriptorRef>
readParentContextDescriptor(ContextDescriptorRef base) { readParentContextDescriptor(ContextDescriptorRef base) {
auto parentAddress = resolveRelativeIndirectableField(base, base->Parent); auto parentAddress = resolveRelativeIndirectableField(base, base->Parent);
if (!parentAddress) if (!parentAddress)
return None; return None;
if (!*parentAddress) if (!parentAddress->isResolved()) {
return ContextDescriptorRef(nullptr); // Currently we can only handle references directly to a symbol without
if (auto parentDescriptor = readContextDescriptor(*parentAddress)) // an offset.
return parentDescriptor; if (parentAddress->getOffset() != 0) {
return None;
}
return ParentContextDescriptorRef(parentAddress->getSymbol());
}
auto addr = parentAddress->getResolvedAddress();
if (!addr)
return ParentContextDescriptorRef();
if (auto parentDescriptor = readContextDescriptor(addr.getAddressData()))
return ParentContextDescriptorRef(parentDescriptor);
return None; return None;
} }
@@ -1807,13 +1926,20 @@ private:
/// produce a mangled node describing the name of \c context. /// produce a mangled node describing the name of \c context.
Demangle::NodePointer Demangle::NodePointer
adoptAnonymousContextName(ContextDescriptorRef contextRef, adoptAnonymousContextName(ContextDescriptorRef contextRef,
Optional<ContextDescriptorRef> &parentContextRef, Optional<ParentContextDescriptorRef> &parentContextRef,
Demangler &dem, Demangler &dem,
Demangle::NodePointer &outerNode) { Demangle::NodePointer &outerNode) {
outerNode = nullptr; outerNode = nullptr;
if (!parentContextRef || !*parentContextRef) // Bail if there is no parent, or if the parent is in another image.
// (Anonymous contexts should always be emitted in the same image as their
// children.)
if (!parentContextRef
|| !*parentContextRef
|| !parentContextRef->isResolved())
return nullptr; return nullptr;
auto parentContextLocalRef = parentContextRef->getResolved();
auto context = contextRef.getLocalBuffer(); auto context = contextRef.getLocalBuffer();
auto typeContext = dyn_cast<TargetTypeContextDescriptor<Runtime>>(context); auto typeContext = dyn_cast<TargetTypeContextDescriptor<Runtime>>(context);
@@ -1822,11 +1948,11 @@ private:
return nullptr; return nullptr;
auto anonymousParent = dyn_cast_or_null<TargetAnonymousContextDescriptor<Runtime>>( auto anonymousParent = dyn_cast_or_null<TargetAnonymousContextDescriptor<Runtime>>(
parentContextRef->getLocalBuffer()); parentContextLocalRef.getLocalBuffer());
if (!anonymousParent) if (!anonymousParent)
return nullptr; return nullptr;
auto mangledNode = demangleAnonymousContextName(*parentContextRef, dem); auto mangledNode = demangleAnonymousContextName(parentContextLocalRef, dem);
if (!mangledNode) if (!mangledNode)
return nullptr; return nullptr;
@@ -1863,7 +1989,7 @@ private:
// We have a match. Update the parent context to skip the anonymous // We have a match. Update the parent context to skip the anonymous
// context entirely. // context entirely.
parentContextRef = readParentContextDescriptor(*parentContextRef); parentContextRef = readParentContextDescriptor(parentContextLocalRef);
// The outer node is the first child. // The outer node is the first child.
outerNode = mangledNode->getChild(0); outerNode = mangledNode->getChild(0);
@@ -1914,6 +2040,26 @@ private:
return resultAddress; return resultAddress;
} }
Demangle::NodePointer
buildContextDescriptorMangling(const ParentContextDescriptorRef &descriptor,
Demangler &dem) {
if (descriptor.isResolved()) {
return buildContextDescriptorMangling(descriptor.getResolved(), dem);
}
// Try to demangle the symbol name to figure out what context it would
// point to.
auto demangledSymbol = buildContextManglingForSymbol(descriptor.getSymbol(),
dem);
if (!demangledSymbol)
return nullptr;
// Look through Type notes since we're building up a mangling here.
if (demangledSymbol->getKind() == Demangle::Node::Kind::Type){
demangledSymbol = demangledSymbol->getChild(0);
}
return demangledSymbol;
}
Demangle::NodePointer Demangle::NodePointer
buildContextDescriptorMangling(ContextDescriptorRef descriptor, buildContextDescriptorMangling(ContextDescriptorRef descriptor,
Demangler &dem) { Demangler &dem) {
@@ -2184,17 +2330,13 @@ private:
case ContextDescriptorKind::OpaqueType: { case ContextDescriptorKind::OpaqueType: {
// The opaque type may have a named anonymous context for us to map // The opaque type may have a named anonymous context for us to map
// back to its defining decl. // back to its defining decl.
if (!parentDescriptorResult) if (!parentDescriptorResult
return nullptr; || !*parentDescriptorResult
|| !parentDescriptorResult->isResolved())
auto anonymous =
dyn_cast_or_null<TargetAnonymousContextDescriptor<Runtime>>(
parentDescriptorResult->getLocalBuffer());
if (!anonymous)
return nullptr; return nullptr;
auto mangledNode = auto mangledNode =
demangleAnonymousContextName(*parentDescriptorResult, dem); demangleAnonymousContextName(parentDescriptorResult->getResolved(), dem);
if (!mangledNode) if (!mangledNode)
return nullptr; return nullptr;
if (mangledNode->getKind() == Node::Kind::Global) if (mangledNode->getKind() == Node::Kind::Global)

View File

@@ -19,6 +19,9 @@
#define SWIFT_REMOTE_REMOTEADDRESS_H #define SWIFT_REMOTE_REMOTEADDRESS_H
#include <cstdint> #include <cstdint>
#include <string>
#include <llvm/ADT/StringRef.h>
#include <cassert>
namespace swift { namespace swift {
namespace remote { namespace remote {
@@ -46,6 +49,40 @@ public:
} }
}; };
/// A symbolic relocated absolute pointer value.
class RemoteAbsolutePointer {
/// The symbol name that the pointer refers to. Empty if the value is absolute.
std::string Symbol;
/// The offset from the symbol, or the resolved remote address if \c Symbol is empty.
int64_t Offset;
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(); }
llvm::StringRef getSymbol() const { return Symbol; }
int64_t getOffset() const { return Offset; }
RemoteAddress getResolvedAddress() const {
assert(isResolved());
return RemoteAddress(Offset);
}
explicit operator bool() const {
return Offset != 0 || !Symbol.empty();
}
};
} // end namespace remote } // end namespace remote
} // end namespace swift } // end namespace swift

View File

@@ -491,7 +491,7 @@ public:
Result<OpenedExistential> Result<OpenedExistential>
getDynamicTypeAndAddressClassExistential(RemoteAddress object) { getDynamicTypeAndAddressClassExistential(RemoteAddress object) {
auto pointerval = Reader.readPointerValue(object.getAddressData()); auto pointerval = Reader.readResolvedPointerValue(object.getAddressData());
if (!pointerval) if (!pointerval)
return getFailure<OpenedExistential>(); return getFailure<OpenedExistential>();
auto result = Reader.readMetadataFromInstance(*pointerval); auto result = Reader.readMetadataFromInstance(*pointerval);
@@ -508,7 +508,7 @@ public:
getDynamicTypeAndAddressErrorExistential(RemoteAddress object, getDynamicTypeAndAddressErrorExistential(RemoteAddress object,
bool dereference=true) { bool dereference=true) {
if (dereference) { if (dereference) {
auto pointerval = Reader.readPointerValue(object.getAddressData()); auto pointerval = Reader.readResolvedPointerValue(object.getAddressData());
if (!pointerval) if (!pointerval)
return getFailure<OpenedExistential>(); return getFailure<OpenedExistential>();
object = RemoteAddress(*pointerval); object = RemoteAddress(*pointerval);
@@ -531,7 +531,7 @@ public:
auto payloadAddress = result->PayloadAddress; auto payloadAddress = result->PayloadAddress;
if (!result->IsBridgedError && if (!result->IsBridgedError &&
typeResult->getClassOrBoundGenericClass()) { typeResult->getClassOrBoundGenericClass()) {
auto pointerval = Reader.readPointerValue( auto pointerval = Reader.readResolvedPointerValue(
payloadAddress.getAddressData()); payloadAddress.getAddressData());
if (!pointerval) if (!pointerval)
return getFailure<OpenedExistential>(); return getFailure<OpenedExistential>();
@@ -559,7 +559,7 @@ public:
// of the reference. // of the reference.
auto payloadAddress = result->PayloadAddress; auto payloadAddress = result->PayloadAddress;
if (typeResult->getClassOrBoundGenericClass()) { if (typeResult->getClassOrBoundGenericClass()) {
auto pointerval = Reader.readPointerValue( auto pointerval = Reader.readResolvedPointerValue(
payloadAddress.getAddressData()); payloadAddress.getAddressData());
if (!pointerval) if (!pointerval)
return getFailure<OpenedExistential>(); return getFailure<OpenedExistential>();
@@ -578,7 +578,7 @@ public:
// 1) Loading a pointer from the input address // 1) Loading a pointer from the input address
// 2) Reading it as metadata and resolving the type // 2) Reading it as metadata and resolving the type
// 3) Wrapping the resolved type in an existential metatype. // 3) Wrapping the resolved type in an existential metatype.
auto pointerval = Reader.readPointerValue(object.getAddressData()); auto pointerval = Reader.readResolvedPointerValue(object.getAddressData());
if (!pointerval) if (!pointerval)
return getFailure<OpenedExistential>(); return getFailure<OpenedExistential>();
auto typeResult = Reader.readTypeFromMetadata(*pointerval); auto typeResult = Reader.readTypeFromMetadata(*pointerval);