mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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:
@@ -433,27 +433,27 @@ struct MembersHelper<> {
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static void copyConstruct(void *self, int index, const void *other) {
|
||||
llvm_unreachable("bad index");
|
||||
assert(false && "bad index");
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static void moveConstruct(void *self, int index, void *other) {
|
||||
llvm_unreachable("bad index");
|
||||
assert(false && "bad index");
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static void copyAssignSame(int index, void *self, const void *other) {
|
||||
llvm_unreachable("bad index");
|
||||
assert(false && "bad index");
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static void moveAssignSame(int index, void *self, void *other) {
|
||||
llvm_unreachable("bad index");
|
||||
assert(false && "bad index");
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static void destruct(int index, void *self) {
|
||||
llvm_unreachable("bad index");
|
||||
assert(false && "bad index");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -608,6 +608,8 @@ public:
|
||||
auto CDAddr = this->readCaptureDescriptorFromMetadata(*MetadataAddress);
|
||||
if (!CDAddr)
|
||||
return nullptr;
|
||||
if (!CDAddr->isResolved())
|
||||
return nullptr;
|
||||
|
||||
// FIXME: Non-generic SIL boxes also use the HeapLocalVariable metadata
|
||||
// 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
|
||||
// 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)
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
/// NOTE: subclasses MUST override at least one of the readBytes functions. The default
|
||||
/// implementation calls through to the other one.
|
||||
virtual ReadBytesResult
|
||||
readBytes(RemoteAddress address, uint64_t size) {
|
||||
readBytes(RemoteAddress address, uint64_t size) {
|
||||
auto *Buf = malloc(size);
|
||||
ReadBytesResult Result(Buf, [](const void *ptr) {
|
||||
free(const_cast<void *>(ptr));
|
||||
@@ -96,6 +96,34 @@ public:
|
||||
memcpy(dest, Ptr.get(), size);
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "swift/Demangling/Demangler.h"
|
||||
#include "swift/Demangling/TypeDecoder.h"
|
||||
#include "swift/Basic/Defer.h"
|
||||
#include "swift/Basic/ExternalUnion.h"
|
||||
#include "swift/Basic/Range.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/ABI/TypeIdentity.h"
|
||||
@@ -181,6 +182,75 @@ private:
|
||||
std::unique_ptr<const TargetContextDescriptor<Runtime>,
|
||||
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
|
||||
/// nominal type descriptor.
|
||||
std::unordered_map<StoredPointer, OwnedContextDescriptorRef>
|
||||
@@ -310,30 +380,34 @@ public:
|
||||
auto remoteAddress =
|
||||
mangledName.getAddressData() + offsetInMangledName + offset;
|
||||
|
||||
RemoteAbsolutePointer resolved;
|
||||
if (directness == Directness::Indirect) {
|
||||
if (auto indirectAddress = readPointerValue(remoteAddress)) {
|
||||
remoteAddress = *indirectAddress;
|
||||
if (auto indirectAddress = readPointer(remoteAddress)) {
|
||||
resolved = *indirectAddress;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
resolved = RemoteAbsolutePointer("", remoteAddress);
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
case Demangle::SymbolicReferenceKind::Context: {
|
||||
auto context = readContextDescriptor(remoteAddress);
|
||||
if (!context)
|
||||
return nullptr;
|
||||
// Try to preserve a reference to an OpaqueTypeDescriptor
|
||||
// symbolically, since we'd like to read out and resolve the type ref
|
||||
// to the underlying type if available.
|
||||
if (useOpaqueTypeSymbolicReferences
|
||||
&& context->getKind() == ContextDescriptorKind::OpaqueType) {
|
||||
return dem.createNode(
|
||||
Node::Kind::OpaqueTypeDescriptorSymbolicReference,
|
||||
context.getAddressData());
|
||||
}
|
||||
|
||||
return buildContextMangling(context, dem);
|
||||
auto context = readContextDescriptor(resolved);
|
||||
if (!context)
|
||||
return nullptr;
|
||||
// Try to preserve a reference to an OpaqueTypeDescriptor
|
||||
// symbolically, since we'd like to read out and resolve the type ref
|
||||
// to the underlying type if available.
|
||||
if (useOpaqueTypeSymbolicReferences
|
||||
&& context.isResolved()
|
||||
&& context.getResolved()->getKind() == ContextDescriptorKind::OpaqueType){
|
||||
return dem.createNode(
|
||||
Node::Kind::OpaqueTypeDescriptorSymbolicReference,
|
||||
context.getResolved().getAddressData());
|
||||
}
|
||||
|
||||
return buildContextMangling(context, dem);
|
||||
}
|
||||
case Demangle::SymbolicReferenceKind::AccessorFunctionReference: {
|
||||
// The symbolic reference points at a resolver function, but we can't
|
||||
@@ -426,14 +500,6 @@ public:
|
||||
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
|
||||
/// 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.
|
||||
@@ -821,6 +887,23 @@ public:
|
||||
Dem.demangleSymbol(StringRef(MangledTypeName, Length));
|
||||
return decodeMangledType(Demangled);
|
||||
}
|
||||
|
||||
/// Given the address of a context descriptor, attempt to read it, or
|
||||
/// represent it symbolically.
|
||||
ParentContextDescriptorRef
|
||||
readContextDescriptor(const RemoteAbsolutePointer &address) {
|
||||
// Map an unresolved pointer to an unresolved context ref.
|
||||
if (!address.isResolved()) {
|
||||
// We can only handle references to a symbol without an offset currently.
|
||||
if (address.getOffset() != 0) {
|
||||
return ParentContextDescriptorRef();
|
||||
}
|
||||
return ParentContextDescriptorRef(address.getSymbol());
|
||||
}
|
||||
|
||||
return ParentContextDescriptorRef(
|
||||
readContextDescriptor(address.getResolvedAddress().getAddressData()));
|
||||
}
|
||||
|
||||
/// Given the address of a context descriptor, attempt to read it.
|
||||
ContextDescriptorRef
|
||||
@@ -954,6 +1037,44 @@ public:
|
||||
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
|
||||
/// for it.
|
||||
Demangle::NodePointer
|
||||
@@ -1331,47 +1452,40 @@ public:
|
||||
auto heapMeta = cast<TargetHeapLocalVariableMetadata<Runtime>>(meta);
|
||||
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.
|
||||
Optional<StoredPointer>
|
||||
Optional<RemoteAbsolutePointer>
|
||||
readCaptureDescriptorFromMetadata(StoredPointer MetadataAddress) {
|
||||
auto meta = readMetadata(MetadataAddress);
|
||||
if (!meta || meta->getKind() != MetadataKind::HeapLocalVariable)
|
||||
return None;
|
||||
|
||||
auto heapMeta = cast<TargetHeapLocalVariableMetadata<Runtime>>(meta);
|
||||
return heapMeta->CaptureDescription;
|
||||
return resolvePointerField(meta, heapMeta->CaptureDescription);
|
||||
}
|
||||
|
||||
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>
|
||||
StoredPointer getAddress(RemoteRef<Base> base) {
|
||||
return (StoredPointer)base.getAddressData();
|
||||
@@ -1384,14 +1498,14 @@ protected:
|
||||
}
|
||||
|
||||
template<typename Base, typename Field>
|
||||
Optional<StoredPointer> resolveRelativeIndirectableField(
|
||||
Optional<RemoteAbsolutePointer> resolveRelativeIndirectableField(
|
||||
RemoteRef<Base> base, const Field &field) {
|
||||
auto fieldRef = base.getField(field);
|
||||
int32_t offset;
|
||||
memcpy(&offset, fieldRef.getLocalBuffer(), sizeof(int32_t));
|
||||
|
||||
if (offset == 0)
|
||||
return 0;
|
||||
return Optional<RemoteAbsolutePointer>(nullptr);
|
||||
bool indirect = offset & 1;
|
||||
offset &= ~1u;
|
||||
|
||||
@@ -1402,14 +1516,10 @@ protected:
|
||||
// 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 readPointer(resultAddress);
|
||||
}
|
||||
|
||||
return resultAddress;
|
||||
return RemoteAbsolutePointer("", resultAddress);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
Optional<ContextDescriptorRef>
|
||||
Optional<ParentContextDescriptorRef>
|
||||
readParentContextDescriptor(ContextDescriptorRef base) {
|
||||
auto parentAddress = resolveRelativeIndirectableField(base, base->Parent);
|
||||
if (!parentAddress)
|
||||
return None;
|
||||
if (!*parentAddress)
|
||||
return ContextDescriptorRef(nullptr);
|
||||
if (auto parentDescriptor = readContextDescriptor(*parentAddress))
|
||||
return parentDescriptor;
|
||||
if (!parentAddress->isResolved()) {
|
||||
// Currently we can only handle references directly to a symbol without
|
||||
// an offset.
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1807,13 +1926,20 @@ private:
|
||||
/// produce a mangled node describing the name of \c context.
|
||||
Demangle::NodePointer
|
||||
adoptAnonymousContextName(ContextDescriptorRef contextRef,
|
||||
Optional<ContextDescriptorRef> &parentContextRef,
|
||||
Demangler &dem,
|
||||
Demangle::NodePointer &outerNode) {
|
||||
Optional<ParentContextDescriptorRef> &parentContextRef,
|
||||
Demangler &dem,
|
||||
Demangle::NodePointer &outerNode) {
|
||||
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;
|
||||
|
||||
auto parentContextLocalRef = parentContextRef->getResolved();
|
||||
|
||||
auto context = contextRef.getLocalBuffer();
|
||||
auto typeContext = dyn_cast<TargetTypeContextDescriptor<Runtime>>(context);
|
||||
@@ -1822,11 +1948,11 @@ private:
|
||||
return nullptr;
|
||||
|
||||
auto anonymousParent = dyn_cast_or_null<TargetAnonymousContextDescriptor<Runtime>>(
|
||||
parentContextRef->getLocalBuffer());
|
||||
parentContextLocalRef.getLocalBuffer());
|
||||
if (!anonymousParent)
|
||||
return nullptr;
|
||||
|
||||
auto mangledNode = demangleAnonymousContextName(*parentContextRef, dem);
|
||||
auto mangledNode = demangleAnonymousContextName(parentContextLocalRef, dem);
|
||||
if (!mangledNode)
|
||||
return nullptr;
|
||||
|
||||
@@ -1863,7 +1989,7 @@ private:
|
||||
|
||||
// We have a match. Update the parent context to skip the anonymous
|
||||
// context entirely.
|
||||
parentContextRef = readParentContextDescriptor(*parentContextRef);
|
||||
parentContextRef = readParentContextDescriptor(parentContextLocalRef);
|
||||
|
||||
// The outer node is the first child.
|
||||
outerNode = mangledNode->getChild(0);
|
||||
@@ -1914,6 +2040,26 @@ private:
|
||||
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
|
||||
buildContextDescriptorMangling(ContextDescriptorRef descriptor,
|
||||
Demangler &dem) {
|
||||
@@ -2184,17 +2330,13 @@ private:
|
||||
case ContextDescriptorKind::OpaqueType: {
|
||||
// The opaque type may have a named anonymous context for us to map
|
||||
// back to its defining decl.
|
||||
if (!parentDescriptorResult)
|
||||
return nullptr;
|
||||
|
||||
auto anonymous =
|
||||
dyn_cast_or_null<TargetAnonymousContextDescriptor<Runtime>>(
|
||||
parentDescriptorResult->getLocalBuffer());
|
||||
if (!anonymous)
|
||||
if (!parentDescriptorResult
|
||||
|| !*parentDescriptorResult
|
||||
|| !parentDescriptorResult->isResolved())
|
||||
return nullptr;
|
||||
|
||||
auto mangledNode =
|
||||
demangleAnonymousContextName(*parentDescriptorResult, dem);
|
||||
demangleAnonymousContextName(parentDescriptorResult->getResolved(), dem);
|
||||
if (!mangledNode)
|
||||
return nullptr;
|
||||
if (mangledNode->getKind() == Node::Kind::Global)
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
#define SWIFT_REMOTE_REMOTEADDRESS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace swift {
|
||||
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 swift
|
||||
|
||||
|
||||
@@ -491,7 +491,7 @@ public:
|
||||
|
||||
Result<OpenedExistential>
|
||||
getDynamicTypeAndAddressClassExistential(RemoteAddress object) {
|
||||
auto pointerval = Reader.readPointerValue(object.getAddressData());
|
||||
auto pointerval = Reader.readResolvedPointerValue(object.getAddressData());
|
||||
if (!pointerval)
|
||||
return getFailure<OpenedExistential>();
|
||||
auto result = Reader.readMetadataFromInstance(*pointerval);
|
||||
@@ -508,7 +508,7 @@ public:
|
||||
getDynamicTypeAndAddressErrorExistential(RemoteAddress object,
|
||||
bool dereference=true) {
|
||||
if (dereference) {
|
||||
auto pointerval = Reader.readPointerValue(object.getAddressData());
|
||||
auto pointerval = Reader.readResolvedPointerValue(object.getAddressData());
|
||||
if (!pointerval)
|
||||
return getFailure<OpenedExistential>();
|
||||
object = RemoteAddress(*pointerval);
|
||||
@@ -531,7 +531,7 @@ public:
|
||||
auto payloadAddress = result->PayloadAddress;
|
||||
if (!result->IsBridgedError &&
|
||||
typeResult->getClassOrBoundGenericClass()) {
|
||||
auto pointerval = Reader.readPointerValue(
|
||||
auto pointerval = Reader.readResolvedPointerValue(
|
||||
payloadAddress.getAddressData());
|
||||
if (!pointerval)
|
||||
return getFailure<OpenedExistential>();
|
||||
@@ -559,7 +559,7 @@ public:
|
||||
// of the reference.
|
||||
auto payloadAddress = result->PayloadAddress;
|
||||
if (typeResult->getClassOrBoundGenericClass()) {
|
||||
auto pointerval = Reader.readPointerValue(
|
||||
auto pointerval = Reader.readResolvedPointerValue(
|
||||
payloadAddress.getAddressData());
|
||||
if (!pointerval)
|
||||
return getFailure<OpenedExistential>();
|
||||
@@ -578,7 +578,7 @@ public:
|
||||
// 1) Loading a pointer from the input address
|
||||
// 2) Reading it as metadata and resolving the type
|
||||
// 3) Wrapping the resolved type in an existential metatype.
|
||||
auto pointerval = Reader.readPointerValue(object.getAddressData());
|
||||
auto pointerval = Reader.readResolvedPointerValue(object.getAddressData());
|
||||
if (!pointerval)
|
||||
return getFailure<OpenedExistential>();
|
||||
auto typeResult = Reader.readTypeFromMetadata(*pointerval);
|
||||
|
||||
Reference in New Issue
Block a user