1 #include "llvm/Config/config.h" 2 3 #include "../RemoteTargetMessage.h" 4 #include <assert.h> 5 #include <map> 6 #include <stdint.h> 7 #include <string> 8 #include <vector> 9 10 using namespace llvm; 11 12 class LLIChildTarget { 13 public: 14 ~LLIChildTarget(); // OS-specific destructor 15 void initialize(); 16 LLIMessageType waitForIncomingMessage(); 17 void handleMessage(LLIMessageType messageType); 18 19 private: 20 // Incoming message handlers 21 void handleAllocateSpace(); 22 void handleLoadSection(bool IsCode); 23 void handleExecute(); 24 void handleTerminate(); 25 26 // Outgoing message handlers 27 void sendChildActive(); 28 void sendAllocationResult(uint64_t Addr); 29 void sendLoadComplete(); 30 void sendExecutionComplete(uint64_t Result); 31 32 // OS-specific functions 33 void initializeConnection(); 34 int WriteBytes(const void *Data, size_t Size); 35 int ReadBytes(void *Data, size_t Size); 36 uint64_t allocate(uint32_t Alignment, uint32_t Size); 37 void makeSectionExecutable(uint64_t Addr, uint32_t Size); 38 void InvalidateInstructionCache(const void *Addr, size_t Len); 39 void releaseMemory(uint64_t Addr, uint32_t Size); 40 41 // Store a map of allocated buffers to sizes. 42 typedef std::map<uint64_t, uint32_t> AllocMapType; 43 AllocMapType m_AllocatedBufferMap; 44 45 // Communication handles (OS-specific) 46 void *ConnectionData; 47 }; 48 49 int main() { 50 LLIChildTarget ThisChild; 51 ThisChild.initialize(); 52 LLIMessageType MsgType; 53 do { 54 MsgType = ThisChild.waitForIncomingMessage(); 55 ThisChild.handleMessage(MsgType); 56 } while (MsgType != LLI_Terminate && 57 MsgType != LLI_Error); 58 return 0; 59 } 60 61 // Public methods 62 void LLIChildTarget::initialize() { 63 initializeConnection(); 64 sendChildActive(); 65 } 66 67 LLIMessageType LLIChildTarget::waitForIncomingMessage() { 68 int32_t MsgType = -1; 69 if (ReadBytes(&MsgType, 4) > 0) 70 return (LLIMessageType)MsgType; 71 return LLI_Error; 72 } 73 74 void LLIChildTarget::handleMessage(LLIMessageType messageType) { 75 switch (messageType) { 76 case LLI_AllocateSpace: 77 handleAllocateSpace(); 78 break; 79 case LLI_LoadCodeSection: 80 handleLoadSection(true); 81 break; 82 case LLI_LoadDataSection: 83 handleLoadSection(false); 84 break; 85 case LLI_Execute: 86 handleExecute(); 87 break; 88 case LLI_Terminate: 89 handleTerminate(); 90 break; 91 default: 92 // FIXME: Handle error! 93 break; 94 } 95 } 96 97 // Incoming message handlers 98 void LLIChildTarget::handleAllocateSpace() { 99 // Read and verify the message data size. 100 uint32_t DataSize; 101 int rc = ReadBytes(&DataSize, 4); 102 assert(rc == 4); 103 assert(DataSize == 8); 104 105 // Read the message arguments. 106 uint32_t Alignment; 107 uint32_t AllocSize; 108 rc = ReadBytes(&Alignment, 4); 109 assert(rc == 4); 110 rc = ReadBytes(&AllocSize, 4); 111 assert(rc == 4); 112 113 // Allocate the memory. 114 uint64_t Addr = allocate(Alignment, AllocSize); 115 116 // Send AllocationResult message. 117 sendAllocationResult(Addr); 118 } 119 120 void LLIChildTarget::handleLoadSection(bool IsCode) { 121 // Read the message data size. 122 uint32_t DataSize; 123 int rc = ReadBytes(&DataSize, 4); 124 assert(rc == 4); 125 126 // Read the target load address. 127 uint64_t Addr; 128 rc = ReadBytes(&Addr, 8); 129 assert(rc == 8); 130 131 size_t BufferSize = DataSize - 8; 132 133 // FIXME: Verify that this is in allocated space 134 135 // Read section data into previously allocated buffer 136 rc = ReadBytes((void*)Addr, DataSize - 8); 137 assert(rc == (int)(BufferSize)); 138 139 // If IsCode, mark memory executable 140 if (IsCode) 141 makeSectionExecutable(Addr, BufferSize); 142 143 // Send MarkLoadComplete message. 144 sendLoadComplete(); 145 } 146 147 void LLIChildTarget::handleExecute() { 148 // Read the message data size. 149 uint32_t DataSize; 150 int rc = ReadBytes(&DataSize, 4); 151 assert(rc == 4); 152 assert(DataSize == 8); 153 154 // Read the target address. 155 uint64_t Addr; 156 rc = ReadBytes(&Addr, 8); 157 assert(rc == 8); 158 159 // Call function 160 int Result; 161 int (*fn)(void) = (int(*)(void))Addr; 162 Result = fn(); 163 164 // Send ExecutionResult message. 165 sendExecutionComplete((int64_t)Result); 166 } 167 168 void LLIChildTarget::handleTerminate() { 169 // Release all allocated memory 170 AllocMapType::iterator Begin = m_AllocatedBufferMap.begin(); 171 AllocMapType::iterator End = m_AllocatedBufferMap.end(); 172 for (AllocMapType::iterator It = Begin; It != End; ++It) { 173 releaseMemory(It->first, It->second); 174 } 175 m_AllocatedBufferMap.clear(); 176 } 177 178 // Outgoing message handlers 179 void LLIChildTarget::sendChildActive() { 180 // Write the message type. 181 uint32_t MsgType = (uint32_t)LLI_ChildActive; 182 int rc = WriteBytes(&MsgType, 4); 183 assert(rc == 4); 184 185 // Write the data size. 186 uint32_t DataSize = 0; 187 rc = WriteBytes(&DataSize, 4); 188 assert(rc == 4); 189 } 190 191 void LLIChildTarget::sendAllocationResult(uint64_t Addr) { 192 // Write the message type. 193 uint32_t MsgType = (uint32_t)LLI_AllocationResult; 194 int rc = WriteBytes(&MsgType, 4); 195 assert(rc == 4); 196 197 // Write the data size. 198 uint32_t DataSize = 8; 199 rc = WriteBytes(&DataSize, 4); 200 assert(rc == 4); 201 202 // Write the allocated address. 203 rc = WriteBytes(&Addr, 8); 204 assert(rc == 8); 205 } 206 207 void LLIChildTarget::sendLoadComplete() { 208 // Write the message type. 209 uint32_t MsgType = (uint32_t)LLI_LoadComplete; 210 int rc = WriteBytes(&MsgType, 4); 211 assert(rc == 4); 212 213 // Write the data size. 214 uint32_t DataSize = 0; 215 rc = WriteBytes(&DataSize, 4); 216 assert(rc == 4); 217 } 218 219 void LLIChildTarget::sendExecutionComplete(uint64_t Result) { 220 // Write the message type. 221 uint32_t MsgType = (uint32_t)LLI_ExecutionResult; 222 int rc = WriteBytes(&MsgType, 4); 223 assert(rc == 4); 224 225 226 // Write the data size. 227 uint32_t DataSize = 8; 228 rc = WriteBytes(&DataSize, 4); 229 assert(rc == 4); 230 231 // Write the result. 232 rc = WriteBytes(&Result, 8); 233 assert(rc == 8); 234 } 235 236 #ifdef LLVM_ON_UNIX 237 #include "Unix/ChildTarget.inc" 238 #endif 239 240 #ifdef LLVM_ON_WIN32 241 #include "Windows/ChildTarget.inc" 242 #endif 243