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