mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-03 14:21:30 +00:00 
			
		
		
		
	In release builds this is actually possible as without asserts there is no testing of the actual read bytes and the variables could be partially uninitialized. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224114 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			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 = 0;
 | 
						|
  int rc = ReadBytes(&DataSize, 4);
 | 
						|
  (void)rc;
 | 
						|
  assert(rc == 4);
 | 
						|
  assert(DataSize == 8);
 | 
						|
 | 
						|
  // Read the message arguments.
 | 
						|
  uint32_t Alignment = 0;
 | 
						|
  uint32_t AllocSize = 0;
 | 
						|
  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 = 0;
 | 
						|
  int rc = ReadBytes(&DataSize, 4);
 | 
						|
  (void)rc;
 | 
						|
  assert(rc == 4);
 | 
						|
 | 
						|
  // Read the target load address.
 | 
						|
  uint64_t Addr = 0;
 | 
						|
  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 = 0;
 | 
						|
  int rc = ReadBytes(&DataSize, 4);
 | 
						|
  (void)rc;
 | 
						|
  assert(rc == 4);
 | 
						|
  assert(DataSize == 8);
 | 
						|
 | 
						|
  // Read the target address.
 | 
						|
  uint64_t Addr = 0;
 | 
						|
  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
 |