ChildTarget.cpp revision 276479
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
12using namespace llvm;
13
14class LLIChildTarget {
15public:
16  void initialize();
17  LLIMessageType waitForIncomingMessage();
18  void handleMessage(LLIMessageType messageType);
19  RemoteTarget *RT;
20  RPCChannel RPC;
21
22private:
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
47int 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
62void LLIChildTarget::initialize() {
63  RPC.createClient();
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      RT->stop();
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  (void)rc;
103  assert(rc == 4);
104  assert(DataSize == 8);
105
106  // Read the message arguments.
107  uint32_t Alignment;
108  uint32_t AllocSize;
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
122void LLIChildTarget::handleLoadSection(bool IsCode) {
123  // Read the message data size.
124  uint32_t DataSize;
125  int rc = ReadBytes(&DataSize, 4);
126  (void)rc;
127  assert(rc == 4);
128
129  // Read the target load address.
130  uint64_t Addr;
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
151void LLIChildTarget::handleExecute() {
152  // Read the message data size.
153  uint32_t DataSize;
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;
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
173void 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
186void 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
203void 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
220void 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