Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 1 | #include "llvm/Config/config.h" |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 2 | #include "llvm/Support/Memory.h" |
Alp Toker | 632c6cd | 2014-01-23 22:19:45 +0000 | [diff] [blame] | 3 | #include "../RPCChannel.h" |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 4 | #include "../RemoteTarget.h" |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 5 | #include "../RemoteTargetMessage.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: |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 16 | void initialize(); |
| 17 | LLIMessageType waitForIncomingMessage(); |
| 18 | void handleMessage(LLIMessageType messageType); |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 19 | RemoteTarget *RT; |
Alp Toker | 632c6cd | 2014-01-23 22:19:45 +0000 | [diff] [blame] | 20 | RPCChannel RPC; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 21 | |
| 22 | private: |
| 23 | // Incoming message handlers |
| 24 | void handleAllocateSpace(); |
| 25 | void handleLoadSection(bool IsCode); |
| 26 | void handleExecute(); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 27 | |
| 28 | // Outgoing message handlers |
| 29 | void sendChildActive(); |
| 30 | void sendAllocationResult(uint64_t Addr); |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 31 | void sendLoadStatus(uint32_t Status); |
| 32 | void sendExecutionComplete(int Result); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 33 | |
| 34 | // OS-specific functions |
| 35 | void initializeConnection(); |
Alp Toker | 632c6cd | 2014-01-23 22:19:45 +0000 | [diff] [blame] | 36 | int WriteBytes(const void *Data, size_t Size) { |
Alp Toker | ad6aa47 | 2014-01-24 17:18:52 +0000 | [diff] [blame^] | 37 | return RPC.WriteBytes(Data, Size) ? Size : -1; |
Alp Toker | 632c6cd | 2014-01-23 22:19:45 +0000 | [diff] [blame] | 38 | } |
Alp Toker | ad6aa47 | 2014-01-24 17:18:52 +0000 | [diff] [blame^] | 39 | int ReadBytes(void *Data, size_t Size) { |
| 40 | return RPC.ReadBytes(Data, Size) ? Size : -1; |
| 41 | } |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 42 | |
| 43 | // Communication handles (OS-specific) |
| 44 | void *ConnectionData; |
| 45 | }; |
| 46 | |
| 47 | int main() { |
| 48 | LLIChildTarget ThisChild; |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 49 | ThisChild.RT = new RemoteTarget(); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 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); |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 57 | delete ThisChild.RT; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 58 | return 0; |
| 59 | } |
| 60 | |
| 61 | // Public methods |
| 62 | void LLIChildTarget::initialize() { |
Alp Toker | 632c6cd | 2014-01-23 22:19:45 +0000 | [diff] [blame] | 63 | RPC.createClient(); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 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: |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 89 | RT->stop(); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 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; |
| 101 | int rc = ReadBytes(&DataSize, 4); |
Matt Arsenault | c44a3ff | 2013-12-05 19:37:36 +0000 | [diff] [blame] | 102 | (void)rc; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 103 | assert(rc == 4); |
| 104 | assert(DataSize == 8); |
| 105 | |
| 106 | // Read the message arguments. |
| 107 | uint32_t Alignment; |
| 108 | uint32_t AllocSize; |
| 109 | rc = ReadBytes(&Alignment, 4); |
| 110 | assert(rc == 4); |
| 111 | rc = ReadBytes(&AllocSize, 4); |
| 112 | assert(rc == 4); |
| 113 | |
| 114 | // Allocate the memory. |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 115 | uint64_t Addr; |
| 116 | RT->allocateSpace(AllocSize, Alignment, Addr); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 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; |
| 125 | int rc = ReadBytes(&DataSize, 4); |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 126 | (void)rc; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 127 | assert(rc == 4); |
| 128 | |
| 129 | // Read the target load address. |
| 130 | uint64_t Addr; |
| 131 | rc = ReadBytes(&Addr, 8); |
| 132 | assert(rc == 8); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 133 | size_t BufferSize = DataSize - 8; |
| 134 | |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 135 | if (!RT->isAllocatedMemory(Addr, BufferSize)) |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 136 | return sendLoadStatus(LLI_Status_NotAllocated); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 137 | |
| 138 | // Read section data into previously allocated buffer |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 139 | rc = ReadBytes((void*)Addr, BufferSize); |
| 140 | if (rc != (int)(BufferSize)) |
| 141 | return sendLoadStatus(LLI_Status_IncompleteMsg); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 142 | |
| 143 | // If IsCode, mark memory executable |
| 144 | if (IsCode) |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 145 | sys::Memory::InvalidateInstructionCache((void *)Addr, BufferSize); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 146 | |
| 147 | // Send MarkLoadComplete message. |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 148 | sendLoadStatus(LLI_Status_Success); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | void LLIChildTarget::handleExecute() { |
| 152 | // Read the message data size. |
| 153 | uint32_t DataSize; |
| 154 | int rc = ReadBytes(&DataSize, 4); |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 155 | (void)rc; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 156 | assert(rc == 4); |
| 157 | assert(DataSize == 8); |
| 158 | |
| 159 | // Read the target address. |
| 160 | uint64_t Addr; |
| 161 | rc = ReadBytes(&Addr, 8); |
| 162 | assert(rc == 8); |
| 163 | |
| 164 | // Call function |
Alp Toker | e2641f1 | 2014-01-23 11:04:42 +0000 | [diff] [blame] | 165 | int32_t Result = -1; |
| 166 | RT->executeCode(Addr, Result); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 167 | |
| 168 | // Send ExecutionResult message. |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 169 | sendExecutionComplete(Result); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 170 | } |
| 171 | |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 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); |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 177 | (void)rc; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 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); |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 190 | (void)rc; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 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 | |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 203 | void LLIChildTarget::sendLoadStatus(uint32_t Status) { |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 204 | // Write the message type. |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 205 | uint32_t MsgType = (uint32_t)LLI_LoadResult; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 206 | int rc = WriteBytes(&MsgType, 4); |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 207 | (void)rc; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 208 | assert(rc == 4); |
| 209 | |
| 210 | // Write the data size. |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 211 | uint32_t DataSize = 4; |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 212 | rc = WriteBytes(&DataSize, 4); |
| 213 | assert(rc == 4); |
| 214 | |
| 215 | // Write the result. |
Renato Golin | 695895c | 2014-01-14 22:43:43 +0000 | [diff] [blame] | 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); |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | #ifdef LLVM_ON_UNIX |
Alp Toker | 632c6cd | 2014-01-23 22:19:45 +0000 | [diff] [blame] | 239 | #include "../Unix/RPCChannel.inc" |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 240 | #endif |
| 241 | |
| 242 | #ifdef LLVM_ON_WIN32 |
Alp Toker | 632c6cd | 2014-01-23 22:19:45 +0000 | [diff] [blame] | 243 | #include "../Windows/RPCChannel.inc" |
Andrew Kaylor | c2ebf3f | 2013-10-02 17:12:36 +0000 | [diff] [blame] | 244 | #endif |