Organize the MemoryReader interface headers to better support

multiple clients.
This commit is contained in:
John McCall
2016-04-12 16:04:37 -07:00
parent b5127aa747
commit 91f02848df
8 changed files with 320 additions and 189 deletions

View File

@@ -1,153 +0,0 @@
//===--- Reader.h - Swift Type Reflection Memory Reader ---------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Implements reading memory from the current or external process
// for reflection.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_REFLECTION_READER_H
#define SWIFT_REFLECTION_READER_H
#include "swift/SwiftRemoteMirror/MemoryReaderInterface.h"
#include <dlfcn.h>
#include <cstdint>
#include <cstring>
#include <memory>
#include <vector>
namespace swift {
namespace reflection {
template <typename Iterator>
class ReflectionSection {
using const_iterator = Iterator;
const void * const Begin;
const void * const End;
public:
ReflectionSection(const void * const Begin,
const void * const End)
: Begin(Begin), End(End) {}
ReflectionSection(uint64_t Begin, uint64_t End)
: Begin(reinterpret_cast<const void * const>(Begin)),
End(reinterpret_cast<const void * const>(End)) {}
void *startAddress() {
return const_cast<void *>(Begin);
}
const_iterator begin() const {
return const_iterator(Begin, End);
}
const_iterator end() const {
return const_iterator(End, End);
}
size_t size() const {
return (char *)End - (char *)Begin;
}
};
class MemoryReader {
public:
virtual uint8_t getPointerSize() = 0;
virtual uint8_t getSizeSize() = 0;
virtual addr_t getSymbolAddress(const std::string &Name) = 0;
virtual std::string readString(addr_t Address) = 0;
virtual bool readBytes(addr_t Address, uint8_t *Dest, uint64_t Size) = 0;
template <typename IntegerType>
bool readInteger(addr_t Address, IntegerType *Dest) {
return readBytes(Address, (uint8_t*)Dest, sizeof(IntegerType));
}
virtual ~MemoryReader() = default;
};
class InProcessMemoryReader final : public MemoryReader {
uint8_t getPointerSize() override {
return sizeof(uintptr_t);
}
uint8_t getSizeSize() override {
return sizeof(size_t);
}
addr_t getSymbolAddress(const std::string &Name) override {
auto Symbol = dlsym(RTLD_DEFAULT, Name.c_str());
auto Pointer = reinterpret_cast<uintptr_t>(Symbol);
return static_cast<addr_t>(Pointer);
}
std::string readString(addr_t Address) override {
return std::string((char *)Address);
}
bool readBytes(addr_t Address, uint8_t *Dest, uint64_t Size) override {
return memmove(Dest, reinterpret_cast<const void *>(Address), Size);
}
};
class CMemoryReader final : public MemoryReader {
MemoryReaderImpl Impl;
public:
CMemoryReader(MemoryReaderImpl Impl)
: Impl(Impl) {
assert(this->Impl.getPointerSize && "No getPointerSize implementation");
assert(this->Impl.getStringLength && "No stringLength implementation");
assert(this->Impl.readBytes && "No readBytes implementation");
assert(this->Impl.getPointerSize() != 0 && "Invalid target pointer size");
}
uint8_t getPointerSize() override {
return Impl.getPointerSize();
}
uint8_t getSizeSize() override {
return Impl.getSizeSize();
}
addr_t getSymbolAddress(const std::string &Name) override {
auto Address = Impl.getSymbolAddress(Name.c_str(), Name.size());
return static_cast<addr_t>(Address);
}
uint64_t getStringLength(addr_t Address) {
return Impl.getStringLength(Address);
}
std::string readString(addr_t Address) override {
auto NameSize = getStringLength(Address);
if (!NameSize)
return "";
auto NameBuffer = std::unique_ptr<uint8_t>(new uint8_t[NameSize + 1]);
if (!readBytes(Address, NameBuffer.get(), NameSize + 1))
return "";
return std::string(reinterpret_cast<const char *>(NameBuffer.get()));
}
bool readBytes(addr_t Address, uint8_t *Dest, uint64_t Size) override {
return Impl.readBytes(Address, Dest, Size);
}
};
} // end namespace reflection
} // end namespace swift
#endif // SWIFT_REFLECTION_READER_H

View File

