| #include "llvm/Config/config.h" |
| #include "../RPCChannel.h" |
| #include "../RemoteTarget.h" |
| #include "../RemoteTargetMessage.h" |
| #include "llvm/Support/Memory.h" |
| #include <assert.h> |
| #include <map> |
| #include <stdint.h> |
| #include <string> |
| #include <vector> |
| |
| using namespace llvm; |
| |
| class LLIChildTarget { |
| public: |
| void initialize(); |
| LLIMessageType waitForIncomingMessage(); |
| void handleMessage(LLIMessageType messageType); |
| RemoteTarget *RT; |
| RPCChannel RPC; |
| |
| private: |
| // Incoming message handlers |
| void handleAllocateSpace(); |
| void handleLoadSection(bool IsCode); |
| void handleExecute(); |
| |
| // Outgoing message handlers |
| void sendChildActive(); |
| void sendAllocationResult(uint64_t Addr); |
| void sendLoadStatus(uint32_t Status); |
| void sendExecutionComplete(int Result); |
| |
| // OS-specific functions |
| void initializeConnection(); |
| int WriteBytes(const void *Data, size_t Size) { |
| return RPC.WriteBytes(Data, Size) ? Size : -1; |
| } |
| int ReadBytes(void *Data, size_t Size) { |
| return RPC.ReadBytes(Data, Size) ? Size : -1; |
| } |
| |
| // Communication handles (OS-specific) |
| void *ConnectionData; |
| }; |
| |
| int main() { |
| LLIChildTarget ThisChild; |
| ThisChild.RT = new RemoteTarget(); |
| ThisChild.initialize(); |
| LLIMessageType MsgType; |
| do { |
| MsgType = ThisChild.waitForIncomingMessage(); |
| ThisChild.handleMessage(MsgType); |
| } while (MsgType != LLI_Terminate && |
| MsgType != LLI_Error); |
| delete ThisChild.RT; |
| return 0; |
| } |
| |
| // Public methods |
| void LLIChildTarget::initialize() { |
| RPC.createClient(); |
| sendChildActive(); |
| } |
| |
| LLIMessageType LLIChildTarget::waitForIncomingMessage() { |
| int32_t MsgType = -1; |
| if (ReadBytes(&MsgType, 4) > 0) |
| return (LLIMessageType)MsgType; |
| return LLI_Error; |
| } |
| |
| void LLIChildTarget::handleMessage(LLIMessageType messageType) { |
| switch (messageType) { |
| case LLI_AllocateSpace: |
| handleAllocateSpace(); |
| break; |
| case LLI_LoadCodeSection: |
| handleLoadSection(true); |
| break; |
| case LLI_LoadDataSection: |
| handleLoadSection(false); |
| break; |
| case LLI_Execute: |
| handleExecute(); |
| break; |
| case LLI_Terminate: |
| RT->stop(); |
| break; |
| default: |
| // FIXME: Handle error! |
| break; |
| } |
| } |
| |
| // Incoming message handlers |
| void LLIChildTarget::handleAllocateSpace() { |
| // Read and verify the message data size. |
| uint32_t DataSize; |
| int rc = ReadBytes(&DataSize, 4); |
| (void)rc; |
| assert(rc == 4); |
| assert(DataSize == 8); |
| |
| // Read the message arguments. |
| uint32_t Alignment; |
| uint32_t AllocSize; |
| rc = ReadBytes(&Alignment, 4); |
| assert(rc == 4); |
| rc = ReadBytes(&AllocSize, 4); |
| assert(rc == 4); |
| |
| // Allocate the memory. |
| uint64_t Addr; |
| RT->allocateSpace(AllocSize, Alignment, Addr); |
| |
| // Send AllocationResult message. |
| sendAllocationResult(Addr); |
| } |
| |
| 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; |
| |
| if (!RT->isAllocatedMemory(Addr, BufferSize)) |
| return sendLoadStatus(LLI_Status_NotAllocated); |
| |
| // Read section data into previously allocated buffer |
| rc = ReadBytes((void*)Addr, BufferSize); |
| if (rc != (int)(BufferSize)) |
| return sendLoadStatus(LLI_Status_IncompleteMsg); |
| |
| // If IsCode, mark memory executable |
| if (IsCode) |
| sys::Memory::InvalidateInstructionCache((void *)Addr, BufferSize); |
| |
| // Send MarkLoadComplete message. |
| 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); |
| |
| // Read the target address. |
| uint64_t Addr; |
| rc = ReadBytes(&Addr, 8); |
| assert(rc == 8); |
| |
| // Call function |
| int32_t Result = -1; |
| RT->executeCode(Addr, Result); |
| |
| // Send ExecutionResult message. |
| sendExecutionComplete(Result); |
| } |
| |
| // 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. |
| uint32_t DataSize = 0; |
| rc = WriteBytes(&DataSize, 4); |
| assert(rc == 4); |
| } |
| |
| 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. |
| uint32_t DataSize = 8; |
| rc = WriteBytes(&DataSize, 4); |
| assert(rc == 4); |
| |
| // Write the allocated address. |
| rc = WriteBytes(&Addr, 8); |
| assert(rc == 8); |
| } |
| |
| void LLIChildTarget::sendLoadStatus(uint32_t Status) { |
| // Write the message type. |
| uint32_t MsgType = (uint32_t)LLI_LoadResult; |
| int rc = WriteBytes(&MsgType, 4); |
| (void)rc; |
| assert(rc == 4); |
| |
| // Write the data size. |
| uint32_t DataSize = 4; |
| rc = WriteBytes(&DataSize, 4); |
| assert(rc == 4); |
| |
| // Write the result. |
| rc = WriteBytes(&Status, 4); |
| assert(rc == 4); |
| } |
| |
| 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 = 4; |
| rc = WriteBytes(&DataSize, 4); |
| assert(rc == 4); |
| |
| // Write the result. |
| rc = WriteBytes(&Result, 4); |
| assert(rc == 4); |
| } |
| |
| #ifdef LLVM_ON_UNIX |
| #include "../Unix/RPCChannel.inc" |
| #endif |
| |
| #ifdef LLVM_ON_WIN32 |
| #include "../Windows/RPCChannel.inc" |
| #endif |