Skip to content

Commit 209c242

Browse files
committed
[ORC] Add writePointers to ExecutorProcessControl's MemoryAccess
Add pointer write functionality to MemoryAccess that is needed for implementing redirection manager. It also refactors the code a bit by introducing InProcessMemoryAccess class. Reviewed By: lhames Differential Revision: https://reviews.llvm.org/D157378
1 parent 73086da commit 209c242

File tree

5 files changed

+126
-32
lines changed

5 files changed

+126
-32
lines changed

llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class EPCGenericMemoryAccess : public ExecutorProcessControl::MemoryAccess {
3232
ExecutorAddr WriteUInt32s;
3333
ExecutorAddr WriteUInt64s;
3434
ExecutorAddr WriteBuffers;
35+
ExecutorAddr WritePointers;
3536
};
3637

3738
/// Create an EPCGenericMemoryAccess instance from a given set of
@@ -74,6 +75,13 @@ class EPCGenericMemoryAccess : public ExecutorProcessControl::MemoryAccess {
7475
FAs.WriteBuffers, std::move(OnWriteComplete), Ws);
7576
}
7677

78+
void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
79+
WriteResultFn OnWriteComplete) override {
80+
using namespace shared;
81+
EPC.callSPSWrapperAsync<void(SPSSequence<SPSMemoryAccessPointerWrite>)>(
82+
FAs.WritePointers, std::move(OnWriteComplete), Ws);
83+
}
84+
7785
private:
7886
ExecutorProcessControl &EPC;
7987
FuncAddrs FAs;

llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ class ExecutorProcessControl {
120120
virtual void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
121121
WriteResultFn OnWriteComplete) = 0;
122122

123+
virtual void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
124+
WriteResultFn OnWriteComplete) = 0;
125+
123126
Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) {
124127
std::promise<MSVCPError> ResultP;
125128
auto ResultF = ResultP.get_future();
@@ -159,6 +162,14 @@ class ExecutorProcessControl {
159162
[&](Error Err) { ResultP.set_value(std::move(Err)); });
160163
return ResultF.get();
161164
}
165+
166+
Error writePointers(ArrayRef<tpctypes::PointerWrite> Ws) {
167+
std::promise<MSVCPError> ResultP;
168+
auto ResultF = ResultP.get_future();
169+
writePointersAsync(Ws,
170+
[&](Error Err) { ResultP.set_value(std::move(Err)); });
171+
return ResultF.get();
172+
}
162173
};
163174

164175
/// A pair of a dylib and a set of symbols to be looked up.
@@ -403,21 +414,48 @@ class ExecutorProcessControl {
403414
StringMap<ExecutorAddr> BootstrapSymbols;
404415
};
405416

