[Reflection] Change ReadBytesFunction to return a pointer rather than copying data, and adjust its users accordingly.

rdar://problem/37538580
This commit is contained in:
Mike Ash
2018-02-21 12:17:28 -05:00
parent 1dcdd939ca
commit bf58357e54
6 changed files with 71 additions and 30 deletions

View File

@@ -62,17 +62,27 @@ public:
if (!length) if (!length)
return false; return false;
auto buffer = std::unique_ptr<uint8_t>(new uint8_t[length + 1]); const void *ptr;
if (!readBytes(address, buffer.get(), length + 1)) std::function<void()> freeFunc;
std::tie(ptr, freeFunc) = readBytes(address, length);
if (ptr != nullptr) {
dest = std::string(reinterpret_cast<const char *>(ptr), length);
freeFunc();
return true;
} else {
return false; return false;
}
dest = std::string(reinterpret_cast<const char *>(buffer.get()));
return true;
} }
bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) override { std::tuple<const void *, std::function<void()>>
return Impl.readBytes(Impl.reader_context, readBytes(RemoteAddress address, uint64_t size) override {
address.getAddressData(), dest, size) != 0; FreeBytesFunction freeFunc;
void *freeContext;
auto ptr = Impl.readBytes(Impl.reader_context, address.getAddressData(), size,
&freeFunc, &freeContext);
auto freeLambda = [=]{ freeFunc(ptr, freeContext); };
return std::make_tuple(ptr, freeLambda);
} }
}; };

View File

@@ -42,9 +42,9 @@ class InProcessMemoryReader final : public MemoryReader {
return true; return true;
} }
bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) override { std::tuple<const void *, std::function<void()>>
std::memcpy(dest, address.getLocalPointer<void>(), (size_t) size); readBytes(RemoteAddress address, uint64_t size) override {
return true; return std::make_tuple(address.getLocalPointer<void>(), []{});
} }
}; };

View File

@@ -20,7 +20,9 @@
#include "swift/Remote/RemoteAddress.h" #include "swift/Remote/RemoteAddress.h"
#include <functional>
#include <string> #include <string>
#include <tuple>
namespace swift { namespace swift {
namespace remote { namespace remote {
@@ -40,12 +42,12 @@ public:
/// Look up the given public symbol name in the remote process. /// Look up the given public symbol name in the remote process.
virtual RemoteAddress getSymbolAddress(const std::string &name) = 0; virtual RemoteAddress getSymbolAddress(const std::string &name) = 0;
/// Attempts to read 'size' bytes from the given address in the /// Attempts to read 'size' bytes from the given address in the remote process.
/// remote process.
/// ///
/// Returns false if the operation failed. /// Returns a pointer to the requested data and a function that must be called to
virtual bool readBytes(RemoteAddress address, uint8_t *dest, /// free that data when done. The pointer will be NULL if the operation failed.
uint64_t size) = 0; virtual std::tuple<const void *, std::function<void()>>
readBytes(RemoteAddress address, uint64_t size) = 0;
/// Attempts to read a C string from the given address in the remote /// Attempts to read a C string from the given address in the remote
/// process. /// process.
@@ -63,6 +65,23 @@ public:
sizeof(IntegerType)); sizeof(IntegerType));
} }
/// Attempts to read 'size' bytes from the given address in the
/// remote process.
///
/// Returns false if the operation failed.
bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) {
const void *ptr;
std::function<void()> freeFunc;
std::tie(ptr, freeFunc) = readBytes(address, size);
if (ptr != nullptr) {
memcpy(dest, ptr, size);
freeFunc();
return true;
} else {
return false;
}
}
virtual ~MemoryReader() = default; virtual ~MemoryReader() = default;
}; };

View File

@@ -32,13 +32,14 @@ extern "C" {
// in the system library, so we use 'swift_addr_t'. // in the system library, so we use 'swift_addr_t'.
typedef uint64_t swift_addr_t; typedef uint64_t swift_addr_t;
typedef void (*FreeBytesFunction)(void *bytes, void *context); typedef void (*FreeBytesFunction)(const void *bytes, void *context);
typedef uint8_t (*PointerSizeFunction)(void *reader_context); typedef uint8_t (*PointerSizeFunction)(void *reader_context);
typedef uint8_t (*SizeSizeFunction)(void *reader_context); typedef uint8_t (*SizeSizeFunction)(void *reader_context);
typedef void *(*ReadBytesFunction)(void *reader_context, swift_addr_t address, typedef const void *(*ReadBytesFunction)(void *reader_context, swift_addr_t address,
uint64_t size, FreeBytesFunction *outFreeFunction, uint64_t size,
void **outFreeContext); FreeBytesFunction *outFreeFunction,
void **outFreeContext);
typedef uint64_t (*GetStringLengthFunction)(void *reader_context, typedef uint64_t (*GetStringLengthFunction)(void *reader_context,
swift_addr_t address); swift_addr_t address);
typedef swift_addr_t (*GetSymbolAddressFunction)(void *reader_context, typedef swift_addr_t (*GetSymbolAddressFunction)(void *reader_context,

View File

@@ -191,15 +191,14 @@ public:
return false; return false;
} }
bool readBytes(RemoteAddress address, uint8_t *dest, std::tuple<const void *, std::function<void()>>
uint64_t size) override { readBytes(RemoteAddress address, uint64_t size) override {
if (!isAddressValid(address, size)) if (!isAddressValid(address, size))
return false; return std::make_tuple(nullptr, []{});
// TODO: Account for offset in ELF binaries // TODO: Account for offset in ELF binaries
auto src = (const void *)address.getAddressData(); auto ptr = (const void *)address.getAddressData();
memcpy(dest, (const void*)src, size); return std::make_tuple(ptr, []{});
return true;
} }
bool readString(RemoteAddress address, std::string &dest) override { bool readString(RemoteAddress address, std::string &dest) override {

View File

@@ -95,9 +95,15 @@ void PipeMemoryReader_collectBytesFromPipe(const PipeMemoryReader *Reader,
} }
} }
static void PipeMemoryReader_freeBytes(const void *bytes, void *context) {
free((void *)bytes);
}
static static
int PipeMemoryReader_readBytes(void *Context, swift_addr_t Address, void *Dest, const void *PipeMemoryReader_readBytes(void *Context, swift_addr_t Address,
uint64_t Size) { uint64_t Size,
FreeBytesFunction *outFreeFunction,
void **outFreeContext) {
const PipeMemoryReader *Reader = (const PipeMemoryReader *)Context; const PipeMemoryReader *Reader = (const PipeMemoryReader *)Context;
uintptr_t TargetAddress = Address; uintptr_t TargetAddress = Address;
size_t TargetSize = (size_t)Size; size_t TargetSize = (size_t)Size;
@@ -105,8 +111,14 @@ int PipeMemoryReader_readBytes(void *Context, swift_addr_t Address, void *Dest,
write(WriteFD, REQUEST_READ_BYTES, 2); write(WriteFD, REQUEST_READ_BYTES, 2);
write(WriteFD, &TargetAddress, sizeof(TargetAddress)); write(WriteFD, &TargetAddress, sizeof(TargetAddress));
write(WriteFD, &TargetSize, sizeof(size_t)); write(WriteFD, &TargetSize, sizeof(size_t));
PipeMemoryReader_collectBytesFromPipe(Reader, Dest, Size);
return 1; void *Buf = malloc(Size);
PipeMemoryReader_collectBytesFromPipe(Reader, Buf, Size);
*outFreeFunction = PipeMemoryReader_freeBytes;
*outFreeContext = NULL;
return Buf;
} }
static static