Files
swift-mirror/include/swift/Reflection/Reader.h
David Farler c5298c0b52 [Reflection] Start fleshing out the remote mirrors library
- Don't depend on LLVM Support and swiftBasic as this will bring in
  llvmSupport and other heavy dependencies, which we don't build for
  non-host architectures right now anyway.

- Add a reader template that works with the same (albeit somewhat
  clunky) interface in-process with the runtime and remotely, by having
  the memory tool supply a function that will copy data from the remote
  process.

- Add a Buffer type to abstract indirecting pointers in a remote address
  space, which is handled by the memory reader.

- Start sketching out the C remote mirrors interface.
2016-02-12 16:34:28 -08:00

115 lines
2.8 KiB
C++

#ifndef SWIFT_REFLECTION_READER_H
#define SWIFT_REFLECTION_READER_H
#include <cstdint>
#include <memory>
class BufferImpl;
namespace swift {
namespace reflection {
using CopyFunction = size_t (*)(uintptr_t Source, void *Dest, size_t Size);
/// An abstract impl interface for getting the head of what may be a buffer
/// copied from an external address space.
class BufferImpl {
public:
virtual const void *getPointer() = 0;
virtual ~BufferImpl() {}
};
/// A trivial wrapper for pointers in the current address space.
template <typename T>
class InternalBuffer final : public BufferImpl {
const T *Source;
public:
InternalBuffer(const T *Source) : Source(Source) {}
virtual const void *getPointer() override {
return reinterpret_cast<const void *>(Source);
}
};
/// A buffer of data copied out of an external address space.
template <typename T>
class ExternalBuffer final : public BufferImpl {
uint8_t Buf[sizeof(T)] = {0};
public:
virtual const void *getPointer() override {
return reinterpret_cast<const void *>(Buf);
}
};
/// An abstraction over a pointer which may be in another
/// address space.
///
/// These will always be backed by real data, but it is
/// important not to indirect twice out of this type.
/// Ask the MemoryReader to read each pointer. For example:
/// Buffer<MyStruct> MS = Reader.read(APointer);
/// int i = MS->i; // OK.
///
/// If MyStruct has a nested MyStruct *, you read it like so:
/// Buffer<MyStruct> MS = Reader.read(MS->nestedMyStruct);
template <typename T>
class Buffer {
friend class MemoryReader;
std::unique_ptr<BufferImpl> Impl;
Buffer() : Impl(nullptr) {}
Buffer(std::unique_ptr<BufferImpl> Impl)
: Impl(std::move(Impl)) {}
public:
const T& operator*() {
return *reinterpret_cast<const T*>(Impl->getPointer());
}
const T* operator->() {
return reinterpret_cast<const T*>(Impl->getPointer());
}
operator bool() const {
return bool(Impl);
}
};
class MemoryReader {
CopyFunction copy;
public:
MemoryReader() : copy(nullptr) {}
MemoryReader(CopyFunction copy) : copy(copy) {}
template <typename T>
Buffer<T> read(const T *Source) {
using External = ExternalBuffer<T>;
using Internal = InternalBuffer<T>;
if (copy) {
auto external = std::unique_ptr<External>(new External());
auto bytesCopied = copy(reinterpret_cast<uintptr_t>(Source),
const_cast<void *>(external->getPointer()),
sizeof(T));
if (bytesCopied != sizeof(T))
return Buffer<T>();
return Buffer<T>(std::move(external));
} else {
auto internal = new Internal(Source);
return Buffer<T>(std::unique_ptr<Internal>(internal));
}
}
};
} // end namespace reflection
} // end namespace swift
#endif // SWIFT_REFLECTION_READER_H