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();
WriteBytes(const void * Data,size_t Size)36 int WriteBytes(const void *Data, size_t Size) {
37 return RPC.WriteBytes(Data, Size) ? Size : -1;
38 }
ReadBytes(void * Data,size_t Size)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
main()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
initialize()62 void LLIChildTarget::initialize() {
63 RPC.createClient();
64 sendChildActive();
65 }
66
waitForIncomingMessage()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
handleMessage(LLIMessageType messageType)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
handleAllocateSpace()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
handleLoadSection(bool IsCode)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
handleExecute()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
sendChildActive()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
sendAllocationResult(uint64_t Addr)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
sendLoadStatus(uint32_t Status)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
sendExecutionComplete(int Result)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