1 #include "llvm/Config/config.h"
2
3 #include "../RemoteTargetMessage.h"
4 #include <assert.h>
5 #include <map>
6 #include <stdint.h>
7 #include <string>
8 #include <vector>
9
10 using namespace llvm;
11
12 class LLIChildTarget {
13 public:
14 ~LLIChildTarget(); // OS-specific destructor
15 void initialize();
16 LLIMessageType waitForIncomingMessage();
17 void handleMessage(LLIMessageType messageType);
18
19 private:
20 // Incoming message handlers
21 void handleAllocateSpace();
22 void handleLoadSection(bool IsCode);
23 void handleExecute();
24 void handleTerminate();
25
26 // Outgoing message handlers
27 void sendChildActive();
28 void sendAllocationResult(uint64_t Addr);
29 void sendLoadComplete();
30 void sendExecutionComplete(uint64_t Result);
31
32 // OS-specific functions
33 void initializeConnection();
34 int WriteBytes(const void *Data, size_t Size);
35 int ReadBytes(void *Data, size_t Size);
36 uint64_t allocate(uint32_t Alignment, uint32_t Size);
37 void makeSectionExecutable(uint64_t Addr, uint32_t Size);
38 void InvalidateInstructionCache(const void *Addr, size_t Len);
39 void releaseMemory(uint64_t Addr, uint32_t Size);
40
41 // Store a map of allocated buffers to sizes.
42 typedef std::map<uint64_t, uint32_t> AllocMapType;
43 AllocMapType m_AllocatedBufferMap;
44
45 // Communication handles (OS-specific)
46 void *ConnectionData;
47 };
48
main()49 int main() {
50 LLIChildTarget ThisChild;
51 ThisChild.initialize();
52 LLIMessageType MsgType;
53 do {
54 MsgType = ThisChild.waitForIncomingMessage();
55 ThisChild.handleMessage(MsgType);
56 } while (MsgType != LLI_Terminate &&
57 MsgType != LLI_Error);
58 return 0;
59 }
60
61 // Public methods
initialize()62 void LLIChildTarget::initialize() {
63 initializeConnection();
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 handleTerminate();
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;
101 int rc = ReadBytes(&DataSize, 4);
102 assert(rc == 4);
103 assert(DataSize == 8);
104
105 // Read the message arguments.
106 uint32_t Alignment;
107 uint32_t AllocSize;
108 rc = ReadBytes(&Alignment, 4);
109 assert(rc == 4);
110 rc = ReadBytes(&AllocSize, 4);
111 assert(rc == 4);
112
113 // Allocate the memory.
114 uint64_t Addr = allocate(Alignment, AllocSize);
115
116 // Send AllocationResult message.
117 sendAllocationResult(Addr);
118 }
119
handleLoadSection(bool IsCode)120 void LLIChildTarget::handleLoadSection(bool IsCode) {
121 // Read the message data size.
122 uint32_t DataSize;
123 int rc = ReadBytes(&DataSize, 4);
124 assert(rc == 4);
125
126 // Read the target load address.
127 uint64_t Addr;
128 rc = ReadBytes(&Addr, 8);
129 assert(rc == 8);
130
131 size_t BufferSize = DataSize - 8;
132
133 // FIXME: Verify that this is in allocated space
134
135 // Read section data into previously allocated buffer
136 rc = ReadBytes((void*)Addr, DataSize - 8);
137 assert(rc == (int)(BufferSize));
138
139 // If IsCode, mark memory executable
140 if (IsCode)
141 makeSectionExecutable(Addr, BufferSize);
142
143 // Send MarkLoadComplete message.
144 sendLoadComplete();
145 }
146
handleExecute()147 void LLIChildTarget::handleExecute() {
148 // Read the message data size.
149 uint32_t DataSize;
150 int rc = ReadBytes(&DataSize, 4);
151 assert(rc == 4);
152 assert(DataSize == 8);
153
154 // Read the target address.
155 uint64_t Addr;
156 rc = ReadBytes(&Addr, 8);
157 assert(rc == 8);
158
159 // Call function
160 int Result;
161 int (*fn)(void) = (int(*)(void))Addr;
162 Result = fn();
163
164 // Send ExecutionResult message.
165 sendExecutionComplete((int64_t)Result);
166 }
167
handleTerminate()168 void LLIChildTarget::handleTerminate() {
169 // Release all allocated memory
170 AllocMapType::iterator Begin = m_AllocatedBufferMap.begin();
171 AllocMapType::iterator End = m_AllocatedBufferMap.end();
172 for (AllocMapType::iterator It = Begin; It != End; ++It) {
173 releaseMemory(It->first, It->second);
174 }
175 m_AllocatedBufferMap.clear();
176 }
177
178 // Outgoing message handlers
sendChildActive()179 void LLIChildTarget::sendChildActive() {
180 // Write the message type.
181 uint32_t MsgType = (uint32_t)LLI_ChildActive;
182 int rc = WriteBytes(&MsgType, 4);
183 assert(rc == 4);
184
185 // Write the data size.
186 uint32_t DataSize = 0;
187 rc = WriteBytes(&DataSize, 4);
188 assert(rc == 4);
189 }
190
sendAllocationResult(uint64_t Addr)191 void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
192 // Write the message type.
193 uint32_t MsgType = (uint32_t)LLI_AllocationResult;
194 int rc = WriteBytes(&MsgType, 4);
195 assert(rc == 4);
196
197 // Write the data size.
198 uint32_t DataSize = 8;
199 rc = WriteBytes(&DataSize, 4);
200 assert(rc == 4);
201
202 // Write the allocated address.
203 rc = WriteBytes(&Addr, 8);
204 assert(rc == 8);
205 }
206
sendLoadComplete()207 void LLIChildTarget::sendLoadComplete() {
208 // Write the message type.
209 uint32_t MsgType = (uint32_t)LLI_LoadComplete;
210 int rc = WriteBytes(&MsgType, 4);
211 assert(rc == 4);
212
213 // Write the data size.
214 uint32_t DataSize = 0;
215 rc = WriteBytes(&DataSize, 4);
216 assert(rc == 4);
217 }
218
sendExecutionComplete(uint64_t Result)219 void LLIChildTarget::sendExecutionComplete(uint64_t Result) {
220 // Write the message type.
221 uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
222 int rc = WriteBytes(&MsgType, 4);
223 assert(rc == 4);
224
225
226 // Write the data size.
227 uint32_t DataSize = 8;
228 rc = WriteBytes(&DataSize, 4);
229 assert(rc == 4);
230
231 // Write the result.
232 rc = WriteBytes(&Result, 8);
233 assert(rc == 8);
234 }
235
236 #ifdef LLVM_ON_UNIX
237 #include "Unix/ChildTarget.inc"
238 #endif
239
240 #ifdef LLVM_ON_WIN32
241 #include "Windows/ChildTarget.inc"
242 #endif
243