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
10using namespace llvm;
11
12class LLIChildTarget {
13public:
14  ~LLIChildTarget(); // OS-specific destructor
15  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
243