summaryrefslogtreecommitdiff
path: root/tools/lli
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lli')
-rw-r--r--tools/lli/ChildTarget/ChildTarget.cpp56
-rw-r--r--tools/lli/RemoteMemoryManager.cpp10
-rw-r--r--tools/lli/RemoteTarget.cpp15
-rw-r--r--tools/lli/RemoteTarget.h16
-rw-r--r--tools/lli/RemoteTargetExternal.cpp331
-rw-r--r--tools/lli/RemoteTargetExternal.h51
-rw-r--r--tools/lli/RemoteTargetMessage.h54
-rw-r--r--tools/lli/Unix/RemoteTargetExternal.inc49
-rw-r--r--tools/lli/lli.cpp7
9 files changed, 437 insertions, 152 deletions
diff --git a/tools/lli/ChildTarget/ChildTarget.cpp b/tools/lli/ChildTarget/ChildTarget.cpp
index dba8966cf4..ca75beb842 100644
--- a/tools/lli/ChildTarget/ChildTarget.cpp
+++ b/tools/lli/ChildTarget/ChildTarget.cpp
@@ -25,8 +25,8 @@ private:
// Outgoing message handlers
void sendChildActive();
void sendAllocationResult(uint64_t Addr);
- void sendLoadComplete();
- void sendExecutionComplete(uint64_t Result);
+ void sendLoadStatus(uint32_t Status);
+ void sendExecutionComplete(int Result);
// OS-specific functions
void initializeConnection();
@@ -36,6 +36,7 @@ private:
void makeSectionExecutable(uint64_t Addr, uint32_t Size);
void InvalidateInstructionCache(const void *Addr, size_t Len);
void releaseMemory(uint64_t Addr, uint32_t Size);
+ bool isAllocatedMemory(uint64_t Address, uint32_t Size);
// Store a map of allocated buffers to sizes.
typedef std::map<uint64_t, uint32_t> AllocMapType;
@@ -121,33 +122,36 @@ void LLIChildTarget::handleLoadSection(bool IsCode) {
// Read the message data size.
uint32_t DataSize;
int rc = ReadBytes(&DataSize, 4);
+ (void)rc;
assert(rc == 4);
// Read the target load address.
uint64_t Addr;
rc = ReadBytes(&Addr, 8);
assert(rc == 8);
-
size_t BufferSize = DataSize - 8;
- // FIXME: Verify that this is in allocated space
+ if (!isAllocatedMemory(Addr, BufferSize))
+ return sendLoadStatus(LLI_Status_NotAllocated);
// Read section data into previously allocated buffer
- rc = ReadBytes((void*)Addr, DataSize - 8);
- assert(rc == (int)(BufferSize));
+ rc = ReadBytes((void*)Addr, BufferSize);
+ if (rc != (int)(BufferSize))
+ return sendLoadStatus(LLI_Status_IncompleteMsg);
// If IsCode, mark memory executable
if (IsCode)
makeSectionExecutable(Addr, BufferSize);
// Send MarkLoadComplete message.
- sendLoadComplete();
+ sendLoadStatus(LLI_Status_Success);
}
void LLIChildTarget::handleExecute() {
// Read the message data size.
uint32_t DataSize;
int rc = ReadBytes(&DataSize, 4);
+ (void)rc;
assert(rc == 4);
assert(DataSize == 8);
@@ -162,7 +166,7 @@ void LLIChildTarget::handleExecute() {
Result = fn();
// Send ExecutionResult message.
- sendExecutionComplete((int64_t)Result);
+ sendExecutionComplete(Result);
}
void LLIChildTarget::handleTerminate() {
@@ -175,11 +179,26 @@ void LLIChildTarget::handleTerminate() {
m_AllocatedBufferMap.clear();
}
+bool LLIChildTarget::isAllocatedMemory(uint64_t Address, uint32_t Size) {
+ uint64_t End = Address+Size;
+ AllocMapType::iterator ItBegin = m_AllocatedBufferMap.begin();
+ AllocMapType::iterator ItEnd = m_AllocatedBufferMap.end();
+ for (AllocMapType::iterator It = ItBegin; It != ItEnd; ++It) {
+ uint64_t A = It->first;
+ uint64_t E = A + It->second;
+ // Starts and finishes inside allocated region
+ if (Address >= A && End <= E)
+ return true;
+ }
+ return false;
+}
+
// Outgoing message handlers
void LLIChildTarget::sendChildActive() {
// Write the message type.
uint32_t MsgType = (uint32_t)LLI_ChildActive;
int rc = WriteBytes(&MsgType, 4);
+ (void)rc;
assert(rc == 4);
// Write the data size.
@@ -192,6 +211,7 @@ void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
// Write the message type.
uint32_t MsgType = (uint32_t)LLI_AllocationResult;
int rc = WriteBytes(&MsgType, 4);
+ (void)rc;
assert(rc == 4);
// Write the data size.
@@ -204,33 +224,39 @@ void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
assert(rc == 8);
}
-void LLIChildTarget::sendLoadComplete() {
+void LLIChildTarget::sendLoadStatus(uint32_t Status) {
// Write the message type.
- uint32_t MsgType = (uint32_t)LLI_LoadComplete;
+ uint32_t MsgType = (uint32_t)LLI_LoadResult;
int rc = WriteBytes(&MsgType, 4);
+ (void)rc;
assert(rc == 4);
// Write the data size.
- uint32_t DataSize = 0;
+ uint32_t DataSize = 4;
rc = WriteBytes(&DataSize, 4);
assert(rc == 4);
+
+ // Write the result.
+ rc = WriteBytes(&Status, 4);
+ assert(rc == 4);
}
-void LLIChildTarget::sendExecutionComplete(uint64_t Result) {
+void LLIChildTarget::sendExecutionComplete(int Result) {
// Write the message type.
uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
int rc = WriteBytes(&MsgType, 4);
+ (void)rc;
assert(rc == 4);
// Write the data size.
- uint32_t DataSize = 8;
+ uint32_t DataSize = 4;
rc = WriteBytes(&DataSize, 4);
assert(rc == 4);
// Write the result.
- rc = WriteBytes(&Result, 8);
- assert(rc == 8);
+ rc = WriteBytes(&Result, 4);
+ assert(rc == 4);
}
#ifdef LLVM_ON_UNIX
diff --git a/tools/lli/RemoteMemoryManager.cpp b/tools/lli/RemoteMemoryManager.cpp
index 04fc40e426..c9d426a4e6 100644
--- a/tools/lli/RemoteMemoryManager.cpp
+++ b/tools/lli/RemoteMemoryManager.cpp
@@ -129,7 +129,7 @@ void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
// Allocate space in the remote target.
uint64_t RemoteAddr;
- if (Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
+ if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
report_fatal_error(Target->getErrorMsg());
// Map the section addresses so relocations will get updated in the local
@@ -155,13 +155,13 @@ bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
uint64_t RemoteAddr = I->first;
const Allocation &Section = I->second;
if (Section.IsCode) {
- Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size());
-
+ if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
+ report_fatal_error(Target->getErrorMsg());
DEBUG(dbgs() << " loading code: " << Section.MB.base()
<< " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
} else {
- Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size());
-
+ if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
+ report_fatal_error(Target->getErrorMsg());
DEBUG(dbgs() << " loading data: " << Section.MB.base()
<< " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
}
diff --git a/tools/lli/RemoteTarget.cpp b/tools/lli/RemoteTarget.cpp
index 5c74e6e7a0..9631ef7aac 100644
--- a/tools/lli/RemoteTarget.cpp
+++ b/tools/lli/RemoteTarget.cpp
@@ -56,34 +56,35 @@ bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment,
sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : NULL;
sys::MemoryBlock Mem = sys::Memory::AllocateRWX(Size, Prev, &ErrorMsg);
if (Mem.base() == NULL)
- return true;
+ return false;
if ((uintptr_t)Mem.base() % Alignment) {
ErrorMsg = "unable to allocate sufficiently aligned memory";
- return true;
+ return false;
}
Address = reinterpret_cast<uint64_t>(Mem.base());
- return false;
+ return true;
}
bool RemoteTarget::loadData(uint64_t Address, const void *Data, size_t Size) {
memcpy ((void*)Address, Data, Size);
- return false;
+ return true;
}
bool RemoteTarget::loadCode(uint64_t Address, const void *Data, size_t Size) {
memcpy ((void*)Address, Data, Size);
sys::MemoryBlock Mem((void*)Address, Size);
sys::Memory::setExecutable(Mem, &ErrorMsg);
- return false;
+ return true;
}
bool RemoteTarget::executeCode(uint64_t Address, int &RetVal) {
int (*fn)(void) = (int(*)(void))Address;
RetVal = fn();
- return false;
+ return true;
}
-void RemoteTarget::create() {
+bool RemoteTarget::create() {
+ return true;
}
void RemoteTarget::stop() {
diff --git a/tools/lli/RemoteTarget.h b/tools/lli/RemoteTarget.h
index c95fbd1ae9..a7d4e59e3b 100644
--- a/tools/lli/RemoteTarget.h
+++ b/tools/lli/RemoteTarget.h
@@ -25,11 +25,13 @@
namespace llvm {
class RemoteTarget {
- std::string ErrorMsg;
bool IsRunning;
SmallVector<sys::MemoryBlock, 16> Allocations;
+protected:
+ std::string ErrorMsg;
+
public:
StringRef getErrorMsg() const { return ErrorMsg; }
@@ -39,7 +41,7 @@ public:
/// @param Alignment Required minimum alignment for allocated space.
/// @param[out] Address Remote address of the allocated memory.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool allocateSpace(size_t Size,
unsigned Alignment,
@@ -51,7 +53,7 @@ public:
/// @param Data Source address in the host process.
/// @param Size Number of bytes to copy.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool loadData(uint64_t Address,
const void *Data,
@@ -63,7 +65,7 @@ public:
/// @param Data Source address in the host process.
/// @param Size Number of bytes to copy.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool loadCode(uint64_t Address,
const void *Data,
@@ -76,7 +78,7 @@ public:
/// process.
/// @param[out] RetVal The integer return value of the called function.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool executeCode(uint64_t Address,
int &RetVal);
@@ -89,12 +91,12 @@ public:
virtual unsigned getPageAlignment() { return 4096; }
/// Start the remote process.
- virtual void create();
+ virtual bool create();
/// Terminate the remote process.
virtual void stop();
- RemoteTarget() : ErrorMsg(""), IsRunning(false) {}
+ RemoteTarget() : IsRunning(false), ErrorMsg("") {}
virtual ~RemoteTarget() { if (IsRunning) stop(); }
// Create an instance of the system-specific remote target class.
diff --git a/tools/lli/RemoteTargetExternal.cpp b/tools/lli/RemoteTargetExternal.cpp
index 809488c9e3..3bf7bf4e3b 100644
--- a/tools/lli/RemoteTargetExternal.cpp
+++ b/tools/lli/RemoteTargetExternal.cpp
@@ -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.");
-
- uint32_t DataSize = 8;
- rc = WriteBytes(&DataSize, 4);
- assert(rc == 4 && "Error writing data size.");
+bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
+ if (!SendHeader(LLI_AllocateSpace)) {
+ ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
+ return false;
+ }
- rc = WriteBytes(&Alignment, 4);
- assert(rc == 4 && "Error writing alignment data.");
+ AppendWrite((const void *)&Alignment, 4);
+ AppendWrite((const void *)&Size, 4);
- 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.");
-
- uint32_t DataSize = Size + 8;
- rc = WriteBytes(&DataSize, 4);
- assert(rc == 4 && "Error writing data size.");
+ LLIMessageType MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
+ if (!SendHeader(MsgType)) {
+ ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
+ return false;
+ }
- rc = WriteBytes(&Addr, 8);
- assert(rc == 8 && "Error writing data.");
+ AppendWrite((const void *)&Addr, 8);
+ AppendWrite(Data, Size);
- 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
}
+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;
+}
+
+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;
+}
+
+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;
+}
-void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType) {
- int rc;
- (void)rc;
+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 == 0 && "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;
+
+ // 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;
}
-void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, int &Data) {
- uint64_t Temp;
- Receive(ExpectedMsgType, Temp);
- Data = (int)(int64_t)Temp;
+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;
}
-void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, uint64_t &Data) {
- 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.");
+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 DataSize;
- rc = ReadBytes(&DataSize, 4);
- assert(rc == 4 && "Error reading data size.");
- assert(DataSize == 8 && "Error: unexpected data 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);
+}
- rc = ReadBytes(&Data, 8);
- assert(DataSize == 8 && "Error: unexpected data.");
+void RemoteTargetExternal::AppendRead(void *Data, uint32_t Size) {
+ ReceiveData.push_back(Data);
+ Sizes.push_back(Size);
}
#ifdef LLVM_ON_UNIX
diff --git a/tools/lli/RemoteTargetExternal.h b/tools/lli/RemoteTargetExternal.h
index 63548eb52d..5ef67100e3 100644
--- a/tools/lli/RemoteTargetExternal.h
+++ b/tools/lli/RemoteTargetExternal.h
@@ -35,7 +35,7 @@ public:
/// @param Alignment Required minimum alignment for allocated space.
/// @param[out] Address Remote address of the allocated memory.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool allocateSpace(size_t Size,
unsigned Alignment,
@@ -47,7 +47,7 @@ public:
/// @param Data Source address in the host process.
/// @param Size Number of bytes to copy.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool loadData(uint64_t Address, const void *Data, size_t Size);
@@ -57,7 +57,7 @@ public:
/// @param Data Source address in the host process.
/// @param Size Number of bytes to copy.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool loadCode(uint64_t Address, const void *Data, size_t Size);
@@ -68,7 +68,7 @@ public:
/// process.
/// @param[out] RetVal The integer return value of the called function.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool executeCode(uint64_t Address, int &RetVal);
@@ -80,7 +80,10 @@ public:
virtual unsigned getPageAlignment() { return 4096; }
/// Start the remote process.
- virtual void create();
+ ///
+ /// @returns True on success. On failure, ErrorMsg is updated with
+ /// descriptive text of the encountered error.
+ virtual bool create();
/// Terminate the remote process.
virtual void stop();
@@ -91,23 +94,37 @@ public:
private:
std::string ChildName;
- // This will get filled in as a point to an OS-specific structure.
- void *ConnectionData;
-
- void SendAllocateSpace(uint32_t Alignment, uint32_t Size);
- void SendLoadSection(uint64_t Addr,
+ bool SendAllocateSpace(uint32_t Alignment, uint32_t Size);
+ bool SendLoadSection(uint64_t Addr,
const void *Data,
uint32_t Size,
bool IsCode);
- void SendExecute(uint64_t Addr);
- void SendTerminate();
+ bool SendExecute(uint64_t Addr);
+ bool SendTerminate();
+
+ // High-level wrappers for receiving data
+ bool Receive(LLIMessageType Msg);
+ bool Receive(LLIMessageType Msg, int32_t &Data);
+ bool Receive(LLIMessageType Msg, uint64_t &Data);
+
+ // Lower level target-independent read/write to deal with errors
+ bool ReceiveHeader(LLIMessageType Msg);
+ bool ReceivePayload();
+ bool SendHeader(LLIMessageType Msg);
+ bool SendPayload();
+
+ // Functions to append/retrieve data from the payload
+ SmallVector<const void *, 2> SendData;
+ SmallVector<void *, 1> ReceiveData; // Future proof
+ SmallVector<int, 2> Sizes;
+ void AppendWrite(const void *Data, uint32_t Size);
+ void AppendRead(void *Data, uint32_t Size);
- void Receive(LLIMessageType Msg);
- void Receive(LLIMessageType Msg, int &Data);
- void Receive(LLIMessageType Msg, uint64_t &Data);
+ // This will get filled in as a point to an OS-specific structure.
+ void *ConnectionData;
- int WriteBytes(const void *Data, size_t Size);
- int ReadBytes(void *Data, size_t Size);
+ bool WriteBytes(const void *Data, size_t Size);
+ bool ReadBytes(void *Data, size_t Size);
void Wait();
};
diff --git a/tools/lli/RemoteTargetMessage.h b/tools/lli/RemoteTargetMessage.h
index 12cfa9a404..cb934a1066 100644
--- a/tools/lli/RemoteTargetMessage.h
+++ b/tools/lli/RemoteTargetMessage.h
@@ -26,20 +26,60 @@ namespace llvm {
// only here for testing purposes and is therefore intended to be the simplest
// implementation that will work. It is assumed that the parent and child
// share characteristics like endianness.
+//
+// Quick description of the protocol:
+//
+// { Header + Payload Size + Payload }
+//
+// The protocol message consist of a header, the payload size (which can be
+// zero), and the payload itself. The payload can contain any number of items,
+// and the size has to be the sum of them all. Each end is responsible for
+// reading/writing the correct number of items with the correct sizes.
+//
+// The current four known exchanges are:
+//
+// * Allocate Space:
+// Parent: { LLI_AllocateSpace, 8, Alignment, Size }
+// Child: { LLI_AllocationResult, 8, Address }
+//
+// * Load Data:
+// Parent: { LLI_LoadDataSection, 8+Size, Address, Data }
+// Child: { LLI_LoadComplete, 4, StatusCode }
+//
+// * Load Code:
+// Parent: { LLI_LoadCodeSection, 8+Size, Address, Code }
+// Child: { LLI_LoadComplete, 4, StatusCode }
+//
+// * Execute Code:
+// Parent: { LLI_Execute, 8, Address }
+// Child: { LLI_ExecutionResult, 4, Result }
+//
+// It is the responsibility of either side to check for correct headers,
+// sizes and payloads, since any inconsistency would misalign the pipe, and
+// result in data corruption.
enum LLIMessageType {
LLI_Error = -1,
LLI_ChildActive = 0, // Data = not used
- LLI_AllocateSpace, // Data = struct { uint_32t Align, uint_32t Size }
- LLI_AllocationResult, // Data = uint64_t AllocAddress (in Child memory space)
- LLI_LoadCodeSection, // Data = uint32_t Addr, followed by section contests
- LLI_LoadDataSection, // Data = uint32_t Addr, followed by section contents
- LLI_LoadComplete, // Data = not used
- LLI_Execute, // Data = Address of function to execute
- LLI_ExecutionResult, // Data = uint64_t Result
+ LLI_AllocateSpace, // Data = struct { uint32_t Align, uint_32t Size }
+ LLI_AllocationResult, // Data = uint64_t Address (child memory space)
+
+ LLI_LoadCodeSection, // Data = uint64_t Address, void * SectionData
+ LLI_LoadDataSection, // Data = uint64_t Address, void * SectionData
+ LLI_LoadResult, // Data = uint32_t LLIMessageStatus
+
+ LLI_Execute, // Data = uint64_t Address
+ LLI_ExecutionResult, // Data = uint32_t Result
+
LLI_Terminate // Data = not used
};
+enum LLIMessageStatus {
+ LLI_Status_Success = 0, // Operation succeeded
+ LLI_Status_NotAllocated, // Address+Size not allocated in child space
+ LLI_Status_IncompleteMsg // Size received doesn't match request
+};
+
} // end namespace llvm
#endif
diff --git a/tools/lli/Unix/RemoteTargetExternal.inc b/tools/lli/Unix/RemoteTargetExternal.inc
index 481c1d5156..ea8e4597d5 100644
--- a/tools/lli/Unix/RemoteTargetExternal.inc
+++ b/tools/lli/Unix/RemoteTargetExternal.inc
@@ -30,7 +30,7 @@ struct ConnectionData_t {
namespace llvm {
-void RemoteTargetExternal::create() {
+bool RemoteTargetExternal::create() {
int PipeFD[2][2];
pid_t ChildPID;
@@ -73,16 +73,53 @@ void RemoteTargetExternal::create() {
// Store the parent ends of the pipes
ConnectionData = (void*)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]);
- Receive(LLI_ChildActive);
+ // We must get Ack from the client (blocking read)
+ if (!Receive(LLI_ChildActive)) {
+ ErrorMsg += ", (RemoteTargetExternal::create) - Stopping process!";
+ stop();
+ return false;
+ }
+ }
+ return true;
+}
+
+static void ReportError(int rc, size_t Size, std::string &ErrorMsg) {
+ if (rc == -1) {
+ if (errno == EPIPE)
+ ErrorMsg += "pipe closed";
+ else if (errno == EINTR)
+ ErrorMsg += "interrupted";
+ else
+ ErrorMsg += "file descriptor error";
+ } else {
+ char Number[10] = { 0 };
+ ErrorMsg += "Expecting ";
+ sprintf(Number, "%d", (uint32_t)Size);
+ ErrorMsg += Number;
+ ErrorMsg += " bytes, Got ";
+ sprintf(Number, "%d", rc);
+ ErrorMsg += Number;
}
}
-int RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
- return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
+bool RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
+ int rc = write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
+ if (rc != -1 && (size_t)rc == Size)
+ return true;
+
+ ErrorMsg = "WriteBytes: ";
+ ReportError(rc, Size, ErrorMsg);
+ return false;
}
-int RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
- return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
+bool RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
+ int rc = read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
+ if (rc != -1 && (size_t)rc == Size)
+ return true;
+
+ ErrorMsg = "ReadBytes: ";
+ ReportError(rc, Size, ErrorMsg);
+ return false;
}
void RemoteTargetExternal::Wait() {
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index 3766f8c0ca..c6db51a2b0 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -685,7 +685,10 @@ int main(int argc, char **argv, char * const *envp) {
MM->setRemoteTarget(Target.get());
// Create the remote target.
- Target->create();
+ if (!Target->create()) {
+ errs() << "ERROR: " << Target->getErrorMsg() << "\n";
+ return EXIT_FAILURE;
+ }
// Since we're executing in a (at least simulated) remote address space,
// we can't use the ExecutionEngine::runFunctionAsMain(). We have to
@@ -702,7 +705,7 @@ int main(int argc, char **argv, char * const *envp) {
DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
<< format("%llx", Entry) << "\n");
- if (Target->executeCode(Entry, Result))
+ if (!Target->executeCode(Entry, Result))
errs() << "ERROR: " << Target->getErrorMsg() << "\n";
// Like static constructors, the remote target MCJIT support doesn't handle