]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / lli / ChildTarget / ChildTarget.cpp
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   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
120 void 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
147 void 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
168 void 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
179 void 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
191 void 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
207 void 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
219 void 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