Home | History | Annotate | Download | only in ChildTarget
      1 #include "llvm/Config/config.h"
      2 #include "../RPCChannel.h"
      3 #include "../RemoteTarget.h"
      4 #include "../RemoteTargetMessage.h"
      5 #include "llvm/Support/Memory.h"
      6 #include <assert.h>
      7 #include <map>
      8 #include <stdint.h>
      9 #include <string>
     10 #include <vector>
     11 
     12 using namespace llvm;
     13 
     14 class LLIChildTarget {
     15 public:
     16   void initialize();
     17   LLIMessageType waitForIncomingMessage();
     18   void handleMessage(LLIMessageType messageType);
     19   RemoteTarget *RT;
     20   RPCChannel RPC;
     21 
     22 private:
     23   // Incoming message handlers
     24   void handleAllocateSpace();
     25   void handleLoadSection(bool IsCode);
     26   void handleExecute();
     27 
     28   // Outgoing message handlers
     29   void sendChildActive();
     30   void sendAllocationResult(uint64_t Addr);
     31   void sendLoadStatus(uint32_t Status);
     32   void sendExecutionComplete(int Result);
     33 
     34   // OS-specific functions
     35   void initializeConnection();
     36   int WriteBytes(const void *Data, size_t Size) {
     37     return RPC.WriteBytes(Data, Size) ? Size : -1;
     38   }
     39   int ReadBytes(void *Data, size_t Size) {
     40     return RPC.ReadBytes(Data, Size) ? Size : -1;
     41   }
     42 
     43   // Communication handles (OS-specific)
     44   void *ConnectionData;
     45 };
     46 
     47 int main() {
     48   LLIChildTarget  ThisChild;
     49   ThisChild.RT = new RemoteTarget();
     50   ThisChild.initialize();
     51   LLIMessageType MsgType;
     52   do {
     53     MsgType = ThisChild.waitForIncomingMessage();
     54     ThisChild.handleMessage(MsgType);
     55   } while (MsgType != LLI_Terminate &&
     56            MsgType != LLI_Error);
     57   delete ThisChild.RT;
     58   return 0;
     59 }
     60 
     61 // Public methods
     62 void LLIChildTarget::initialize() {
     63   RPC.createClient();
     64   sendChildActive();
     65 }
     66 
     67 LLIMessageType LLIChildTarget::waitForIncomingMessage() {
     68   int32_t MsgType = -1;
     69   if (ReadBytes(&MsgType, 4) > 0)
     70     return (LLIMessageType)MsgType;
     71   return LLI_Error;
     72 }
     73 
     74 void LLIChildTarget::handleMessage(LLIMessageType messageType) {
     75   switch (messageType) {
     76     case LLI_AllocateSpace:
     77       handleAllocateSpace();
     78       break;
     79     case LLI_LoadCodeSection:
     80       handleLoadSection(true);
     81       break;
     82     case LLI_LoadDataSection:
     83       handleLoadSection(false);
     84       break;
     85     case LLI_Execute:
     86       handleExecute();
     87       break;
     88     case LLI_Terminate:
     89       RT->stop();
     90       break;
     91     default:
     92       // FIXME: Handle error!
     93       break;
     94   }
     95 }
     96 
     97 // Incoming message handlers
     98 void LLIChildTarget::handleAllocateSpace() {
     99   // Read and verify the message data size.
    100   uint32_t DataSize = 0;
    101   int rc = ReadBytes(&DataSize, 4);
    102   (void)rc;
    103   assert(rc == 4);
    104   assert(DataSize == 8);
    105 
    106   // Read the message arguments.
    107   uint32_t Alignment = 0;
    108   uint32_t AllocSize = 0;
    109   rc = ReadBytes(&Alignment, 4);
    110   assert(rc == 4);
    111   rc = ReadBytes(&AllocSize, 4);
    112   assert(rc == 4);
    113 
    114   // Allocate the memory.
    115   uint64_t Addr;
    116   RT->allocateSpace(AllocSize, Alignment, Addr);
    117 
    118   // Send AllocationResult message.
    119   sendAllocationResult(Addr);
    120 }
    121 
    122 void LLIChildTarget::handleLoadSection(bool IsCode) {
    123   // Read the message data size.
    124   uint32_t DataSize = 0;
    125   int rc = ReadBytes(&DataSize, 4);
    126   (void)rc;
    127   assert(rc == 4);
    128 
    129   // Read the target load address.
    130   uint64_t Addr = 0;
    131   rc = ReadBytes(&Addr, 8);
    132   assert(rc == 8);
    133   size_t BufferSize = DataSize - 8;
    134 
    135   if (!RT->isAllocatedMemory(Addr, BufferSize))
    136     return sendLoadStatus(LLI_Status_NotAllocated);
    137 
    138   // Read section data into previously allocated buffer
    139   rc = ReadBytes((void*)Addr, BufferSize);
    140   if (rc != (int)(BufferSize))
    141     return sendLoadStatus(LLI_Status_IncompleteMsg);
    142 
    143   // If IsCode, mark memory executable
    144   if (IsCode)
    145     sys::Memory::InvalidateInstructionCache((void *)Addr, BufferSize);
    146 
    147   // Send MarkLoadComplete message.
    148   sendLoadStatus(LLI_Status_Success);
    149 }
    150 
    151 void LLIChildTarget::handleExecute() {
    152   // Read the message data size.
    153   uint32_t DataSize = 0;
    154   int rc = ReadBytes(&DataSize, 4);
    155   (void)rc;
    156   assert(rc == 4);
    157   assert(DataSize == 8);
    158 
    159   // Read the target address.
    160   uint64_t Addr = 0;
    161   rc = ReadBytes(&Addr, 8);
    162   assert(rc == 8);
    163 
    164   // Call function
    165   int32_t Result = -1;
    166   RT->executeCode(Addr, Result);
    167 
    168   // Send ExecutionResult message.
    169   sendExecutionComplete(Result);
    170 }
    171 
    172 // Outgoing message handlers
    173 void LLIChildTarget::sendChildActive() {
    174   // Write the message type.
    175   uint32_t MsgType = (uint32_t)LLI_ChildActive;
    176   int rc = WriteBytes(&MsgType, 4);
    177   (void)rc;
    178   assert(rc == 4);
    179 
    180   // Write the data size.
    181   uint32_t DataSize = 0;
    182   rc = WriteBytes(&DataSize, 4);
    183   assert(rc == 4);
    184 }
    185 
    186 void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
    187   // Write the message type.
    188   uint32_t MsgType = (uint32_t)LLI_AllocationResult;
    189   int rc = WriteBytes(&MsgType, 4);
    190   (void)rc;
    191   assert(rc == 4);
    192 
    193   // Write the data size.
    194   uint32_t DataSize = 8;
    195   rc = WriteBytes(&DataSize, 4);
    196   assert(rc == 4);
    197 
    198   // Write the allocated address.
    199   rc = WriteBytes(&Addr, 8);
    200   assert(rc == 8);
    201 }
    202 
    203 void LLIChildTarget::sendLoadStatus(uint32_t Status) {
    204   // Write the message type.
    205   uint32_t MsgType = (uint32_t)LLI_LoadResult;
    206   int rc = WriteBytes(&MsgType, 4);
    207   (void)rc;
    208   assert(rc == 4);
    209 
    210   // Write the data size.
    211   uint32_t DataSize = 4;
    212   rc = WriteBytes(&DataSize, 4);
    213   assert(rc == 4);
    214 
    215   // Write the result.
    216   rc = WriteBytes(&Status, 4);
    217   assert(rc == 4);
    218 }
    219 
    220 void LLIChildTarget::sendExecutionComplete(int Result) {
    221   // Write the message type.
    222   uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
    223   int rc = WriteBytes(&MsgType, 4);
    224   (void)rc;
    225   assert(rc == 4);
    226 
    227 
    228   // Write the data size.
    229   uint32_t DataSize = 4;
    230   rc = WriteBytes(&DataSize, 4);
    231   assert(rc == 4);
    232 
    233   // Write the result.
    234   rc = WriteBytes(&Result, 4);
    235   assert(rc == 4);
    236 }
    237 
    238 #ifdef LLVM_ON_UNIX
    239 #include "../Unix/RPCChannel.inc"
    240 #endif
    241 
    242 #ifdef LLVM_ON_WIN32
    243 #include "../Windows/RPCChannel.inc"
    244 #endif
    245