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 
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
62 void LLIChildTarget::initialize() {
63   initializeConnection();
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       handleTerminate();
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.
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 = allocate(Alignment, AllocSize);
116 
117   // Send AllocationResult message.
118   sendAllocationResult(Addr);
119 }
120 
121 void LLIChildTarget::handleLoadSection(bool IsCode) {
122   // Read the message data size.
123   uint32_t DataSize;
124   int rc = ReadBytes(&DataSize, 4);
125   assert(rc == 4);
126 
127   // Read the target load address.
128   uint64_t Addr;
129   rc = ReadBytes(&Addr, 8);
130   assert(rc == 8);
131 
132   size_t BufferSize = DataSize - 8;
133 
134   // FIXME: Verify that this is in allocated space
135 
136   // Read section data into previously allocated buffer
137   rc = ReadBytes((void*)Addr, DataSize - 8);
138   assert(rc == (int)(BufferSize));
139 
140   // If IsCode, mark memory executable
141   if (IsCode)
142     makeSectionExecutable(Addr, BufferSize);
143 
144   // Send MarkLoadComplete message.
145   sendLoadComplete();
146 }
147 
148 void LLIChildTarget::handleExecute() {
149   // Read the message data size.
150   uint32_t DataSize;
151   int rc = ReadBytes(&DataSize, 4);
152   assert(rc == 4);
153   assert(DataSize == 8);
154 
155   // Read the target address.
156   uint64_t Addr;
157   rc = ReadBytes(&Addr, 8);
158   assert(rc == 8);
159 
160   // Call function
161   int Result;
162   int (*fn)(void) = (int(*)(void))Addr;
163   Result = fn();
164 
165   // Send ExecutionResult message.
166   sendExecutionComplete((int64_t)Result);
167 }
168 
169 void LLIChildTarget::handleTerminate() {
170   // Release all allocated memory
171   AllocMapType::iterator Begin = m_AllocatedBufferMap.begin();
172   AllocMapType::iterator End = m_AllocatedBufferMap.end();
173   for (AllocMapType::iterator It = Begin; It != End; ++It) {
174     releaseMemory(It->first, It->second);
175   }
176   m_AllocatedBufferMap.clear();
177 }
178 
179 // Outgoing message handlers
180 void LLIChildTarget::sendChildActive() {
181   // Write the message type.
182   uint32_t MsgType = (uint32_t)LLI_ChildActive;
183   int rc = WriteBytes(&MsgType, 4);
184   assert(rc == 4);
185 
186   // Write the data size.
187   uint32_t DataSize = 0;
188   rc = WriteBytes(&DataSize, 4);
189   assert(rc == 4);
190 }
191 
192 void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
193   // Write the message type.
194   uint32_t MsgType = (uint32_t)LLI_AllocationResult;
195   int rc = WriteBytes(&MsgType, 4);
196   assert(rc == 4);
197 
198   // Write the data size.
199   uint32_t DataSize = 8;
200   rc = WriteBytes(&DataSize, 4);
201   assert(rc == 4);
202 
203   // Write the allocated address.
204   rc = WriteBytes(&Addr, 8);
205   assert(rc == 8);
206 }
207 
208 void LLIChildTarget::sendLoadComplete() {
209   // Write the message type.
210   uint32_t MsgType = (uint32_t)LLI_LoadComplete;
211   int rc = WriteBytes(&MsgType, 4);
212   assert(rc == 4);
213 
214   // Write the data size.
215   uint32_t DataSize = 0;
216   rc = WriteBytes(&DataSize, 4);
217   assert(rc == 4);
218 }
219 
220 void LLIChildTarget::sendExecutionComplete(uint64_t Result) {
221   // Write the message type.
222   uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
223   int rc = WriteBytes(&MsgType, 4);
224   assert(rc == 4);
225 
226 
227   // Write the data size.
228   uint32_t DataSize = 8;
229   rc = WriteBytes(&DataSize, 4);
230   assert(rc == 4);
231 
232   // Write the result.
233   rc = WriteBytes(&Result, 8);
234   assert(rc == 8);
235 }
236 
237 #ifdef LLVM_ON_UNIX
238 #include "Unix/ChildTarget.inc"
239 #endif
240 
241 #ifdef LLVM_ON_WIN32
242 #include "Windows/ChildTarget.inc"
243 #endif
244