Home | History | Annotate | Download | only in lli
      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