1 #include "llvm/Config/config.h"
2 #include "../RemoteTargetMessage.h"
3 #include <assert.h>
4 #include <map>
5 #include <stdint.h>
6 #include <string>
7 #include <vector>
8 
9 using namespace llvm;
10 
11 class LLIChildTarget {
12 public:
13   ~LLIChildTarget(); // OS-specific destructor
14   void initialize();
15   LLIMessageType waitForIncomingMessage();
16   void handleMessage(LLIMessageType messageType);
17 
18 private:
19   // Incoming message handlers
20   void handleAllocateSpace();
21   void handleLoadSection(bool IsCode);
22   void handleExecute();
23   void handleTerminate();
24 
25   // Outgoing message handlers
26   void sendChildActive();
27   void sendAllocationResult(uint64_t Addr);
28   void sendLoadStatus(uint32_t Status);
29   void sendExecutionComplete(int Result);
30 
31   // OS-specific functions
32   void initializeConnection();
33   int WriteBytes(const void *Data, size_t Size);
34   int ReadBytes(void *Data, size_t Size);
35   uint64_t allocate(uint32_t Alignment, uint32_t Size);
36   void makeSectionExecutable(uint64_t Addr, uint32_t Size);
37   void InvalidateInstructionCache(const void *Addr, size_t Len);
38   void releaseMemory(uint64_t Addr, uint32_t Size);
39   bool isAllocatedMemory(uint64_t Address, 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   (void)rc;
126   assert(rc == 4);
127 
128   // Read the target load address.
129   uint64_t Addr;
130   rc = ReadBytes(&Addr, 8);
131   assert(rc == 8);
132   size_t BufferSize = DataSize - 8;
133 
134   if (!isAllocatedMemory(Addr, BufferSize))
135     return sendLoadStatus(LLI_Status_NotAllocated);
136 
137   // Read section data into previously allocated buffer
138   rc = ReadBytes((void*)Addr, BufferSize);
139   if (rc != (int)(BufferSize))
140     return sendLoadStatus(LLI_Status_IncompleteMsg);
141 
142   // If IsCode, mark memory executable
143   if (IsCode)
144     makeSectionExecutable(Addr, BufferSize);
145 
146   // Send MarkLoadComplete message.
147   sendLoadStatus(LLI_Status_Success);
148 }
149 
150 void LLIChildTarget::handleExecute() {
151   // Read the message data size.
152   uint32_t DataSize;
153   int rc = ReadBytes(&DataSize, 4);
154   (void)rc;
155   assert(rc == 4);
156   assert(DataSize == 8);
157 
158   // Read the target address.
159   uint64_t Addr;
160   rc = ReadBytes(&Addr, 8);
161   assert(rc == 8);
162 
163   // Call function
164   int Result;
165   int (*fn)(void) = (int(*)(void))Addr;
166   Result = fn();
167 
168   // Send ExecutionResult message.
169   sendExecutionComplete(Result);
170 }
171 
172 void LLIChildTarget::handleTerminate() {
173   // Release all allocated memory
174   AllocMapType::iterator Begin = m_AllocatedBufferMap.begin();
175   AllocMapType::iterator End = m_AllocatedBufferMap.end();
176   for (AllocMapType::iterator It = Begin; It != End; ++It) {
177     releaseMemory(It->first, It->second);
178   }
179   m_AllocatedBufferMap.clear();
180 }
181 
182 bool LLIChildTarget::isAllocatedMemory(uint64_t Address, uint32_t Size) {
183   uint64_t End = Address+Size;
184   AllocMapType::iterator ItBegin = m_AllocatedBufferMap.begin();
185   AllocMapType::iterator ItEnd = m_AllocatedBufferMap.end();
186   for (AllocMapType::iterator It = ItBegin; It != ItEnd; ++It) {
187     uint64_t A = It->first;
188     uint64_t E = A + It->second;
189     // Starts and finishes inside allocated region
190     if (Address >= A && End <= E)
191       return true;
192   }
193   return false;
194 }
195 
196 // Outgoing message handlers
197 void LLIChildTarget::sendChildActive() {
198   // Write the message type.
199   uint32_t MsgType = (uint32_t)LLI_ChildActive;
200   int rc = WriteBytes(&MsgType, 4);
201   (void)rc;
202   assert(rc == 4);
203 
204   // Write the data size.
205   uint32_t DataSize = 0;
206   rc = WriteBytes(&DataSize, 4);
207   assert(rc == 4);
208 }
209 
210 void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
211   // Write the message type.
212   uint32_t MsgType = (uint32_t)LLI_AllocationResult;
213   int rc = WriteBytes(&MsgType, 4);
214   (void)rc;
215   assert(rc == 4);
216 
217   // Write the data size.
218   uint32_t DataSize = 8;
219   rc = WriteBytes(&DataSize, 4);
220   assert(rc == 4);
221 
222   // Write the allocated address.
223   rc = WriteBytes(&Addr, 8);
224   assert(rc == 8);
225 }
226 
227 void LLIChildTarget::sendLoadStatus(uint32_t Status) {
228   // Write the message type.
229   uint32_t MsgType = (uint32_t)LLI_LoadResult;
230   int rc = WriteBytes(&MsgType, 4);
231   (void)rc;
232   assert(rc == 4);
233 
234   // Write the data size.
235   uint32_t DataSize = 4;
236   rc = WriteBytes(&DataSize, 4);
237   assert(rc == 4);
238 
239   // Write the result.
240   rc = WriteBytes(&Status, 4);
241   assert(rc == 4);
242 }
243 
244 void LLIChildTarget::sendExecutionComplete(int Result) {
245   // Write the message type.
246   uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
247   int rc = WriteBytes(&MsgType, 4);
248   (void)rc;
249   assert(rc == 4);
250 
251 
252   // Write the data size.
253   uint32_t DataSize = 4;
254   rc = WriteBytes(&DataSize, 4);
255   assert(rc == 4);
256 
257   // Write the result.
258   rc = WriteBytes(&Result, 4);
259   assert(rc == 4);
260 }
261 
262 #ifdef LLVM_ON_UNIX
263 #include "Unix/ChildTarget.inc"
264 #endif
265 
266 #ifdef LLVM_ON_WIN32
267 #include "Windows/ChildTarget.inc"
268 #endif
269