blob: 55fcae9def8fab51a54490a00f0e2e70a6951a2e [file] [log] [blame]
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +00001#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
10using namespace llvm;
11
12class LLIChildTarget {
13public:
Benjamin Kramerc83946f2013-10-05 11:53:20 +000014 ~LLIChildTarget(); // OS-specific destructor
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +000015 void initialize();
16 LLIMessageType waitForIncomingMessage();
17 void handleMessage(LLIMessageType messageType);
18
19private:
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
49int 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
62void LLIChildTarget::initialize() {
63 initializeConnection();
64 sendChildActive();
65}
66
67LLIMessageType LLIChildTarget::waitForIncomingMessage() {
68 int32_t MsgType = -1;
69 if (ReadBytes(&MsgType, 4) > 0)
70 return (LLIMessageType)MsgType;
71 return LLI_Error;
72}
73
74void 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
98void 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
120void 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
147void 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
168void 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
179void 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
191void 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
207void 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
219void 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