llvm.org GIT mirror llvm / 83ece7a
Sanitize MCJIT remote execution MCJIT remote execution (ChildTarget+RemoteTargetExternal) protocol was in dire need of refactoring. It was fail-prone, had no error reporting and implemented the same message logic on every single function. This patch rectifies it, and makes it work on ARM, where it was randomly failing. Other architectures shall profit from this change as well, making their buildbots and releases more reliable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199261 91177308-0d34-0410-b5e6-96231b3b80d8 Renato Golin 6 years ago
9 changed file(s) with 474 addition(s) and 189 deletion(s). Raw diff Collapse all Expand all
2424 // Outgoing message handlers
2525 void sendChildActive();
2626 void sendAllocationResult(uint64_t Addr);
27 void sendLoadComplete();
28 void sendExecutionComplete(uint64_t Result);
27 void sendLoadStatus(uint32_t Status);
28 void sendExecutionComplete(int Result);
2929
3030 // OS-specific functions
3131 void initializeConnection();
3535 void makeSectionExecutable(uint64_t Addr, uint32_t Size);
3636 void InvalidateInstructionCache(const void *Addr, size_t Len);
3737 void releaseMemory(uint64_t Addr, uint32_t Size);
38 bool isAllocatedMemory(uint64_t Address, uint32_t Size);
3839
3940 // Store a map of allocated buffers to sizes.
4041 typedef std::map AllocMapType;
120121 // Read the message data size.
121122 uint32_t DataSize;
122123 int rc = ReadBytes(&DataSize, 4);
124 (void)rc;
123125 assert(rc == 4);
124126
125127 // Read the target load address.
126128 uint64_t Addr;
127129 rc = ReadBytes(&Addr, 8);
128130 assert(rc == 8);
129
130131 size_t BufferSize = DataSize - 8;
131132
132 // FIXME: Verify that this is in allocated space
133 if (!isAllocatedMemory(Addr, BufferSize))
134 return sendLoadStatus(LLI_Status_NotAllocated);
133135
134136 // Read section data into previously allocated buffer
135 rc = ReadBytes((void*)Addr, DataSize - 8);
136 assert(rc == (int)(BufferSize));
137 rc = ReadBytes((void*)Addr, BufferSize);
138 if (rc != (int)(BufferSize))
139 return sendLoadStatus(LLI_Status_IncompleteMsg);
137140
138141 // If IsCode, mark memory executable
139142 if (IsCode)
140143 makeSectionExecutable(Addr, BufferSize);
141144
142145 // Send MarkLoadComplete message.
143 sendLoadComplete();
146 sendLoadStatus(LLI_Status_Success);
144147 }
145148
146149 void LLIChildTarget::handleExecute() {
147150 // Read the message data size.
148151 uint32_t DataSize;
149152 int rc = ReadBytes(&DataSize, 4);
153 (void)rc;
150154 assert(rc == 4);
151155 assert(DataSize == 8);
152156
161165 Result = fn();
162166
163167 // Send ExecutionResult message.
164 sendExecutionComplete((int64_t)Result);
168 sendExecutionComplete(Result);
165169 }
166170
167171 void LLIChildTarget::handleTerminate() {
174178 m_AllocatedBufferMap.clear();
175179 }
176180
181 bool LLIChildTarget::isAllocatedMemory(uint64_t Address, uint32_t Size) {
182 uint64_t End = Address+Size;
183 AllocMapType::iterator ItBegin = m_AllocatedBufferMap.begin();
184 AllocMapType::iterator ItEnd = m_AllocatedBufferMap.end();
185 for (AllocMapType::iterator It = ItBegin; It != ItEnd; ++It) {
186 uint64_t A = It->first;
187 uint64_t E = A + It->second;
188 // Starts and finishes inside allocated region
189 if (Address >= A && End <= E)
190 return true;
191 }
192 return false;
193 }
194
177195 // Outgoing message handlers
178196 void LLIChildTarget::sendChildActive() {
179197 // Write the message type.
180198 uint32_t MsgType = (uint32_t)LLI_ChildActive;
181199 int rc = WriteBytes(&MsgType, 4);
200 (void)rc;
182201 assert(rc == 4);
183202
184203 // Write the data size.
191210 // Write the message type.
192211 uint32_t MsgType = (uint32_t)LLI_AllocationResult;
193212 int rc = WriteBytes(&MsgType, 4);
213 (void)rc;
194214 assert(rc == 4);
195215
196216 // Write the data size.
203223 assert(rc == 8);
204224 }
205225
206 void LLIChildTarget::sendLoadComplete() {
207 // Write the message type.
208 uint32_t MsgType = (uint32_t)LLI_LoadComplete;
209 int rc = WriteBytes(&MsgType, 4);
210 assert(rc == 4);
211
212 // Write the data size.
213 uint32_t DataSize = 0;
214 rc = WriteBytes(&DataSize, 4);
215 assert(rc == 4);
216 }
217
218 void LLIChildTarget::sendExecutionComplete(uint64_t Result) {
226 void LLIChildTarget::sendLoadStatus(uint32_t Status) {
227 // Write the message type.
228 uint32_t MsgType = (uint32_t)LLI_LoadResult;
229 int rc = WriteBytes(&MsgType, 4);
230 (void)rc;
231 assert(rc == 4);
232
233 // Write the data size.
234 uint32_t DataSize = 4;
235 rc = WriteBytes(&DataSize, 4);
236 assert(rc == 4);
237
238 // Write the result.
239 rc = WriteBytes(&Status, 4);
240 assert(rc == 4);
241 }
242
243 void LLIChildTarget::sendExecutionComplete(int Result) {
219244 // Write the message type.
220245 uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
221246 int rc = WriteBytes(&MsgType, 4);
222 assert(rc == 4);
223
224
225 // Write the data size.
226 uint32_t DataSize = 8;
247 (void)rc;
248 assert(rc == 4);
249
250
251 // Write the data size.
252 uint32_t DataSize = 4;
227253 rc = WriteBytes(&DataSize, 4);
228254 assert(rc == 4);
229255
230256 // Write the result.
231 rc = WriteBytes(&Result, 8);
232 assert(rc == 8);
257 rc = WriteBytes(&Result, 4);
258 assert(rc == 4);
233259 }
234260
235261 #ifdef LLVM_ON_UNIX
128128
129129 // Allocate space in the remote target.
130130 uint64_t RemoteAddr;
131 if (Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
131 if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
132132 report_fatal_error(Target->getErrorMsg());
133133
134134 // Map the section addresses so relocations will get updated in the local
154154 uint64_t RemoteAddr = I->first;
155155 const Allocation &Section = I->second;
156156 if (Section.IsCode) {
157 Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size());
158
157 if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
158 report_fatal_error(Target->getErrorMsg());
159159 DEBUG(dbgs() << " loading code: " << Section.MB.base()
160160 << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
161161 } else {
162 Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size());
163
162 if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
163 report_fatal_error(Target->getErrorMsg());
164164 DEBUG(dbgs() << " loading data: " << Section.MB.base()
165165 << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
166166 }
5555 sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : NULL;
5656 sys::MemoryBlock Mem = sys::Memory::AllocateRWX(Size, Prev, &ErrorMsg);
5757 if (Mem.base() == NULL)
58 return true;
58 return false;
5959 if ((uintptr_t)Mem.base() % Alignment) {
6060 ErrorMsg = "unable to allocate sufficiently aligned memory";
61 return true;
61 return false;
6262 }
6363 Address = reinterpret_cast(Mem.base());
64 return false;
64 return true;
6565 }
6666
6767 bool RemoteTarget::loadData(uint64_t Address, const void *Data, size_t Size) {
6868 memcpy ((void*)Address, Data, Size);
69 return false;
69 return true;
7070 }
7171
7272 bool RemoteTarget::loadCode(uint64_t Address, const void *Data, size_t Size) {
7373 memcpy ((void*)Address, Data, Size);
7474 sys::MemoryBlock Mem((void*)Address, Size);
7575 sys::Memory::setExecutable(Mem, &ErrorMsg);
76 return false;
76 return true;
7777 }
7878
7979 bool RemoteTarget::executeCode(uint64_t Address, int &RetVal) {
8080 int (*fn)(void) = (int(*)(void))Address;
8181 RetVal = fn();
82 return false;
82 return true;
8383 }
8484
85 void RemoteTarget::create() {
85 bool RemoteTarget::create() {
86 return true;
8687 }
8788
8889 void RemoteTarget::stop() {
2424 namespace llvm {
2525
2626 class RemoteTarget {
27 std::string ErrorMsg;
2827 bool IsRunning;
2928
3029 SmallVector Allocations;
30
31 protected:
32 std::string ErrorMsg;
3133
3234 public:
3335 StringRef getErrorMsg() const { return ErrorMsg; }
3840 /// @param Alignment Required minimum alignment for allocated space.
3941 /// @param[out] Address Remote address of the allocated memory.
4042 ///
41 /// @returns False on success. On failure, ErrorMsg is updated with
43 /// @returns True on success. On failure, ErrorMsg is updated with
4244 /// descriptive text of the encountered error.
4345 virtual bool allocateSpace(size_t Size,
4446 unsigned Alignment,
5052 /// @param Data Source address in the host process.
5153 /// @param Size Number of bytes to copy.
5254 ///
53 /// @returns False on success. On failure, ErrorMsg is updated with
55 /// @returns True on success. On failure, ErrorMsg is updated with
5456 /// descriptive text of the encountered error.
5557 virtual bool loadData(uint64_t Address,
5658 const void *Data,
6264 /// @param Data Source address in the host process.
6365 /// @param Size Number of bytes to copy.
6466 ///
65 /// @returns False on success. On failure, ErrorMsg is updated with
67 /// @returns True on success. On failure, ErrorMsg is updated with
6668 /// descriptive text of the encountered error.
6769 virtual bool loadCode(uint64_t Address,
6870 const void *Data,
7577 /// process.
7678 /// @param[out] RetVal The integer return value of the called function.
7779 ///
78 /// @returns False on success. On failure, ErrorMsg is updated with
80 /// @returns True on success. On failure, ErrorMsg is updated with
7981 /// descriptive text of the encountered error.
8082 virtual bool executeCode(uint64_t Address,
8183 int &RetVal);
8890 virtual unsigned getPageAlignment() { return 4096; }
8991
9092 /// Start the remote process.
91 virtual void create();
93 virtual bool create();
9294
9395 /// Terminate the remote process.
9496 virtual void stop();
9597
96 RemoteTarget() : ErrorMsg(""), IsRunning(false) {}
98 RemoteTarget() : IsRunning(false), ErrorMsg("") {}
9799 virtual ~RemoteTarget() { if (IsRunning) stop(); }
98100
99101 // Create an instance of the system-specific remote target class.
1616 #include "RemoteTargetExternal.h"
1717 #include "llvm/ADT/StringRef.h"
1818 #include "llvm/Support/DataTypes.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/Format.h"
1921 #include "llvm/Support/Memory.h"
2022 #include "llvm/Support/Program.h"
2123 #include "llvm/Support/raw_ostream.h"
2527
2628 bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,
2729 uint64_t &Address) {
28 SendAllocateSpace(Alignment, Size);
29 Receive(LLI_AllocationResult, Address);
30 return false;
30 DEBUG(dbgs() << "Message [allocate space] size: " << Size <<
31 ", align: " << Alignment << "\n");
32 if (!SendAllocateSpace(Alignment, Size)) {
33 ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
34 return false;
35 }
36 if (!Receive(LLI_AllocationResult, Address)) {
37 ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
38 return false;
39 }
40 if (Address == 0) {
41 ErrorMsg += "failed allocation, (RemoteTargetExternal::allocateSpace)";
42 return false;
43 }
44 DEBUG(dbgs() << "Message [allocate space] addr: 0x" <<
45 format("%llx", Address) << "\n");
46 return true;
3147 }
3248
3349 bool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {
34 SendLoadSection(Address, Data, (uint32_t)Size, false);
35 Receive(LLI_LoadComplete);
36 return false;
50 DEBUG(dbgs() << "Message [load data] addr: 0x" << format("%llx", Address) <<
51 ", size: " << Size << "\n");
52 if (!SendLoadSection(Address, Data, (uint32_t)Size, false)) {
53 ErrorMsg += ", (RemoteTargetExternal::loadData)";
54 return false;
55 }
56 int Status = LLI_Status_Success;
57 if (!Receive(LLI_LoadResult, Status)) {
58 ErrorMsg += ", (RemoteTargetExternal::loadData)";
59 return false;
60 }
61 if (Status == LLI_Status_IncompleteMsg) {
62 ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
63 return false;
64 }
65 if (Status == LLI_Status_NotAllocated) {
66 ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
67 return false;
68 }
69 DEBUG(dbgs() << "Message [load data] complete\n");
70 return true;
3771 }
3872
3973 bool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {
40 SendLoadSection(Address, Data, (uint32_t)Size, true);
41 Receive(LLI_LoadComplete);
42 return false;
43 }
44
45 bool RemoteTargetExternal::executeCode(uint64_t Address, int &RetVal) {
46 SendExecute(Address);
47
48 Receive(LLI_ExecutionResult, RetVal);
49 return false;
74 DEBUG(dbgs() << "Message [load code] addr: 0x" << format("%llx", Address) <<
75 ", size: " << Size << "\n");
76 if (!SendLoadSection(Address, Data, (uint32_t)Size, true)) {
77 ErrorMsg += ", (RemoteTargetExternal::loadCode)";
78 return false;
79 }
80 int Status = LLI_Status_Success;
81 if (!Receive(LLI_LoadResult, Status)) {
82 ErrorMsg += ", (RemoteTargetExternal::loadCode)";
83 return false;
84 }
85 if (Status == LLI_Status_IncompleteMsg) {
86 ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
87 return false;
88 }
89 if (Status == LLI_Status_NotAllocated) {
90 ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
91 return false;
92 }
93 DEBUG(dbgs() << "Message [load code] complete\n");
94 return true;
95 }
96
97 bool RemoteTargetExternal::executeCode(uint64_t Address, int32_t &RetVal) {
98 DEBUG(dbgs() << "Message [exectue code] addr: " << Address << "\n");
99 if (!SendExecute(Address)) {
100 ErrorMsg += ", (RemoteTargetExternal::executeCode)";
101 return false;
102 }
103 if (!Receive(LLI_ExecutionResult, RetVal)) {
104 ErrorMsg += ", (RemoteTargetExternal::executeCode)";
105 return false;
106 }
107 DEBUG(dbgs() << "Message [exectue code] return: " << RetVal << "\n");
108 return true;
50109 }
51110
52111 void RemoteTargetExternal::stop() {
54113 Wait();
55114 }
56115
57 void RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
58 int rc;
59 (void)rc;
60 uint32_t MsgType = (uint32_t)LLI_AllocateSpace;
61 rc = WriteBytes(&MsgType, 4);
62 assert(rc == 4 && "Error writing message type.");
63
64 uint32_t DataSize = 8;
65 rc = WriteBytes(&DataSize, 4);
66 assert(rc == 4 && "Error writing data size.");
67
68 rc = WriteBytes(&Alignment, 4);
69 assert(rc == 4 && "Error writing alignment data.");
70
71 rc = WriteBytes(&Size, 4);
72 assert(rc == 4 && "Error writing size data.");
73 }
74
75 void RemoteTargetExternal::SendLoadSection(uint64_t Addr,
116 bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
117 if (!SendHeader(LLI_AllocateSpace)) {
118 ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
119 return false;
120 }
121
122 AppendWrite((const void *)&Alignment, 4);
123 AppendWrite((const void *)&Size, 4);
124
125 if (!SendPayload()) {
126 ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
127 return false;
128 }
129 return true;
130 }
131
132 bool RemoteTargetExternal::SendLoadSection(uint64_t Addr,
76133 const void *Data,
77134 uint32_t Size,
78135 bool IsCode) {
79 int rc;
80 (void)rc;
81 uint32_t MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
82 rc = WriteBytes(&MsgType, 4);
83 assert(rc == 4 && "Error writing message type.");
84
85 uint32_t DataSize = Size + 8;
86 rc = WriteBytes(&DataSize, 4);
87 assert(rc == 4 && "Error writing data size.");
88
89 rc = WriteBytes(&Addr, 8);
90 assert(rc == 8 && "Error writing data.");
91
92 rc = WriteBytes(Data, Size);
93 assert(rc == (int)Size && "Error writing data.");
94 }
95
96 void RemoteTargetExternal::SendExecute(uint64_t Addr) {
97 int rc;
98 (void)rc;
99 uint32_t MsgType = (uint32_t)LLI_Execute;
100 rc = WriteBytes(&MsgType, 4);
101 assert(rc == 4 && "Error writing message type.");
102
103 uint32_t DataSize = 8;
104 rc = WriteBytes(&DataSize, 4);
105 assert(rc == 4 && "Error writing data size.");
106
107 rc = WriteBytes(&Addr, 8);
108 assert(rc == 8 && "Error writing data.");
109 }
110
111 void RemoteTargetExternal::SendTerminate() {
112 int rc;
113 (void)rc;
114 uint32_t MsgType = (uint32_t)LLI_Terminate;
115 rc = WriteBytes(&MsgType, 4);
116 assert(rc == 4 && "Error writing message type.");
117
136 LLIMessageType MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
137 if (!SendHeader(MsgType)) {
138 ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
139 return false;
140 }
141
142 AppendWrite((const void *)&Addr, 8);
143 AppendWrite(Data, Size);
144
145 if (!SendPayload()) {
146 ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
147 return false;
148 }
149 return true;
150 }
151
152 bool RemoteTargetExternal::SendExecute(uint64_t Addr) {
153 if (!SendHeader(LLI_Execute)) {
154 ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
155 return false;
156 }
157
158 AppendWrite((const void *)&Addr, 8);
159
160 if (!SendPayload()) {
161 ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
162 return false;
163 }
164 return true;
165 }
166
167 bool RemoteTargetExternal::SendTerminate() {
168 return SendHeader(LLI_Terminate);
118169 // No data or data size is sent with Terminate
119170 }
120171
121
122 void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType) {
123 int rc;
124 (void)rc;
172 bool RemoteTargetExternal::Receive(LLIMessageType Msg) {
173 if (!ReceiveHeader(Msg))
174 return false;
175 int Unused;
176 AppendRead(&Unused, 0);
177 if (!ReceivePayload())
178 return false;
179 ReceiveData.clear();
180 Sizes.clear();
181 return true;
182 }
183
184 bool RemoteTargetExternal::Receive(LLIMessageType Msg, int32_t &Data) {
185 if (!ReceiveHeader(Msg))
186 return false;
187 AppendRead(&Data, 4);
188 if (!ReceivePayload())
189 return false;
190 ReceiveData.clear();
191 Sizes.clear();
192 return true;
193 }
194
195 bool RemoteTargetExternal::Receive(LLIMessageType Msg, uint64_t &Data) {
196 if (!ReceiveHeader(Msg))
197 return false;
198 AppendRead(&Data, 8);
199 if (!ReceivePayload())
200 return false;
201 ReceiveData.clear();
202 Sizes.clear();
203 return true;
204 }
205
206 bool RemoteTargetExternal::ReceiveHeader(LLIMessageType ExpectedMsgType) {
207 assert(ReceiveData.empty() && Sizes.empty() &&
208 "Payload vector not empty to receive header");
209
210 // Message header, with type to follow
125211 uint32_t MsgType;
126 rc = ReadBytes(&MsgType, 4);
127 assert(rc == 4 && "Error reading message type.");
128 assert(MsgType == (uint32_t)ExpectedMsgType && "Error: received unexpected message type.");
129
212 if (!ReadBytes(&MsgType, 4)) {
213 ErrorMsg += ", (RemoteTargetExternal::ReceiveHeader)";
214 return false;
215 }
216 if (MsgType != (uint32_t)ExpectedMsgType) {
217 ErrorMsg = "received unexpected message type";
218 ErrorMsg += ". Expecting: ";
219 ErrorMsg += ExpectedMsgType;
220 ErrorMsg += ", Got: ";
221 ErrorMsg += MsgType;
222 return false;
223 }
224 return true;
225 }
226
227 bool RemoteTargetExternal::ReceivePayload() {
228 assert(!ReceiveData.empty() &&
229 "Payload vector empty to receive");
230 assert(ReceiveData.size() == Sizes.size() &&
231 "Unexpected mismatch between data and size");
232
233 uint32_t TotalSize = 0;
234 for (int I=0, E=Sizes.size(); I < E; I++)
235 TotalSize += Sizes[I];
236
237 // Payload size header
130238 uint32_t DataSize;
131 rc = ReadBytes(&DataSize, 4);
132 assert(rc == 4 && "Error reading data size.");
133 assert(DataSize == 0 && "Error: unexpected data size.");
134 }
135
136 void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, int &Data) {
137 uint64_t Temp;
138 Receive(ExpectedMsgType, Temp);
139 Data = (int)(int64_t)Temp;
140 }
141
142 void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, uint64_t &Data) {
143 int rc;
144 (void)rc;
145 uint32_t MsgType;
146 rc = ReadBytes(&MsgType, 4);
147 assert(rc == 4 && "Error reading message type.");
148 assert(MsgType == (uint32_t)ExpectedMsgType && "Error: received unexpected message type.");
149
150 uint32_t DataSize;
151 rc = ReadBytes(&DataSize, 4);
152 assert(rc == 4 && "Error reading data size.");
153 assert(DataSize == 8 && "Error: unexpected data size.");
154
155 rc = ReadBytes(&Data, 8);
156 assert(DataSize == 8 && "Error: unexpected data.");
239 if (!ReadBytes(&DataSize, 4)) {
240 ErrorMsg += ", invalid data size";
241 return false;
242 }
243 if (DataSize != TotalSize) {
244 ErrorMsg = "unexpected data size";
245 ErrorMsg += ". Expecting: ";
246 ErrorMsg += TotalSize;
247 ErrorMsg += ", Got: ";
248 ErrorMsg += DataSize;
249 return false;
250 }
251 if (DataSize == 0)
252 return true;
253
254 // Payload itself
255 for (int I=0, E=Sizes.size(); I < E; I++) {
256 if (!ReadBytes(ReceiveData[I], Sizes[I])) {
257 ErrorMsg = "unexpected data while reading message";
258 return false;
259 }
260 }
261
262 return true;
263 }
264
265 bool RemoteTargetExternal::SendHeader(LLIMessageType MsgType) {
266 assert(SendData.empty() && Sizes.empty() &&
267 "Payload vector not empty to send header");
268
269 // Message header, with type to follow
270 if (!WriteBytes(&MsgType, 4)) {
271 ErrorMsg += ", (RemoteTargetExternal::SendHeader)";
272 return false;
273 }
274 return true;
275 }
276
277 bool RemoteTargetExternal::SendPayload() {
278 assert(!SendData.empty() && !Sizes.empty() &&
279 "Payload vector empty to send");
280 assert(SendData.size() == Sizes.size() &&
281 "Unexpected mismatch between data and size");
282
283 uint32_t TotalSize = 0;
284 for (int I=0, E=Sizes.size(); I < E; I++)
285 TotalSize += Sizes[I];
286
287 // Payload size header
288 if (!WriteBytes(&TotalSize, 4)) {
289 ErrorMsg += ", invalid data size";
290 return false;
291 }
292 if (TotalSize == 0)
293 return true;
294
295 // Payload itself
296 for (int I=0, E=Sizes.size(); I < E; I++) {
297 if (!WriteBytes(SendData[I], Sizes[I])) {
298 ErrorMsg = "unexpected data while writing message";
299 return false;
300 }
301 }
302
303 SendData.clear();
304 Sizes.clear();
305 return true;
306 }
307
308 void RemoteTargetExternal::AppendWrite(const void *Data, uint32_t Size) {
309 SendData.push_back(Data);
310 Sizes.push_back(Size);
311 }
312
313 void RemoteTargetExternal::AppendRead(void *Data, uint32_t Size) {
314 ReceiveData.push_back(Data);
315 Sizes.push_back(Size);
157316 }
158317
159318 #ifdef LLVM_ON_UNIX
3434 /// @param Alignment Required minimum alignment for allocated space.
3535 /// @param[out] Address Remote address of the allocated memory.
3636 ///
37 /// @returns False on success. On failure, ErrorMsg is updated with
37 /// @returns True on success. On failure, ErrorMsg is updated with
3838 /// descriptive text of the encountered error.
3939 virtual bool allocateSpace(size_t Size,
4040 unsigned Alignment,
4646 /// @param Data Source address in the host process.
4747 /// @param Size Number of bytes to copy.
4848 ///
49 /// @returns False on success. On failure, ErrorMsg is updated with
49 /// @returns True on success. On failure, ErrorMsg is updated with
5050 /// descriptive text of the encountered error.
5151 virtual bool loadData(uint64_t Address, const void *Data, size_t Size);
5252
5656 /// @param Data Source address in the host process.
5757 /// @param Size Number of bytes to copy.
5858 ///
59 /// @returns False on success. On failure, ErrorMsg is updated with
59 /// @returns True on success. On failure, ErrorMsg is updated with
6060 /// descriptive text of the encountered error.
6161 virtual bool loadCode(uint64_t Address, const void *Data, size_t Size);
6262
6767 /// process.
6868 /// @param[out] RetVal The integer return value of the called function.
6969 ///
70 /// @returns False on success. On failure, ErrorMsg is updated with
70 /// @returns True on success. On failure, ErrorMsg is updated with
7171 /// descriptive text of the encountered error.
7272 virtual bool executeCode(uint64_t Address, int &RetVal);
7373
7979 virtual unsigned getPageAlignment() { return 4096; }
8080
8181 /// Start the remote process.
82 virtual void create();
82 ///
83 /// @returns True on success. On failure, ErrorMsg is updated with
84 /// descriptive text of the encountered error.
85 virtual bool create();
8386
8487 /// Terminate the remote process.
8588 virtual void stop();
9093 private:
9194 std::string ChildName;
9295
96 bool SendAllocateSpace(uint32_t Alignment, uint32_t Size);
97 bool SendLoadSection(uint64_t Addr,
98 const void *Data,
99 uint32_t Size,
100 bool IsCode);
101 bool SendExecute(uint64_t Addr);
102 bool SendTerminate();
103
104 // High-level wrappers for receiving data
105 bool Receive(LLIMessageType Msg);
106 bool Receive(LLIMessageType Msg, int32_t &Data);
107 bool Receive(LLIMessageType Msg, uint64_t &Data);
108
109 // Lower level target-independent read/write to deal with errors
110 bool ReceiveHeader(LLIMessageType Msg);
111 bool ReceivePayload();
112 bool SendHeader(LLIMessageType Msg);
113 bool SendPayload();
114
115 // Functions to append/retrieve data from the payload
116 SmallVector SendData;
117 SmallVector ReceiveData; // Future proof
118 SmallVector Sizes;
119 void AppendWrite(const void *Data, uint32_t Size);
120 void AppendRead(void *Data, uint32_t Size);
121
93122 // This will get filled in as a point to an OS-specific structure.
94123 void *ConnectionData;
95124
96 void SendAllocateSpace(uint32_t Alignment, uint32_t Size);
97 void SendLoadSection(uint64_t Addr,
98 const void *Data,
99 uint32_t Size,
100 bool IsCode);
101 void SendExecute(uint64_t Addr);
102 void SendTerminate();
103
104 void Receive(LLIMessageType Msg);
105 void Receive(LLIMessageType Msg, int &Data);
106 void Receive(LLIMessageType Msg, uint64_t &Data);
107
108 int WriteBytes(const void *Data, size_t Size);
109 int ReadBytes(void *Data, size_t Size);
125 bool WriteBytes(const void *Data, size_t Size);
126 bool ReadBytes(void *Data, size_t Size);
110127 void Wait();
111128 };
112129
2525 // only here for testing purposes and is therefore intended to be the simplest
2626 // implementation that will work. It is assumed that the parent and child
2727 // share characteristics like endianness.
28 //
29 // Quick description of the protocol:
30 //
31 // { Header + Payload Size + Payload }
32 //
33 // The protocol message consist of a header, the payload size (which can be
34 // zero), and the payload itself. The payload can contain any number of items,
35 // and the size has to be the sum of them all. Each end is responsible for
36 // reading/writing the correct number of items with the correct sizes.
37 //
38 // The current four known exchanges are:
39 //
40 // * Allocate Space:
41 // Parent: { LLI_AllocateSpace, 8, Alignment, Size }
42 // Child: { LLI_AllocationResult, 8, Address }
43 //
44 // * Load Data:
45 // Parent: { LLI_LoadDataSection, 8+Size, Address, Data }
46 // Child: { LLI_LoadComplete, 4, StatusCode }
47 //
48 // * Load Code:
49 // Parent: { LLI_LoadCodeSection, 8+Size, Address, Code }
50 // Child: { LLI_LoadComplete, 4, StatusCode }
51 //
52 // * Execute Code:
53 // Parent: { LLI_Execute, 8, Address }
54 // Child: { LLI_ExecutionResult, 4, Result }
55 //
56 // It is the responsibility of either side to check for correct headers,
57 // sizes and payloads, since any inconsistency would misalign the pipe, and
58 // result in data corruption.
2859
2960 enum LLIMessageType {
3061 LLI_Error = -1,
3162 LLI_ChildActive = 0, // Data = not used
32 LLI_AllocateSpace, // Data = struct { uint_32t Align, uint_32t Size }
33 LLI_AllocationResult, // Data = uint64_t AllocAddress (in Child memory space)
34 LLI_LoadCodeSection, // Data = uint32_t Addr, followed by section contests
35 LLI_LoadDataSection, // Data = uint32_t Addr, followed by section contents
36 LLI_LoadComplete, // Data = not used
37 LLI_Execute, // Data = Address of function to execute
38 LLI_ExecutionResult, // Data = uint64_t Result
63 LLI_AllocateSpace, // Data = struct { uint32_t Align, uint_32t Size }
64 LLI_AllocationResult, // Data = uint64_t Address (child memory space)
65
66 LLI_LoadCodeSection, // Data = uint64_t Address, void * SectionData
67 LLI_LoadDataSection, // Data = uint64_t Address, void * SectionData
68 LLI_LoadResult, // Data = uint32_t LLIMessageStatus
69
70 LLI_Execute, // Data = uint64_t Address
71 LLI_ExecutionResult, // Data = uint32_t Result
72
3973 LLI_Terminate // Data = not used
74 };
75
76 enum LLIMessageStatus {
77 LLI_Status_Success = 0, // Operation succeeded
78 LLI_Status_NotAllocated, // Address+Size not allocated in child space
79 LLI_Status_IncompleteMsg // Size received doesn't match request
4080 };
4181
4282 } // end namespace llvm
2929
3030 namespace llvm {
3131
32 void RemoteTargetExternal::create() {
32 bool RemoteTargetExternal::create() {
3333 int PipeFD[2][2];
3434 pid_t ChildPID;
3535
7272 // Store the parent ends of the pipes
7373 ConnectionData = (void*)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]);
7474
75 Receive(LLI_ChildActive);
75 // We must get Ack from the client (blocking read)
76 if (!Receive(LLI_ChildActive)) {
77 ErrorMsg += ", (RemoteTargetExternal::create) - Stopping process!";
78 stop();
79 return false;
80 }
81 }
82 return true;
83 }
84
85 static void ReportError(int rc, size_t Size, std::string &ErrorMsg) {
86 if (rc == -1) {
87 if (errno == EPIPE)
88 ErrorMsg += "pipe closed";
89 else if (errno == EINTR)
90 ErrorMsg += "interrupted";
91 else
92 ErrorMsg += "file descriptor error";
93 } else {
94 char Number[10] = { 0 };
95 ErrorMsg += "Expecting ";
96 sprintf(Number, "%d", (uint32_t)Size);
97 ErrorMsg += Number;
98 ErrorMsg += " bytes, Got ";
99 sprintf(Number, "%d", rc);
100 ErrorMsg += Number;
76101 }
77102 }
78103
79 int RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
80 return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
104 bool RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
105 int rc = write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
106 if (rc != -1 && (size_t)rc == Size)
107 return true;
108
109 ErrorMsg = "WriteBytes: ";
110 ReportError(rc, Size, ErrorMsg);
111 return false;
81112 }
82113
83 int RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
84 return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
114 bool RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
115 int rc = read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
116 if (rc != -1 && (size_t)rc == Size)
117 return true;
118
119 ErrorMsg = "ReadBytes: ";
120 ReportError(rc, Size, ErrorMsg);
121 return false;
85122 }
86123
87124 void RemoteTargetExternal::Wait() {
684684 MM->setRemoteTarget(Target.get());
685685
686686 // Create the remote target.
687 Target->create();
687 if (!Target->create()) {
688 errs() << "ERROR: " << Target->getErrorMsg() << "\n";
689 return EXIT_FAILURE;
690 }
688691
689692 // Since we're executing in a (at least simulated) remote address space,
690693 // we can't use the ExecutionEngine::runFunctionAsMain(). We have to
701704 DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
702705 << format("%llx", Entry) << "\n");
703706
704 if (Target->executeCode(Entry, Result))
707 if (!Target->executeCode(Entry, Result))
705708 errs() << "ERROR: " << Target->getErrorMsg() << "\n";
706709
707710 // Like static constructors, the remote target MCJIT support doesn't handle