91bc56ed82
preserve our customizations, where necessary.
245 lines
5.5 KiB
C++
245 lines
5.5 KiB
C++
#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
|