@@ -19,7 +19,7 @@
#define SWIFT_REFLECTION_REFLECTIONCONTEXT_H
#include "swift/Runtime/Metadata.h"
#include "swift/Reflection/Reader.h"
#include "swift/Remote/MemoryReader.h"
#include "swift/Reflection/Records.h"
#include "swift/Reflection/TypeRef.h"
#include "swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h"
@@ -33,6 +33,41 @@ class NodePointer;
namespace swift {
namespace reflection {
using swift::remote::MemoryReader;
using swift::remote::RemoteAddress;
template <typename Iterator>
class ReflectionSection {
using const_iterator = Iterator;
const void * const Begin;
const void * const End;
public:
ReflectionSection(const void * const Begin,
const void * const End)
: Begin(Begin), End(End) {}
ReflectionSection(uint64_t Begin, uint64_t End)
: Begin(reinterpret_cast<const void * const>(Begin)),
End(reinterpret_cast<const void * const>(End)) {}
void *startAddress() {
return const_cast<void *>(Begin);
}
const_iterator begin() const {
return const_iterator(Begin, End);
}
const_iterator end() const {
return const_iterator(End, End);
}
size_t size() const {
return (char *)End - (char *)Begin;
}
};
template <typename Runtime>
using SharedTargetMetadataRef = std::shared_ptr<TargetMetadata<Runtime>>;
@@ -87,7 +122,7 @@ class ReflectionContext {
SharedTargetMetadataRef<Runtime> _readMetadata(StoredPointer Address,
size_t Size = sizeof(M)) {
uint8_t *Buffer = (uint8_t *)malloc(Size);
if (!Reader->readBytes(Address, Buffer, Size)) {
if (!Reader->readBytes(RemoteAddress(Address), Buffer, Size)) {
free(Buffer);
return nullptr;
}
@@ -202,7 +237,7 @@ public:
return Cached->second;
StoredPointer KindValue = 0;
if (!Reader->readInteger(Address, &KindValue))
if (!Reader->readInteger(RemoteAddress(Address), &KindValue))
return nullptr;
auto Kind = static_cast<MetadataKind>(KindValue);
@@ -219,7 +254,8 @@ public:
StoredPointer NumProtocolsAddress = Address +
TargetExistentialTypeMetadata<Runtime>::OffsetToNumProtocols;
StoredPointer NumProtocols;
if (!Reader->readInteger(NumProtocolsAddress, &NumProtocols))
if (!Reader->readInteger(RemoteAddress(NumProtocolsAddress),
&NumProtocols))
return nullptr;
auto TotalSize = sizeof(TargetExistentialTypeMetadata<Runtime>) +
@@ -254,7 +290,8 @@ public:
auto NumElementsAddress = Address +
TargetTupleTypeMetadata<Runtime>::OffsetToNumElements;
StoredSize NumElements;
if (!Reader->readInteger(NumElementsAddress, &NumElements))
if (!Reader->readInteger(RemoteAddress(NumElementsAddress),
&NumElements))
return nullptr;
auto TotalSize = sizeof(TargetTupleTypeMetadata<Runtime>) +
NumElements * sizeof(StoredPointer);
@@ -270,7 +307,7 @@ public:
template<typename Offset>
StoredPointer resolveRelativeOffset(StoredPointer targetAddress) {
Offset relative;
if (!Reader->readInteger(targetAddress, &relative))
if (!Reader->readInteger(RemoteAddress(targetAddress), &relative))
return 0;
using SignedOffset = typename std::make_signed<Offset>::type;
using SignedPointer = typename std::make_signed<StoredPointer>::type;
@@ -316,7 +353,7 @@ public:
auto Size = sizeof(TargetNominalTypeDescriptor<Runtime>);
auto Buffer = (uint8_t *)malloc(Size);
if (!Reader->readBytes(DescriptorAddress, Buffer, Size)) {
if (!Reader->readBytes(RemoteAddress(DescriptorAddress), Buffer, Size)) {
free(Buffer);
return {nullptr, 0};
}
@@ -340,7 +377,7 @@ public:
readProtocolDescriptor(StoredPointer Address) {
auto Size = sizeof(TargetProtocolDescriptor<Runtime>);
auto Buffer = (uint8_t *)malloc(Size);
if (!Reader->readBytes(Address, Buffer, Size)) {
if (!Reader->readBytes(RemoteAddress(Address), Buffer, Size)) {
free(Buffer);
return nullptr;
}
@@ -356,7 +393,8 @@ public:
auto AddressOfParentAddress
= resolveRelativeOffset<StoredPointer>(MetadataAddress +
ValueMeta->offsetToParentOffset());
if (!Reader->readInteger(AddressOfParentAddress, &ParentAddress))
if (!Reader->readInteger(RemoteAddress(AddressOfParentAddress),
&ParentAddress))
return 0;
} else if (auto Class = dyn_cast<TargetClassMetadata<Runtime>>(Meta.get())){
StoredPointer DescriptorAddress;
@@ -366,7 +404,8 @@ public:
TypeRefVector Substitutions;
auto OffsetToParent
= sizeof(StoredPointer) * (Descriptor->GenericParams.Offset - 1);
if (!Reader->readInteger(MetadataAddress + OffsetToParent, &ParentAddress))
if (!Reader->readInteger(RemoteAddress(MetadataAddress + OffsetToParent),
&ParentAddress))
return 0;
}
return ParentAddress;
@@ -393,7 +432,7 @@ public:
for (ArgIndex i = 0; i < NumGenericParams; ++i,
AddressOfGenericArgAddress += sizeof(StoredPointer)) {
StoredPointer GenericArgAddress;
if (!Reader->readInteger(AddressOfGenericArgAddress,
if (!Reader->readInteger(RemoteAddress(AddressOfGenericArgAddress),
&GenericArgAddress))
return {};
if (auto GenericArg = getTypeRef(GenericArgAddress))
@@ -418,8 +457,8 @@ public:
auto NameAddress
= resolveRelativeOffset<int32_t>(DescriptorAddress +
Descriptor->offsetToNameOffset());
auto MangledName = Reader->readString(NameAddress);
if (MangledName.empty())
std::string MangledName;
if (!Reader->readString(RemoteAddress(NameAddress), MangledName))
return nullptr;
auto DemangleNode = Demangle::demangleTypeAsNode(MangledName);
@@ -471,7 +510,8 @@ public:
for (StoredPointer i = 0; i < TupleMeta->NumElements; ++i,
ElementAddress += sizeof(Element)) {
Element E;
if (!Reader->readBytes(ElementAddress, (uint8_t*)&E, sizeof(Element)))
if (!Reader->readBytes(RemoteAddress(ElementAddress),
(uint8_t*)&E, sizeof(Element)))
return nullptr;
if (auto ElementTypeRef = getTypeRef(E.Type))
@@ -486,7 +526,8 @@ public:
StoredPointer FlagsAddress = MetadataAddress +
TargetFunctionTypeMetadata<Runtime>::OffsetToFlags;
TargetFunctionTypeFlags<Runtime> Flags;
if (!Reader->readBytes(FlagsAddress, (uint8_t*)&Flags, sizeof(Flags)))
if (!Reader->readBytes(RemoteAddress(FlagsAddress),
(uint8_t*)&Flags, sizeof(Flags)))
return nullptr;
TypeRefVector Arguments;
StoredPointer ArgumentAddress = MetadataAddress +
@@ -494,7 +535,8 @@ public:
for (StoredPointer i = 0; i < Function->getNumArguments(); ++i,
ArgumentAddress += sizeof(StoredPointer)) {
StoredPointer FlaggedArgumentAddress;
if (!Reader->readInteger(ArgumentAddress, &FlaggedArgumentAddress))
if (!Reader->readInteger(RemoteAddress(ArgumentAddress),
&FlaggedArgumentAddress))
return nullptr;
// TODO: Use target-agnostic FlaggedPointer to mask this!
FlaggedArgumentAddress &= ~((StoredPointer)1);
@@ -517,8 +559,10 @@ public:
auto ProtocolDescriptor = readProtocolDescriptor(ProtocolAddress);
if (!ProtocolDescriptor)
return nullptr;
auto MangledName = Reader->readString(ProtocolDescriptor->Name);
if (MangledName.empty())
std::string MangledName;
if (!Reader->readString(RemoteAddress(ProtocolDescriptor->Name),
MangledName))
return nullptr;
auto Demangled = Demangle::demangleSymbolAsNode(MangledName);
auto Protocol = TypeRef::fromDemangleNode(Demangled);
@@ -607,8 +651,8 @@ public:
auto NameAddress
= resolveRelativeOffset<int32_t>(DescriptorAddress +
Descriptor->offsetToNameOffset());
auto MangledName = Reader->readString(NameAddress);
if (MangledName.empty())
std::string MangledName;
if (!Reader->readString(RemoteAddress(NameAddress), MangledName))
return {};
auto TR = getTypeRef(MetadataAddress);

View File

@@ -0,0 +1,78 @@
//===- CMemoryReader.h - MemoryReader wrapper for C impls -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file declares an implementation of MemoryReader that wraps the
// C interface provided by SwiftRemoteMirror.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_REMOTE_CMEMORYREADER_H
#define SWIFT_REMOTE_CMEMORYREADER_H
#include "swift/SwiftRemoteMirror/MemoryReaderInterface.h"
#include "swift/Remote/MemoryReader.h"
namespace swift {
namespace remote {
/// An implementation of MemoryReader which wraps the C interface offered
/// by SwiftRemoteMirror.
class CMemoryReader final : public MemoryReader {
MemoryReaderImpl Impl;
public:
CMemoryReader(MemoryReaderImpl Impl) : Impl(Impl) {
assert(this->Impl.getPointerSize && "No getPointerSize implementation");
assert(this->Impl.getStringLength && "No stringLength implementation");
assert(this->Impl.readBytes && "No readBytes implementation");
assert(this->Impl.getPointerSize() != 0 && "Invalid target pointer size");
}
uint8_t getPointerSize() override {
return Impl.getPointerSize();
}
uint8_t getSizeSize() override {
return Impl.getSizeSize();
}
RemoteAddress getSymbolAddress(const std::string &name) override {
auto addressData = Impl.getSymbolAddress(name.c_str(), name.size());
return RemoteAddress(addressData);
}
uint64_t getStringLength(RemoteAddress address) {
return Impl.getStringLength(address.getAddressData());
}
bool readString(RemoteAddress address, std::string &dest) override {
auto length = getStringLength(address);
if (!length)
return false;
auto buffer = std::unique_ptr<uint8_t>(new uint8_t[length + 1]);
if (!readBytes(address, buffer.get(), length + 1))
return false;
dest = std::string(reinterpret_cast<const char *>(buffer.get()));
return true;
}
bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) override {
return Impl.readBytes(address.getAddressData(), dest, size);
}
};
}
}
#endif

View File

@@ -0,0 +1,58 @@
//===- InProcessMemoryReader.h - Access to local memory ---------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file declares an abstract interface for working with remote memory.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_REMOTE_INPROCESSMEMORYREADER_H
#define SWIFT_REMOTE_INPROCESSMEMORYREADER_H
#include "swift/Remote/MemoryReader.h"
#include <memory>
#include <dlfcn.h>
namespace swift {
namespace remote {
/// An implementation of MemoryReader which simply reads from the current
/// address space.
class InProcessMemoryReader final : public MemoryReader {
uint8_t getPointerSize() override {
return sizeof(uintptr_t);
}
uint8_t getSizeSize() override {
return sizeof(size_t);
}
RemoteAddress getSymbolAddress(const std::string &name) override {
auto pointer = dlsym(RTLD_DEFAULT, name.c_str());
return RemoteAddress(pointer);
}
bool readString(RemoteAddress address, std::string &dest) override {
dest = address.getLocalPointer<char>();
return true;
}
bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) override {
std::memcpy(dest, address.getLocalPointer<void>(), (size_t) size);
return true;
}
};
}
}
#endif

View File

@@ -0,0 +1,95 @@
//===- MemoryReader.h - Abstract access to remote memory --------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file declares an abstract interface for working with the memory
// of a remote process.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_REMOTE_MEMORYREADER_H
#define SWIFT_REMOTE_MEMORYREADER_H
#include <cstdint>
#include <string>
namespace swift {
namespace remote {
/// An abstract address in the remote process's address space.
class RemoteAddress {
uint64_t Data;
public:
explicit RemoteAddress(const void *localPtr)
: Data(reinterpret_cast<uintptr_t>(localPtr)) {}
explicit RemoteAddress(uint64_t addressData) : Data(addressData) {}
explicit operator bool() const {
return Data != 0;
}
template <class T>
const T *getLocalPointer() const {
return reinterpret_cast<const T*>(static_cast<uintptr_t>(Data));
}
uint64_t getAddressData() const {
return Data;
}
};
/// An abstract interface for reading memory.
///
/// This abstraction presents memory as if it were a read-only
/// representation of the address space of a remote process.
class MemoryReader {
public:
/// Return the size of an ordinary pointer in the remote process, in bytes.
virtual uint8_t getPointerSize() = 0;
/// Return the size of size_t in the remote process, in bytes.
virtual uint8_t getSizeSize() = 0;
/// Look up the given public symbol name in the remote process.
virtual RemoteAddress getSymbolAddress(const std::string &name) = 0;
/// Attempts to read 'size' bytes from the given address in the
/// remote process.
///
/// Returns false if the operation failed.
virtual bool readBytes(RemoteAddress address, uint8_t *dest,
uint64_t size) = 0;
/// Attempts to read a C string from the given address in the remote
/// process.
///
/// Returns false if the operation failed.
virtual bool readString(RemoteAddress address, std::string &dest) = 0;
/// Attempts to read an integer from the given address in the remote
/// process.
///
/// Returns false if the operation failed.
template <typename IntegerType>
bool readInteger(RemoteAddress address, IntegerType *dest) {
return readBytes(address, reinterpret_cast<uint8_t*>(dest),
sizeof(IntegerType));
}
virtual ~MemoryReader() = default;
};
} // end namespace reflection
} // end namespace swift
#endif // SWIFT_REFLECTION_READER_H

View File

@@ -1,8 +1,10 @@
#include "swift/Reflection/ReflectionContext.h"
#include "swift/Remote/CMemoryReader.h"
#include "swift/SwiftRemoteMirror/SwiftRemoteMirror.h"
using namespace swift;
using namespace reflection;
using namespace swift::reflection;
using namespace swift::remote;
using NativeReflectionContext
= ReflectionContext<External<RuntimeTarget<sizeof(uintptr_t)>>>;

View File

@@ -17,6 +17,7 @@
#include "swift/Basic/Demangle.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Reflection/ReflectionContext.h"
#include "swift/Remote/InProcessMemoryReader.h"
#include "swift/Reflection/TypeRef.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/MachO.h"
@@ -36,7 +37,8 @@ using llvm::ArrayRef;
using namespace llvm::object;
using namespace swift;
using namespace reflection;
using namespace swift::reflection;
using namespace swift::remote;
using namespace Demangle;
enum class ActionType {

View File

@@ -22,7 +22,8 @@
#include <unistd.h>
using namespace swift;
using namespace reflection;
using namespace swift::reflection;
using namespace swift::remote;
using namespace Demangle;
static void errorAndExit(const std::string &message) {
@@ -142,9 +143,9 @@ public:
}
}
bool readBytes(addr_t Address, uint8_t *Dest, uint64_t Size) override {
bool readBytes(RemoteAddress Address, uint8_t *Dest, uint64_t Size) override {
StoredPointer TargetAddress = (StoredPointer)Address;
StoredPointer TargetAddress = (StoredPointer)Address.getAddressData();
write(getParentWriteFD(), REQUEST_READ_BYTES, 2);
write(getParentWriteFD(), &TargetAddress, sizeof(TargetAddress));
write(getParentWriteFD(), &Size, sizeof(StoredSize));
@@ -160,13 +161,13 @@ public:
return static_cast<uint64_t>(Length);
}
addr_t getSymbolAddress(const std::string &SymbolName) override {
RemoteAddress getSymbolAddress(const std::string &SymbolName) override {
StoredPointer Address = 0;
write(getParentWriteFD(), REQUEST_SYMBOL_ADDRESS, 2);
write(getParentWriteFD(), SymbolName.c_str(), SymbolName.size());
write(getParentWriteFD(), "\n", 1);
collectBytesFromPipe(&Address, sizeof(Address));
return static_cast<StoredPointer>(Address);
return RemoteAddress(static_cast<StoredPointer>(Address));
}
StoredPointer receiveInstanceAddress() {
@@ -237,7 +238,8 @@ public:
auto buffer = (uint8_t *)malloc(RemoteInfo.TotalSize);
if (!readBytes(RemoteInfo.StartAddress, buffer, RemoteInfo.TotalSize))
if (!readBytes(RemoteAddress(RemoteInfo.StartAddress), buffer,
RemoteInfo.TotalSize))
errorAndExit("Couldn't read reflection information");
auto fieldmd_base
@@ -265,23 +267,26 @@ public:
return Infos;
}
uint64_t getStringLength(StoredPointer Address) {
uint64_t getStringLength(RemoteAddress addr) {
write(getParentWriteFD(), REQUEST_STRING_LENGTH, 2);
StoredPointer Length;
StoredPointer Address = addr.getAddressData();
write(getParentWriteFD(), &Address, sizeof(Address));
StoredPointer Length;
collectBytesFromPipe(&Length, sizeof(Length));
return static_cast<uint64_t>(Length);
}
std::string readString(addr_t Address) override {
bool readString(RemoteAddress Address, std::string &Dest) override {
auto NameSize = getStringLength(Address);
if (!NameSize)
return "";
return false;
auto NameBuffer = std::unique_ptr<uint8_t>(new uint8_t[NameSize + 1]);
if (!readBytes(Address, NameBuffer.get(), NameSize + 1))
return "";
return std::string(reinterpret_cast<const char *>(NameBuffer.get()));
return false;
Dest = reinterpret_cast<const char *>(NameBuffer.get());
return true;
}
};
@@ -321,7 +326,7 @@ static int doDumpHeapInstance(std::string BinaryFilename) {
std::cout << std::hex << instance << std::endl;
StoredPointer isa;
if (!Pipe->readInteger(instance, &isa))
if (!Pipe->readInteger(RemoteAddress(instance), &isa))
errorAndExit("Couldn't get heap object's metadata address");
for (auto &Info : Pipe->receiveReflectionInfo())