mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[RemoteMirrors] Change MemoryReader::readBytes to return a unique_ptr instead of a tuple so that the destructor handles freeing the memory.
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
#ifndef __LP64__
|
#ifndef __LP64__
|
||||||
@@ -75,7 +76,9 @@ class ReflectionContext
|
|||||||
|
|
||||||
std::unordered_map<typename super::StoredPointer, const TypeInfo *> Cache;
|
std::unordered_map<typename super::StoredPointer, const TypeInfo *> Cache;
|
||||||
|
|
||||||
std::vector<std::function<void()>> freeFuncs;
|
/// All buffers we need to keep around long term. This will automatically free them
|
||||||
|
/// when this object is destroyed.
|
||||||
|
std::vector<MemoryReader::ReadBytesResult> savedBuffers;
|
||||||
std::vector<std::tuple<RemoteAddress, RemoteAddress>> dataSegments;
|
std::vector<std::tuple<RemoteAddress, RemoteAddress>> dataSegments;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -95,11 +98,6 @@ public:
|
|||||||
ReflectionContext(const ReflectionContext &other) = delete;
|
ReflectionContext(const ReflectionContext &other) = delete;
|
||||||
ReflectionContext &operator=(const ReflectionContext &other) = delete;
|
ReflectionContext &operator=(const ReflectionContext &other) = delete;
|
||||||
|
|
||||||
~ReflectionContext() {
|
|
||||||
for (auto f : freeFuncs)
|
|
||||||
f();
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryReader &getReader() {
|
MemoryReader &getReader() {
|
||||||
return *this->Reader;
|
return *this->Reader;
|
||||||
}
|
}
|
||||||
@@ -115,50 +113,38 @@ public:
|
|||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
bool addImage(RemoteAddress ImageStart) {
|
bool addImage(RemoteAddress ImageStart) {
|
||||||
const void *Buf;
|
auto Buf = this->getReader().readBytes(ImageStart, sizeof(MachHeader));
|
||||||
std::function<void()> FreeFunc;
|
if (!Buf)
|
||||||
|
|
||||||
std::tie(Buf, FreeFunc) =
|
|
||||||
this->getReader().readBytes(ImageStart, sizeof(MachHeader));
|
|
||||||
if (Buf == nullptr)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto Header = reinterpret_cast<MachHeader *>(Buf);
|
auto Header = reinterpret_cast<MachHeader *>(Buf.get());
|
||||||
|
|
||||||
if (Header->magic != MH_MAGIC && Header->magic != MH_MAGIC_64) {
|
if (Header->magic != MH_MAGIC && Header->magic != MH_MAGIC_64) {
|
||||||
FreeFunc();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Length = Header->sizeofcmds;
|
auto Length = Header->sizeofcmds;
|
||||||
FreeFunc();
|
|
||||||
|
|
||||||
// Read the commands.
|
// Read the commands.
|
||||||
std::tie(Buf, FreeFunc) = this->getReader().readBytes(ImageStart, Length);
|
Buf = this->getReader().readBytes(ImageStart, Length);
|
||||||
|
if (!Buf)
|
||||||
if (Buf == nullptr)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Find the TEXT segment and figure out where the end is.
|
// Find the TEXT segment and figure out where the end is.
|
||||||
Header = reinterpret_cast<MachHeader *>(Buf);
|
Header = reinterpret_cast<MachHeader *>(Buf.get());
|
||||||
unsigned long TextSize;
|
unsigned long TextSize;
|
||||||
auto *TextSegment = getsegmentdata(Header, "__TEXT", &TextSize);
|
auto *TextSegment = getsegmentdata(Header, "__TEXT", &TextSize);
|
||||||
if (TextSegment == nullptr) {
|
if (TextSegment == nullptr)
|
||||||
FreeFunc();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
auto TextEnd =
|
auto TextEnd =
|
||||||
TextSegment - reinterpret_cast<const uint8_t *>(Buf) + TextSize;
|
TextSegment - reinterpret_cast<const uint8_t *>(Buf.get()) + TextSize;
|
||||||
FreeFunc();
|
|
||||||
|
|
||||||
// Read everything including the TEXT segment.
|
// Read everything including the TEXT segment.
|
||||||
std::tie(Buf, FreeFunc) = this->getReader().readBytes(ImageStart, TextEnd);
|
Buf = this->getReader().readBytes(ImageStart, TextEnd);
|
||||||
|
if (!Buf)
|
||||||
if (Buf == nullptr)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Read all the metadata parts.
|
// Read all the metadata parts.
|
||||||
Header = reinterpret_cast<MachHeader *>(Buf);
|
Header = reinterpret_cast<MachHeader *>(Buf.get());
|
||||||
|
|
||||||
// The docs say "not all sections may be present." We'll succeed if ANY of
|
// The docs say "not all sections may be present." We'll succeed if ANY of
|
||||||
// them are present. Not sure if that's the right thing to do.
|
// them are present. Not sure if that's the right thing to do.
|
||||||
@@ -173,12 +159,10 @@ public:
|
|||||||
|
|
||||||
bool success = FieldMd.second || AssocTyMd.second || BuiltinTyMd.second ||
|
bool success = FieldMd.second || AssocTyMd.second || BuiltinTyMd.second ||
|
||||||
CaptureMd.second || TyperefMd.second || ReflStrMd.second;
|
CaptureMd.second || TyperefMd.second || ReflStrMd.second;
|
||||||
if (!success) {
|
if (!success)
|
||||||
FreeFunc();
|
return false;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto LocalStartAddress = reinterpret_cast<uintptr_t>(Buf);
|
auto LocalStartAddress = reinterpret_cast<uintptr_t>(Buf.get());
|
||||||
auto RemoteStartAddress =
|
auto RemoteStartAddress =
|
||||||
reinterpret_cast<uint64_t>(ImageStart.getAddressData());
|
reinterpret_cast<uint64_t>(ImageStart.getAddressData());
|
||||||
|
|
||||||
@@ -194,17 +178,18 @@ public:
|
|||||||
|
|
||||||
this->addReflectionInfo(info);
|
this->addReflectionInfo(info);
|
||||||
|
|
||||||
freeFuncs.push_back(FreeFunc);
|
|
||||||
|
|
||||||
unsigned long DataSize;
|
unsigned long DataSize;
|
||||||
auto *DataSegment = getsegmentdata(Header, "__DATA", &DataSize);
|
auto *DataSegment = getsegmentdata(Header, "__DATA", &DataSize);
|
||||||
if (DataSegment != nullptr) {
|
if (DataSegment != nullptr) {
|
||||||
auto DataSegmentStart = DataSegment - reinterpret_cast<const uint8_t *>(Buf)
|
auto DataSegmentStart = DataSegment - reinterpret_cast<const uint8_t *>(Buf.get())
|
||||||
+ ImageStart.getAddressData();
|
+ ImageStart.getAddressData();
|
||||||
auto DataSegmentEnd = DataSegmentStart + DataSize;
|
auto DataSegmentEnd = DataSegmentStart + DataSize;
|
||||||
dataSegments.push_back(std::make_tuple(RemoteAddress(DataSegmentStart),
|
dataSegments.push_back(std::make_tuple(RemoteAddress(DataSegmentStart),
|
||||||
RemoteAddress(DataSegmentEnd)));
|
RemoteAddress(DataSegmentEnd)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
savedBuffers.push_back(std::move(Buf));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // defined(__APPLE__) && defined(__MACH__)
|
#endif // defined(__APPLE__) && defined(__MACH__)
|
||||||
|
|||||||
@@ -62,31 +62,26 @@ public:
|
|||||||
if (!length)
|
if (!length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const void *ptr;
|
auto Buf = readBytes(address, length);
|
||||||
std::function<void()> freeFunc;
|
if (!Buf)
|
||||||
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 *>(Buf.get()), length);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<const void *, std::function<void()>>
|
ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
|
||||||
readBytes(RemoteAddress address, uint64_t size) override {
|
|
||||||
void *FreeContext;
|
void *FreeContext;
|
||||||
auto Ptr = Impl.readBytes(Impl.reader_context, address.getAddressData(), size,
|
auto Ptr = Impl.readBytes(Impl.reader_context, address.getAddressData(), size,
|
||||||
&FreeContext);
|
&FreeContext);
|
||||||
|
|
||||||
auto Free = Impl.free;
|
auto Free = Impl.free;
|
||||||
if (Free == nullptr)
|
if (Free == nullptr)
|
||||||
return std::make_tuple(Ptr, []{});
|
return ReadBytesResult(Ptr, [](const void *) {});
|
||||||
|
|
||||||
auto ReaderContext = Impl.reader_context;
|
auto ReaderContext = Impl.reader_context;
|
||||||
auto freeLambda = [=]{ Free(ReaderContext, Ptr, FreeContext); };
|
auto freeLambda = [=](const void *Ptr) { Free(ReaderContext, Ptr, FreeContext); };
|
||||||
return std::make_tuple(Ptr, freeLambda);
|
return ReadBytesResult(Ptr, freeLambda);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,8 @@ class InProcessMemoryReader final : public MemoryReader {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<const void *, std::function<void()>>
|
ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
|
||||||
readBytes(RemoteAddress address, uint64_t size) override {
|
return ReadBytesResult(address.getLocalPointer<void>(), [](const void *) {});
|
||||||
return std::make_tuple(address.getLocalPointer<void>(), []{});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "swift/Remote/RemoteAddress.h"
|
#include "swift/Remote/RemoteAddress.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
@@ -33,6 +34,9 @@ namespace remote {
|
|||||||
/// representation of the address space of a remote process.
|
/// representation of the address space of a remote process.
|
||||||
class MemoryReader {
|
class MemoryReader {
|
||||||
public:
|
public:
|
||||||
|
/// A convenient name for the return type from readBytes.
|
||||||
|
using ReadBytesResult = std::unique_ptr<const void, std::function<void(const void *)>>;
|
||||||
|
|
||||||
/// Return the size of an ordinary pointer in the remote process, in bytes.
|
/// Return the size of an ordinary pointer in the remote process, in bytes.
|
||||||
virtual uint8_t getPointerSize() = 0;
|
virtual uint8_t getPointerSize() = 0;
|
||||||
|
|
||||||
@@ -65,15 +69,17 @@ 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 std::tuple<const void *, std::function<void()>>
|
virtual ReadBytesResult
|
||||||
readBytes(RemoteAddress address, uint64_t size) {
|
readBytes(RemoteAddress address, uint64_t size) {
|
||||||
void *buffer = malloc(size);
|
auto *Buf = malloc(size);
|
||||||
bool success = readBytes(address, reinterpret_cast<uint8_t *>(buffer), size);
|
ReadBytesResult Result(Buf, [](const void *ptr) {
|
||||||
|
free(const_cast<void *>(ptr));
|
||||||
|
});
|
||||||
|
bool success = readBytes(address, reinterpret_cast<uint8_t *>(Buf), size);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
free(buffer);
|
Result.reset();
|
||||||
return std::make_tuple(nullptr, []{});
|
|
||||||
}
|
}
|
||||||
return std::make_tuple(buffer, [=]{ free(buffer); });
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to read 'size' bytes from the given address in the
|
/// Attempts to read 'size' bytes from the given address in the
|
||||||
@@ -84,16 +90,12 @@ 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 bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) {
|
virtual bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) {
|
||||||
const void *ptr;
|
auto Ptr = readBytes(address, size);
|
||||||
std::function<void()> freeFunc;
|
if (!Ptr)
|
||||||
std::tie(ptr, freeFunc) = readBytes(address, size);
|
|
||||||
if (ptr != nullptr) {
|
|
||||||
memcpy(dest, ptr, size);
|
|
||||||
freeFunc();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
memcpy(dest, Ptr.get(), size);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~MemoryReader() = default;
|
virtual ~MemoryReader() = default;
|
||||||
|
|||||||
@@ -196,14 +196,12 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<const void *, std::function<void()>>
|
ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
|
||||||
readBytes(RemoteAddress address, uint64_t size) override {
|
|
||||||
if (!isAddressValid(address, size))
|
if (!isAddressValid(address, size))
|
||||||
return std::make_tuple(nullptr, []{});
|
return ReadBytesResult(nullptr, [](const void *){});
|
||||||
|
|
||||||
// TODO: Account for offset in ELF binaries
|
// TODO: Account for offset in ELF binaries
|
||||||
auto ptr = (const void *)address.getAddressData();
|
return ReadBytesResult((const void *)address.getAddressData(), [](const void *) {});
|
||||||
return std::make_tuple(ptr, []{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readString(RemoteAddress address, std::string &dest) override {
|
bool readString(RemoteAddress address, std::string &dest) override {
|
||||||
|
|||||||
Reference in New Issue
Block a user