1 //===---- RemoteTargetExternal.cpp - LLVM out-of-process JIT execution ----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Implementation of the RemoteTargetExternal class which executes JITed code
11 // in a separate process from where it was built.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/Config/config.h"
16 #include "RemoteTarget.h"
17 #include "RemoteTargetExternal.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/Support/DataTypes.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Memory.h"
23 #include "llvm/Support/Program.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include <string>
26
27 using namespace llvm;
28
29 #define DEBUG_TYPE "lli"
30
allocateSpace(size_t Size,unsigned Alignment,uint64_t & Address)31 bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,
32 uint64_t &Address) {
33 DEBUG(dbgs() << "Message [allocate space] size: " << Size <<
34 ", align: " << Alignment << "\n");
35 if (!SendAllocateSpace(Alignment, Size)) {
36 ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
37 return false;
38 }
39 if (!Receive(LLI_AllocationResult, Address)) {
40 ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
41 return false;
42 }
43 if (Address == 0) {
44 ErrorMsg += "failed allocation, (RemoteTargetExternal::allocateSpace)";
45 return false;
46 }
47 DEBUG(dbgs() << "Message [allocate space] addr: 0x" <<
48 format("%llx", Address) << "\n");
49 return true;
50 }
51
loadData(uint64_t Address,const void * Data,size_t Size)52 bool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {
53 DEBUG(dbgs() << "Message [load data] addr: 0x" << format("%llx", Address) <<
54 ", size: " << Size << "\n");
55 if (!SendLoadSection(Address, Data, (uint32_t)Size, false)) {
56 ErrorMsg += ", (RemoteTargetExternal::loadData)";
57 return false;
58 }
59 int Status = LLI_Status_Success;
60 if (!Receive(LLI_LoadResult, Status)) {
61 ErrorMsg += ", (RemoteTargetExternal::loadData)";
62 return false;
63 }
64 if (Status == LLI_Status_IncompleteMsg) {
65 ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
66 return false;
67 }
68 if (Status == LLI_Status_NotAllocated) {
69 ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
70 return false;
71 }
72 DEBUG(dbgs() << "Message [load data] complete\n");
73 return true;
74 }
75
loadCode(uint64_t Address,const void * Data,size_t Size)76 bool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {
77 DEBUG(dbgs() << "Message [load code] addr: 0x" << format("%llx", Address) <<
78 ", size: " << Size << "\n");
79 if (!SendLoadSection(Address, Data, (uint32_t)Size, true)) {
80 ErrorMsg += ", (RemoteTargetExternal::loadCode)";
81 return false;
82 }
83 int Status = LLI_Status_Success;
84 if (!Receive(LLI_LoadResult, Status)) {
85 ErrorMsg += ", (RemoteTargetExternal::loadCode)";
86 return false;
87 }
88 if (Status == LLI_Status_IncompleteMsg) {
89 ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
90 return false;
91 }
92 if (Status == LLI_Status_NotAllocated) {
93 ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
94 return false;
95 }
96 DEBUG(dbgs() << "Message [load code] complete\n");
97 return true;
98 }
99
executeCode(uint64_t Address,int32_t & RetVal)100 bool RemoteTargetExternal::executeCode(uint64_t Address, int32_t &RetVal) {
101 DEBUG(dbgs() << "Message [exectue code] addr: " << Address << "\n");
102 if (!SendExecute(Address)) {
103 ErrorMsg += ", (RemoteTargetExternal::executeCode)";
104 return false;
105 }
106 if (!Receive(LLI_ExecutionResult, RetVal)) {
107 ErrorMsg += ", (RemoteTargetExternal::executeCode)";
108 return false;
109 }
110 DEBUG(dbgs() << "Message [exectue code] return: " << RetVal << "\n");
111 return true;
112 }
113
stop()114 void RemoteTargetExternal::stop() {
115 SendTerminate();
116 RPC.Wait();
117 }
118
SendAllocateSpace(uint32_t Alignment,uint32_t Size)119 bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
120 if (!SendHeader(LLI_AllocateSpace)) {
121 ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
122 return false;
123 }
124
125 AppendWrite((const void *)&Alignment, 4);
126 AppendWrite((const void *)&Size, 4);
127
128 if (!SendPayload()) {
129 ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
130 return false;
131 }
132 return true;
133 }
134
SendLoadSection(uint64_t Addr,const void * Data,uint32_t Size,bool IsCode)135 bool RemoteTargetExternal::SendLoadSection(uint64_t Addr,
136 const void *Data,
137 uint32_t Size,
138 bool IsCode) {
139 LLIMessageType MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
140 if (!SendHeader(MsgType)) {
141 ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
142 return false;
143 }
144
145 AppendWrite((const void *)&Addr, 8);
146 AppendWrite(Data, Size);
147
148 if (!SendPayload()) {
149 ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
150 return false;
151 }
152 return true;
153 }
154
SendExecute(uint64_t Addr)155 bool RemoteTargetExternal::SendExecute(uint64_t Addr) {
156 if (!SendHeader(LLI_Execute)) {
157 ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
158 return false;
159 }
160
161 AppendWrite((const void *)&Addr, 8);
162
163 if (!SendPayload()) {
164 ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
165 return false;
166 }
167 return true;
168 }
169
SendTerminate()170 bool RemoteTargetExternal::SendTerminate() {
171 return SendHeader(LLI_Terminate);
172 // No data or data size is sent with Terminate
173 }
174
Receive(LLIMessageType Msg)175 bool RemoteTargetExternal::Receive(LLIMessageType Msg) {
176 if (!ReceiveHeader(Msg))
177 return false;
178 int Unused;
179 AppendRead(&Unused, 0);
180 if (!ReceivePayload())
181 return false;
182 ReceiveData.clear();
183 Sizes.clear();
184 return true;
185 }
186
Receive(LLIMessageType Msg,int32_t & Data)187 bool RemoteTargetExternal::Receive(LLIMessageType Msg, int32_t &Data) {
188 if (!ReceiveHeader(Msg))
189 return false;
190 AppendRead(&Data, 4);
191 if (!ReceivePayload())
192 return false;
193 ReceiveData.clear();
194 Sizes.clear();
195 return true;
196 }
197
Receive(LLIMessageType Msg,uint64_t & Data)198 bool RemoteTargetExternal::Receive(LLIMessageType Msg, uint64_t &Data) {
199 if (!ReceiveHeader(Msg))
200 return false;
201 AppendRead(&Data, 8);
202 if (!ReceivePayload())
203 return false;
204 ReceiveData.clear();
205 Sizes.clear();
206 return true;
207 }
208
ReceiveHeader(LLIMessageType ExpectedMsgType)209 bool RemoteTargetExternal::ReceiveHeader(LLIMessageType ExpectedMsgType) {
210 assert(ReceiveData.empty() && Sizes.empty() &&
211 "Payload vector not empty to receive header");
212
213 // Message header, with type to follow
214 uint32_t MsgType;
215 if (!ReadBytes(&MsgType, 4)) {
216 ErrorMsg += ", (RemoteTargetExternal::ReceiveHeader)";
217 return false;
218 }
219 if (MsgType != (uint32_t)ExpectedMsgType) {
220 ErrorMsg = "received unexpected message type";
221 ErrorMsg += ". Expecting: ";
222 ErrorMsg += ExpectedMsgType;
223 ErrorMsg += ", Got: ";
224 ErrorMsg += MsgType;
225 return false;
226 }
227 return true;
228 }
229
ReceivePayload()230 bool RemoteTargetExternal::ReceivePayload() {
231 assert(!ReceiveData.empty() &&
232 "Payload vector empty to receive");
233 assert(ReceiveData.size() == Sizes.size() &&
234 "Unexpected mismatch between data and size");
235
236 uint32_t TotalSize = 0;
237 for (int I=0, E=Sizes.size(); I < E; I++)
238 TotalSize += Sizes[I];
239
240 // Payload size header
241 uint32_t DataSize;
242 if (!ReadBytes(&DataSize, 4)) {
243 ErrorMsg += ", invalid data size";
244 return false;
245 }
246 if (DataSize != TotalSize) {
247 ErrorMsg = "unexpected data size";
248 ErrorMsg += ". Expecting: ";
249 ErrorMsg += TotalSize;
250 ErrorMsg += ", Got: ";
251 ErrorMsg += DataSize;
252 return false;
253 }
254 if (DataSize == 0)
255 return true;
256
257 // Payload itself
258 for (int I=0, E=Sizes.size(); I < E; I++) {
259 if (!ReadBytes(ReceiveData[I], Sizes[I])) {
260 ErrorMsg = "unexpected data while reading message";
261 return false;
262 }
263 }
264
265 return true;
266 }
267
SendHeader(LLIMessageType MsgType)268 bool RemoteTargetExternal::SendHeader(LLIMessageType MsgType) {
269 assert(SendData.empty() && Sizes.empty() &&
270 "Payload vector not empty to send header");
271
272 // Message header, with type to follow
273 if (!WriteBytes(&MsgType, 4)) {
274 ErrorMsg += ", (RemoteTargetExternal::SendHeader)";
275 return false;
276 }
277 return true;
278 }
279
SendPayload()280 bool RemoteTargetExternal::SendPayload() {
281 assert(!SendData.empty() && !Sizes.empty() &&
282 "Payload vector empty to send");
283 assert(SendData.size() == Sizes.size() &&
284 "Unexpected mismatch between data and size");
285
286 uint32_t TotalSize = 0;
287 for (int I=0, E=Sizes.size(); I < E; I++)
288 TotalSize += Sizes[I];
289
290 // Payload size header
291 if (!WriteBytes(&TotalSize, 4)) {
292 ErrorMsg += ", invalid data size";
293 return false;
294 }
295 if (TotalSize == 0)
296 return true;
297
298 // Payload itself
299 for (int I=0, E=Sizes.size(); I < E; I++) {
300 if (!WriteBytes(SendData[I], Sizes[I])) {
301 ErrorMsg = "unexpected data while writing message";
302 return false;
303 }
304 }
305
306 SendData.clear();
307 Sizes.clear();
308 return true;
309 }
310
AppendWrite(const void * Data,uint32_t Size)311 void RemoteTargetExternal::AppendWrite(const void *Data, uint32_t Size) {
312 SendData.push_back(Data);
313 Sizes.push_back(Size);
314 }
315
AppendRead(void * Data,uint32_t Size)316 void RemoteTargetExternal::AppendRead(void *Data, uint32_t Size) {
317 ReceiveData.push_back(Data);
318 Sizes.push_back(Size);
319 }
320
321 #ifdef LLVM_ON_UNIX
322 #include "Unix/RPCChannel.inc"
323 #endif
324
325 #ifdef LLVM_ON_WIN32
326 #include "Windows/RPCChannel.inc"
327 #endif
328