417+
class InProcessMemoryAccess : public ExecutorProcessControl::MemoryAccess {
418+
public:
419+
InProcessMemoryAccess(bool IsArch64Bit) : IsArch64Bit(IsArch64Bit) {}
420+
void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
421+
WriteResultFn OnWriteComplete) override;
422+
423+
void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,
424+
WriteResultFn OnWriteComplete) override;
425+
426+
void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,
427+
WriteResultFn OnWriteComplete) override;
428+
429+
void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,
430+
WriteResultFn OnWriteComplete) override;
431+
432+
void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
433+
WriteResultFn OnWriteComplete) override;
434+
435+
void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
436+
WriteResultFn OnWriteComplete) override;
437+
438+
private:
439+
bool IsArch64Bit;
440+
};
441+
406442
/// A ExecutorProcessControl instance that asserts if any of its methods are
407443
/// used. Suitable for use is unit tests, and by ORC clients who haven't moved
408444
/// to ExecutorProcessControl-based APIs yet.
409-
class UnsupportedExecutorProcessControl : public ExecutorProcessControl {
445+
class UnsupportedExecutorProcessControl : public ExecutorProcessControl,
446+
private InProcessMemoryAccess {
410447
public:
411448
UnsupportedExecutorProcessControl(
412449
std::shared_ptr<SymbolStringPool> SSP = nullptr,
413-
std::unique_ptr<TaskDispatcher> D = nullptr,
414-
const std::string &TT = "", unsigned PageSize = 0)
415-
: ExecutorProcessControl(SSP ? std::move(SSP)
416-
: std::make_shared<SymbolStringPool>(),
417-
D ? std::move(D)
418-
: std::make_unique<InPlaceTaskDispatcher>()) {
450+
std::unique_ptr<TaskDispatcher> D = nullptr, const std::string &TT = "",
451+
unsigned PageSize = 0)
452+
: ExecutorProcessControl(
453+
SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>(),
454+
D ? std::move(D) : std::make_unique<InPlaceTaskDispatcher>()),
455+
InProcessMemoryAccess(Triple(TT).isArch64Bit()) {
419456
this->TargetTriple = Triple(TT);
420457
this->PageSize = PageSize;
458+
this->MemAccess = this;
421459
}
422460

423461
Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override {
@@ -452,9 +490,8 @@ class UnsupportedExecutorProcessControl : public ExecutorProcessControl {
452490
};
453491

454492
/// A ExecutorProcessControl implementation targeting the current process.
455-
class SelfExecutorProcessControl
456-
: public ExecutorProcessControl,
457-
private ExecutorProcessControl::MemoryAccess {
493+
class SelfExecutorProcessControl : public ExecutorProcessControl,
494+
private InProcessMemoryAccess {
458495
public:
459496
SelfExecutorProcessControl(
460497
std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
@@ -490,21 +527,6 @@ class SelfExecutorProcessControl
490527
Error disconnect() override;
491528

492529
private:
493-
void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
494-
WriteResultFn OnWriteComplete) override;
495-
496-
void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,
497-
WriteResultFn OnWriteComplete) override;
498-
499-
void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,
500-
WriteResultFn OnWriteComplete) override;
501-
502-
void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,
503-
WriteResultFn OnWriteComplete) override;
504-
505-
void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
506-
WriteResultFn OnWriteComplete) override;
507-
508530
static shared::CWrapperFunctionResult
509531
jitDispatchViaWrapperFunctionManager(void *Ctx, const void *FnTag,
510532
const char *Data, size_t Size);

llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ struct BufferWrite {
100100
StringRef Buffer;
101101
};
102102

103+
/// Describes a write to a pointer.
104+
/// For use with TargetProcessControl::MemoryAccess objects.
105+
struct PointerWrite {
106+
PointerWrite() = default;
107+
PointerWrite(ExecutorAddr Addr, ExecutorAddr Value)
108+
: Addr(Addr), Value(Value) {}
109+
110+
ExecutorAddr Addr;
111+
ExecutorAddr Value;
112+
};
113+
103114
/// A handle used to represent a loaded dylib in the target process.
104115
using DylibHandle = ExecutorAddr;
105116

@@ -133,6 +144,7 @@ using SPSMemoryAccessUInt32Write = SPSMemoryAccessUIntWrite<uint32_t>;
133144
using SPSMemoryAccessUInt64Write = SPSMemoryAccessUIntWrite<uint64_t>;
134145

135146
using SPSMemoryAccessBufferWrite = SPSTuple<SPSExecutorAddr, SPSSequence<char>>;
147+
using SPSMemoryAccessPointerWrite = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>;
136148

137149
template <>
138150
class SPSSerializationTraits<SPSRemoteAllocGroup, tpctypes::RemoteAllocGroup> {
@@ -302,6 +314,26 @@ class SPSSerializationTraits<SPSMemoryAccessBufferWrite,
302314
}
303315
};
304316

317+
template <>
318+
class SPSSerializationTraits<SPSMemoryAccessPointerWrite,
319+
tpctypes::PointerWrite> {
320+
public:
321+
static size_t size(const tpctypes::PointerWrite &W) {
322+
return SPSTuple<SPSExecutorAddr, SPSExecutorAddr>::AsArgList::size(W.Addr,
323+
W.Value);
324+
}
325+
326+
static bool serialize(SPSOutputBuffer &OB, const tpctypes::PointerWrite &W) {
327+
return SPSTuple<SPSExecutorAddr, SPSExecutorAddr>::AsArgList::serialize(
328+
OB, W.Addr, W.Value);
329+
}
330+
331+
static bool deserialize(SPSInputBuffer &IB, tpctypes::PointerWrite &W) {
332+
return SPSTuple<SPSExecutorAddr, SPSExecutorAddr>::AsArgList::deserialize(
333+
IB, W.Addr, W.Value);
334+
}
335+
};
336+
305337
} // end namespace shared
306338
} // end namespace orc
307339
} // end namespace llvm

llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ SelfExecutorProcessControl::SelfExecutorProcessControl(
2929
std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
3030
Triple TargetTriple, unsigned PageSize,
3131
std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
32-
: ExecutorProcessControl(std::move(SSP), std::move(D)) {
32+
: ExecutorProcessControl(std::move(SSP), std::move(D)),
33+
InProcessMemoryAccess(TargetTriple.isArch64Bit()) {
3334

3435
OwnedMemMgr = std::move(MemMgr);
3536
if (!OwnedMemMgr)
@@ -146,41 +147,54 @@ Error SelfExecutorProcessControl::disconnect() {
146147
return Error::success();
147148
}
148149

149-
void SelfExecutorProcessControl::writeUInt8sAsync(
150-
ArrayRef<tpctypes::UInt8Write> Ws, WriteResultFn OnWriteComplete) {
150+
void InProcessMemoryAccess::writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
151+
WriteResultFn OnWriteComplete) {
151152
for (auto &W : Ws)
152153
*W.Addr.toPtr<uint8_t *>() = W.Value;
153154
OnWriteComplete(Error::success());
154155
}
155156

156-
void SelfExecutorProcessControl::writeUInt16sAsync(
157+
void InProcessMemoryAccess::writeUInt16sAsync(
157158
ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) {
158159
for (auto &W : Ws)
159160
*W.Addr.toPtr<uint16_t *>() = W.Value;
160161
OnWriteComplete(Error::success());
161162
}
162163

163-
void SelfExecutorProcessControl::writeUInt32sAsync(
164+
void InProcessMemoryAccess::writeUInt32sAsync(
164165
ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) {
165166
for (auto &W : Ws)
166167
*W.Addr.toPtr<uint32_t *>() = W.Value;
167168
OnWriteComplete(Error::success());
168169
}
169170

170-
void SelfExecutorProcessControl::writeUInt64sAsync(
171+
void InProcessMemoryAccess::writeUInt64sAsync(
171172
ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) {
172173
for (auto &W : Ws)
173174
*W.Addr.toPtr<uint64_t *>() = W.Value;
174175
OnWriteComplete(Error::success());
175176
}
176177

177-
void SelfExecutorProcessControl::writeBuffersAsync(
178+
void InProcessMemoryAccess::writeBuffersAsync(
178179
ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) {
179180
for (auto &W : Ws)
180181
memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size());
181182
OnWriteComplete(Error::success());
182183
}
183184

185+
void InProcessMemoryAccess::writePointersAsync(
186+
ArrayRef<tpctypes::PointerWrite> Ws, WriteResultFn OnWriteComplete) {
187+
if (IsArch64Bit) {
188+
for (auto &W : Ws)
189+
*W.Addr.toPtr<uint64_t *>() = W.Value.getValue();
190+
} else {
191+
for (auto &W : Ws)
192+
*W.Addr.toPtr<uint32_t *>() = static_cast<uint32_t>(W.Value.getValue());
193+
}
194+
195+
OnWriteComplete(Error::success());
196+
}
197+
184198
shared::CWrapperFunctionResult
185199
SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
186200
void *Ctx, const void *FnTag, const char *Data, size_t Size) {

llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ llvm::orc::shared::CWrapperFunctionResult testWriteBuffers(const char *ArgData,
4141
.release();
4242
}
4343

44+
llvm::orc::shared::CWrapperFunctionResult testWritePointers(const char *ArgData,
45+
size_t ArgSize) {
46+
return WrapperFunction<void(SPSSequence<SPSMemoryAccessPointerWrite>)>::
47+
handle(ArgData, ArgSize,
48+
[](std::vector<tpctypes::PointerWrite> Ws) {
49+
for (auto &W : Ws)
50+
*W.Addr.template toPtr<uint64_t *>() = W.Value.getValue();
51+
})
52+
.release();
53+
}
54+
4455
TEST(EPCGenericMemoryAccessTest, MemWrites) {
4556
auto SelfEPC = cantFail(SelfExecutorProcessControl::Create());
4657

@@ -54,6 +65,7 @@ TEST(EPCGenericMemoryAccessTest, MemWrites) {
5465
FAs.WriteUInt64s = ExecutorAddr::fromPtr(
5566
&testWriteUInts<tpctypes::UInt64Write, SPSMemoryAccessUInt64Write>);
5667
FAs.WriteBuffers = ExecutorAddr::fromPtr(&testWriteBuffers);
68+
FAs.WritePointers = ExecutorAddr::fromPtr(&testWritePointers);
5769

5870
auto MemAccess = std::make_unique<EPCGenericMemoryAccess>(*SelfEPC, FAs);
5971

@@ -62,6 +74,7 @@ TEST(EPCGenericMemoryAccessTest, MemWrites) {
6274
uint16_t Test_UInt16 = 0;
6375
uint32_t Test_UInt32 = 0;
6476
uint64_t Test_UInt64 = 0;
77+
uint64_t Test_Pointer = 0;
6578
char Test_Buffer[21];
6679

6780
auto Err1 =
@@ -93,6 +106,11 @@ TEST(EPCGenericMemoryAccessTest, MemWrites) {
93106
EXPECT_THAT_ERROR(std::move(Err5), Succeeded());
94107
EXPECT_EQ(StringRef(Test_Buffer, TestMsg.size()), TestMsg);
95108

109+
auto Err6 = MemAccess->writePointers(
110+
{{ExecutorAddr::fromPtr(&Test_Pointer), ExecutorAddr(1U)}});
111+
EXPECT_THAT_ERROR(std::move(Err6), Succeeded());
112+
EXPECT_EQ(Test_Pointer, 1U);
113+
96114
cantFail(SelfEPC->disconnect());
97115
}
98116

0 commit comments

Comments
 (0)