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