[llvm] r199261 - Sanitize MCJIT remote execution
Jim Grosbach
grosbach at apple.com
Tue Jan 14 15:00:05 PST 2014
Woohoo! Excellent.
-jim
On Jan 14, 2014, at 2:43 PM, Renato Golin <renato.golin at linaro.org> wrote:
> Author: rengolin
> Date: Tue Jan 14 16:43:43 2014
> New Revision: 199261
>
> URL: http://llvm.org/viewvc/llvm-project?rev=199261&view=rev
> Log:
> 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.
>
> Modified:
> llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp
> llvm/trunk/tools/lli/RemoteMemoryManager.cpp
> llvm/trunk/tools/lli/RemoteTarget.cpp
> llvm/trunk/tools/lli/RemoteTarget.h
> llvm/trunk/tools/lli/RemoteTargetExternal.cpp
> llvm/trunk/tools/lli/RemoteTargetExternal.h
> llvm/trunk/tools/lli/RemoteTargetMessage.h
> llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc
> llvm/trunk/tools/lli/lli.cpp
>
> Modified: llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp?rev=199261&r1=199260&r2=199261&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp (original)
> +++ llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp Tue Jan 14 16:43:43 2014
> @@ -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(b
> // 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::sendAllocationResul
> // 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::sendAllocationResul
> 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
>
> Modified: llvm/trunk/tools/lli/RemoteMemoryManager.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteMemoryManager.cpp?rev=199261&r1=199260&r2=199261&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lli/RemoteMemoryManager.cpp (original)
> +++ llvm/trunk/tools/lli/RemoteMemoryManager.cpp Tue Jan 14 16:43:43 2014
> @@ -129,7 +129,7 @@ void RemoteMemoryManager::notifyObjectLo
>
> // 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
> 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");
> }
>
> Modified: llvm/trunk/tools/lli/RemoteTarget.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTarget.cpp?rev=199261&r1=199260&r2=199261&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lli/RemoteTarget.cpp (original)
> +++ llvm/trunk/tools/lli/RemoteTarget.cpp Tue Jan 14 16:43:43 2014
> @@ -56,34 +56,35 @@ bool RemoteTarget::allocateSpace(size_t
> 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() {
>
> Modified: llvm/trunk/tools/lli/RemoteTarget.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTarget.h?rev=199261&r1=199260&r2=199261&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lli/RemoteTarget.h (original)
> +++ llvm/trunk/tools/lli/RemoteTarget.h Tue Jan 14 16:43:43 2014
> @@ -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.
>
> Modified: llvm/trunk/tools/lli/RemoteTargetExternal.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetExternal.cpp?rev=199261&r1=199260&r2=199261&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lli/RemoteTargetExternal.cpp (original)
> +++ llvm/trunk/tools/lli/RemoteTargetExternal.cpp Tue Jan 14 16:43:43 2014
> @@ -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;
> -}
> -
> -bool RemoteTargetExternal::executeCode(uint64_t Address, int &RetVal) {
> - SendExecute(Address);
> -
> - Receive(LLI_ExecutionResult, RetVal);
> - 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, 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.");
> -
> - rc = WriteBytes(&Alignment, 4);
> - assert(rc == 4 && "Error writing alignment data.");
> -
> - rc = WriteBytes(&Size, 4);
> - assert(rc == 4 && "Error writing size data.");
> +bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
> + if (!SendHeader(LLI_AllocateSpace)) {
> + ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
> + return false;
> + }
> +
> + AppendWrite((const void *)&Alignment, 4);
> + AppendWrite((const void *)&Size, 4);
> +
> + 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.");
> -
> - rc = WriteBytes(&Addr, 8);
> - assert(rc == 8 && "Error writing data.");
> -
> - rc = WriteBytes(Data, Size);
> - assert(rc == (int)Size && "Error writing data.");
> -}
> -
> -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.");
> -
> - uint32_t DataSize = 8;
> - rc = WriteBytes(&DataSize, 4);
> - assert(rc == 4 && "Error writing data size.");
> -
> - rc = WriteBytes(&Addr, 8);
> - assert(rc == 8 && "Error writing data.");
> -}
> -
> -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.");
> -
> - // No data or data size is sent with Terminate
> + LLIMessageType MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
> + if (!SendHeader(MsgType)) {
> + ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
> + return false;
> + }
> +
> + AppendWrite((const void *)&Addr, 8);
> + AppendWrite(Data, Size);
> +
> + if (!SendPayload()) {
> + ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
> + return false;
> + }
> + return true;
> +}
> +
> +bool RemoteTargetExternal::SendExecute(uint64_t Addr) {
> + if (!SendHeader(LLI_Execute)) {
> + ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
> + return false;
> + }
> +
> + AppendWrite((const void *)&Addr, 8);
> +
> + if (!SendPayload()) {
> + ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
> + return false;
> + }
> + return true;
> }
>
> -
> -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::SendTerminate() {
> + return SendHeader(LLI_Terminate);
> + // No data or data size is sent with Terminate
> }
>
> -void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, int &Data) {
> - uint64_t Temp;
> - Receive(ExpectedMsgType, Temp);
> - Data = (int)(int64_t)Temp;
> -}
> +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;
> +}
> +
> +bool RemoteTargetExternal::ReceiveHeader(LLIMessageType ExpectedMsgType) {
> + assert(ReceiveData.empty() && Sizes.empty() &&
> + "Payload vector not empty to receive header");
>
> -void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, uint64_t &Data) {
> - int rc;
> - (void)rc;
> + // 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.");
> -
> - rc = ReadBytes(&Data, 8);
> - assert(DataSize == 8 && "Error: unexpected data.");
> + 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;
> +}
> +
> +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
>
> Modified: llvm/trunk/tools/lli/RemoteTargetExternal.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetExternal.h?rev=199261&r1=199260&r2=199261&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lli/RemoteTargetExternal.h (original)
> +++ llvm/trunk/tools/lli/RemoteTargetExternal.h Tue Jan 14 16:43:43 2014
> @@ -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();
> };
>
>
> Modified: llvm/trunk/tools/lli/RemoteTargetMessage.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetMessage.h?rev=199261&r1=199260&r2=199261&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lli/RemoteTargetMessage.h (original)
> +++ llvm/trunk/tools/lli/RemoteTargetMessage.h Tue Jan 14 16:43:43 2014
> @@ -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
>
> Modified: llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc?rev=199261&r1=199260&r2=199261&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc (original)
> +++ llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc Tue Jan 14 16:43:43 2014
> @@ -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() {
>
> Modified: llvm/trunk/tools/lli/lli.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/lli.cpp?rev=199261&r1=199260&r2=199261&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lli/lli.cpp (original)
> +++ llvm/trunk/tools/lli/lli.cpp Tue Jan 14 16:43:43 2014
> @@ -685,7 +685,10 @@ int main(int argc, char **argv, char * c
> 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 * c
> 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
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list