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
This commit is contained in:
Renato Golin
2014-01-14 22:43:43 +00:00
parent 0445dc203b
commit 83ece7a499
9 changed files with 450 additions and 165 deletions

View File

@ -17,6 +17,8 @@
#include "RemoteTargetExternal.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
@ -26,28 +28,85 @@ using namespace llvm;
bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,
uint64_t &Address) {
SendAllocateSpace(Alignment, Size);
Receive(LLI_AllocationResult, Address);
return false;
DEBUG(dbgs() << "Message [allocate space] size: " << Size <<
", align: " << Alignment << "\n");
if (!SendAllocateSpace(Alignment, Size)) {
ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
return false;
}
if (!Receive(LLI_AllocationResult, Address)) {
ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
return false;
}
if (Address == 0) {
ErrorMsg += "failed allocation, (RemoteTargetExternal::allocateSpace)";
return false;
}
DEBUG(dbgs() << "Message [allocate space] addr: 0x" <<
format("%llx", Address) << "\n");
return true;
}
bool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {
SendLoadSection(Address, Data, (uint32_t)Size, false);
Receive(LLI_LoadComplete);
return false;
DEBUG(dbgs() << "Message [load data] addr: 0x" << format("%llx", Address) <<
", size: " << Size << "\n");
if (!SendLoadSection(Address, Data, (uint32_t)Size, false)) {
ErrorMsg += ", (RemoteTargetExternal::loadData)";
return false;
}
int Status = LLI_Status_Success;
if (!Receive(LLI_LoadResult, Status)) {
ErrorMsg += ", (RemoteTargetExternal::loadData)";
return false;
}
if (Status == LLI_Status_IncompleteMsg) {
ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
return false;
}
if (Status == LLI_Status_NotAllocated) {
ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
return false;
}
DEBUG(dbgs() << "Message [load data] complete\n");
return true;
}
bool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {
SendLoadSection(Address, Data, (uint32_t)Size, true);
Receive(LLI_LoadComplete);
return false;
DEBUG(dbgs() << "Message [load code] addr: 0x" << format("%llx", Address) <<
", size: " << Size << "\n");
if (!SendLoadSection(Address, Data, (uint32_t)Size, true)) {
ErrorMsg += ", (RemoteTargetExternal::loadCode)";
return false;
}
int Status = LLI_Status_Success;
if (!Receive(LLI_LoadResult, Status)) {
ErrorMsg += ", (RemoteTargetExternal::loadCode)";
return false;
}
if (Status == LLI_Status_IncompleteMsg) {
ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
return false;
}
if (Status == LLI_Status_NotAllocated) {
ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
return false;
}
DEBUG(dbgs() << "Message [load code] complete\n");
return true;
}
bool RemoteTargetExternal::executeCode(uint64_t Address, int &RetVal) {
SendExecute(Address);
Receive(LLI_ExecutionResult, RetVal);
return false;
bool RemoteTargetExternal::executeCode(uint64_t Address, int32_t &RetVal) {
DEBUG(dbgs() << "Message [exectue code] addr: " << Address << "\n");
if (!SendExecute(Address)) {
ErrorMsg += ", (RemoteTargetExternal::executeCode)";
return false;
}
if (!Receive(LLI_ExecutionResult, RetVal)) {
ErrorMsg += ", (RemoteTargetExternal::executeCode)";
return false;
}
DEBUG(dbgs() << "Message [exectue code] return: " << RetVal << "\n");
return true;
}
void RemoteTargetExternal::stop() {
@ -55,106 +114,206 @@ void RemoteTargetExternal::stop() {
Wait();
}
void RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
int rc;
(void)rc;
uint32_t MsgType = (uint32_t)LLI_AllocateSpace;
rc = WriteBytes(&MsgType, 4);
assert(rc == 4 && "Error writing message type.");
bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
if (!SendHeader(LLI_AllocateSpace)) {
ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
return false;
}
uint32_t DataSize = 8;
rc = WriteBytes(&DataSize, 4);
assert(rc == 4 && "Error writing data size.");
AppendWrite((const void *)&Alignment, 4);
AppendWrite((const void *)&Size, 4);
rc = WriteBytes(&Alignment, 4);
assert(rc == 4 && "Error writing alignment data.");
rc = WriteBytes(&Size, 4);
assert(rc == 4 && "Error writing size data.");
if (!SendPayload()) {
ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
return false;
}
return true;
}
void RemoteTargetExternal::SendLoadSection(uint64_t Addr,
bool RemoteTargetExternal::SendLoadSection(uint64_t Addr,
const void *Data,
uint32_t Size,
bool IsCode) {
int rc;
(void)rc;
uint32_t MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
rc = WriteBytes(&MsgType, 4);
assert(rc == 4 && "Error writing message type.");
LLIMessageType MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
if (!SendHeader(MsgType)) {
ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
return false;
}
uint32_t DataSize = Size + 8;
rc = WriteBytes(&DataSize, 4);
assert(rc == 4 && "Error writing data size.");
AppendWrite((const void *)&Addr, 8);
AppendWrite(Data, Size);
rc = WriteBytes(&Addr, 8);
assert(rc == 8 && "Error writing data.");
rc = WriteBytes(Data, Size);
assert(rc == (int)Size && "Error writing data.");
if (!SendPayload()) {
ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
return false;
}
return true;
}
void RemoteTargetExternal::SendExecute(uint64_t Addr) {
int rc;
(void)rc;
uint32_t MsgType = (uint32_t)LLI_Execute;
rc = WriteBytes(&MsgType, 4);
assert(rc == 4 && "Error writing message type.");
bool RemoteTargetExternal::SendExecute(uint64_t Addr) {
if (!SendHeader(LLI_Execute)) {
ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
return false;
}
uint32_t DataSize = 8;
rc = WriteBytes(&DataSize, 4);
assert(rc == 4 && "Error writing data size.");
AppendWrite((const void *)&Addr, 8);
rc = WriteBytes(&Addr, 8);
assert(rc == 8 && "Error writing data.");
if (!SendPayload()) {
ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
return false;
}
return true;
}
void RemoteTargetExternal::SendTerminate() {
int rc;
(void)rc;
uint32_t MsgType = (uint32_t)LLI_Terminate;
rc = WriteBytes(&MsgType, 4);
assert(rc == 4 && "Error writing message type.");
bool RemoteTargetExternal::SendTerminate() {
return SendHeader(LLI_Terminate);
// No data or data size is sent with Terminate
}
void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType) {
int rc;
(void)rc;
uint32_t MsgType;
rc = ReadBytes(&MsgType, 4);
assert(rc == 4 && "Error reading message type.");
assert(MsgType == (uint32_t)ExpectedMsgType && "Error: received unexpected message type.");
uint32_t DataSize;
rc = ReadBytes(&DataSize, 4);
assert(rc == 4 && "Error reading data size.");
assert(DataSize == 0 && "Error: unexpected data size.");
bool RemoteTargetExternal::Receive(LLIMessageType Msg) {
if (!ReceiveHeader(Msg))
return false;
int Unused;
AppendRead(&Unused, 0);
if (!ReceivePayload())
return false;
ReceiveData.clear();
Sizes.clear();
return true;
}
void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, int &Data) {
uint64_t Temp;
Receive(ExpectedMsgType, Temp);
Data = (int)(int64_t)Temp;
bool RemoteTargetExternal::Receive(LLIMessageType Msg, int32_t &Data) {
if (!ReceiveHeader(Msg))
return false;
AppendRead(&Data, 4);
if (!ReceivePayload())
return false;
ReceiveData.clear();
Sizes.clear();
return true;
}
void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, uint64_t &Data) {
int rc;
(void)rc;
bool RemoteTargetExternal::Receive(LLIMessageType Msg, uint64_t &Data) {
if (!ReceiveHeader(Msg))
return false;
AppendRead(&Data, 8);
if (!ReceivePayload())
return false;
ReceiveData.clear();
Sizes.clear();
return true;
}
bool RemoteTargetExternal::ReceiveHeader(LLIMessageType ExpectedMsgType) {
assert(ReceiveData.empty() && Sizes.empty() &&
"Payload vector not empty to receive header");
// Message header, with type to follow
uint32_t MsgType;
rc = ReadBytes(&MsgType, 4);
assert(rc == 4 && "Error reading message type.");
assert(MsgType == (uint32_t)ExpectedMsgType && "Error: received unexpected message type.");
if (!ReadBytes(&MsgType, 4)) {
ErrorMsg += ", (RemoteTargetExternal::ReceiveHeader)";
return false;
}
if (MsgType != (uint32_t)ExpectedMsgType) {
ErrorMsg = "received unexpected message type";
ErrorMsg += ". Expecting: ";
ErrorMsg += ExpectedMsgType;
ErrorMsg += ", Got: ";
ErrorMsg += MsgType;
return false;
}
return true;
}
bool RemoteTargetExternal::ReceivePayload() {
assert(!ReceiveData.empty() &&
"Payload vector empty to receive");
assert(ReceiveData.size() == Sizes.size() &&
"Unexpected mismatch between data and size");
uint32_t TotalSize = 0;
for (int I=0, E=Sizes.size(); I < E; I++)
TotalSize += Sizes[I];
// Payload size header
uint32_t DataSize;
rc = ReadBytes(&DataSize, 4);
assert(rc == 4 && "Error reading data size.");
assert(DataSize == 8 && "Error: unexpected data size.");
if (!ReadBytes(&DataSize, 4)) {
ErrorMsg += ", invalid data size";
return false;
}
if (DataSize != TotalSize) {
ErrorMsg = "unexpected data size";
ErrorMsg += ". Expecting: ";
ErrorMsg += TotalSize;
ErrorMsg += ", Got: ";
ErrorMsg += DataSize;
return false;
}
if (DataSize == 0)
return true;
rc = ReadBytes(&Data, 8);
assert(DataSize == 8 && "Error: unexpected data.");
// Payload itself
for (int I=0, E=Sizes.size(); I < E; I++) {
if (!ReadBytes(ReceiveData[I], Sizes[I])) {
ErrorMsg = "unexpected data while reading message";
return false;
}
}
return true;
}
bool RemoteTargetExternal::SendHeader(LLIMessageType MsgType) {
assert(SendData.empty() && Sizes.empty() &&
"Payload vector not empty to send header");
// Message header, with type to follow
if (!WriteBytes(&MsgType, 4)) {
ErrorMsg += ", (RemoteTargetExternal::SendHeader)";
return false;
}
return true;
}
bool RemoteTargetExternal::SendPayload() {
assert(!SendData.empty() && !Sizes.empty() &&
"Payload vector empty to send");
assert(SendData.size() == Sizes.size() &&
"Unexpected mismatch between data and size");
uint32_t TotalSize = 0;
for (int I=0, E=Sizes.size(); I < E; I++)
TotalSize += Sizes[I];
// Payload size header
if (!WriteBytes(&TotalSize, 4)) {
ErrorMsg += ", invalid data size";
return false;
}
if (TotalSize == 0)
return true;
// Payload itself
for (int I=0, E=Sizes.size(); I < E; I++) {
if (!WriteBytes(SendData[I], Sizes[I])) {
ErrorMsg = "unexpected data while writing message";
return false;
}
}
SendData.clear();
Sizes.clear();
return true;
}
void RemoteTargetExternal::AppendWrite(const void *Data, uint32_t Size) {
SendData.push_back(Data);
Sizes.push_back(Size);
}
void RemoteTargetExternal::AppendRead(void *Data, uint32_t Size) {
ReceiveData.push_back(Data);
Sizes.push_back(Size);
}
#ifdef LLVM_ON_UNIX