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