]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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. | |
85aaf69f | 100 | uint32_t DataSize = 0; |
1a4d82fc JJ |
101 | int rc = ReadBytes(&DataSize, 4); |
102 | (void)rc; | |
103 | assert(rc == 4); | |
104 | assert(DataSize == 8); | |
105 | ||
106 | // Read the message arguments. | |
85aaf69f SL |
107 | uint32_t Alignment = 0; |
108 | uint32_t AllocSize = 0; | |
1a4d82fc JJ |
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. | |
85aaf69f | 124 | uint32_t DataSize = 0; |
1a4d82fc JJ |
125 | int rc = ReadBytes(&DataSize, 4); |
126 | (void)rc; | |
127 | assert(rc == 4); | |
128 | ||
129 | // Read the target load address. | |
85aaf69f | 130 | uint64_t Addr = 0; |
1a4d82fc JJ |
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. | |
85aaf69f | 153 | uint32_t DataSize = 0; |
1a4d82fc JJ |
154 | int rc = ReadBytes(&DataSize, 4); |
155 | (void)rc; | |
156 | assert(rc == 4); | |
157 | assert(DataSize == 8); | |
158 | ||
159 | // Read the target address. | |
85aaf69f | 160 | uint64_t Addr = 0; |
1a4d82fc JJ |
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 |