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 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 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 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 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 114 void RemoteTargetExternal::stop() { 115 SendTerminate(); 116 RPC.Wait(); 117 } 118 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 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 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 170 bool RemoteTargetExternal::SendTerminate() { 171 return SendHeader(LLI_Terminate); 172 // No data or data size is sent with Terminate 173 } 174 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 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 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 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 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 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 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 311 void RemoteTargetExternal::AppendWrite(const void *Data, uint32_t Size) { 312 SendData.push_back(Data); 313 Sizes.push_back(Size); 314 } 315 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