1 #include "llvm/Config/config.h" 2 #include "../RemoteTargetMessage.h" 3 #include <assert.h> 4 #include <map> 5 #include <stdint.h> 6 #include <string> 7 #include <vector> 8 9 using namespace llvm; 10 11 class LLIChildTarget { 12 public: 13 ~LLIChildTarget(); // OS-specific destructor 14 void initialize(); 15 LLIMessageType waitForIncomingMessage(); 16 void handleMessage(LLIMessageType messageType); 17 18 private: 19 // Incoming message handlers 20 void handleAllocateSpace(); 21 void handleLoadSection(bool IsCode); 22 void handleExecute(); 23 void handleTerminate(); 24 25 // Outgoing message handlers 26 void sendChildActive(); 27 void sendAllocationResult(uint64_t Addr); 28 void sendLoadStatus(uint32_t Status); 29 void sendExecutionComplete(int Result); 30 31 // OS-specific functions 32 void initializeConnection(); 33 int WriteBytes(const void *Data, size_t Size); 34 int ReadBytes(void *Data, size_t Size); 35 uint64_t allocate(uint32_t Alignment, uint32_t Size); 36 void makeSectionExecutable(uint64_t Addr, uint32_t Size); 37 void InvalidateInstructionCache(const void *Addr, size_t Len); 38 void releaseMemory(uint64_t Addr, uint32_t Size); 39 bool isAllocatedMemory(uint64_t Address, 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 (void)rc; 103 assert(rc == 4); 104 assert(DataSize == 8); 105 106 // Read the message arguments. 107 uint32_t Alignment; 108 uint32_t AllocSize; 109 rc = ReadBytes(&Alignment, 4); 110 assert(rc == 4); 111 rc = ReadBytes(&AllocSize, 4); 112 assert(rc == 4); 113 114 // Allocate the memory. 115 uint64_t Addr = allocate(Alignment, AllocSize); 116 117 // Send AllocationResult message. 118 sendAllocationResult(Addr); 119 } 120 121 void LLIChildTarget::handleLoadSection(bool IsCode) { 122 // Read the message data size. 123 uint32_t DataSize; 124 int rc = ReadBytes(&DataSize, 4); 125 (void)rc; 126 assert(rc == 4); 127 128 // Read the target load address. 129 uint64_t Addr; 130 rc = ReadBytes(&Addr, 8); 131 assert(rc == 8); 132 size_t BufferSize = DataSize - 8; 133 134 if (!isAllocatedMemory(Addr, BufferSize)) 135 return sendLoadStatus(LLI_Status_NotAllocated); 136 137 // Read section data into previously allocated buffer 138 rc = ReadBytes((void*)Addr, BufferSize); 139 if (rc != (int)(BufferSize)) 140 return sendLoadStatus(LLI_Status_IncompleteMsg); 141 142 // If IsCode, mark memory executable 143 if (IsCode) 144 makeSectionExecutable(Addr, BufferSize); 145 146 // Send MarkLoadComplete message. 147 sendLoadStatus(LLI_Status_Success); 148 } 149 150 void LLIChildTarget::handleExecute() { 151 // Read the message data size. 152 uint32_t DataSize; 153 int rc = ReadBytes(&DataSize, 4); 154 (void)rc; 155 assert(rc == 4); 156 assert(DataSize == 8); 157 158 // Read the target address. 159 uint64_t Addr; 160 rc = ReadBytes(&Addr, 8); 161 assert(rc == 8); 162 163 // Call function 164 int Result; 165 int (*fn)(void) = (int(*)(void))Addr; 166 Result = fn(); 167 168 // Send ExecutionResult message. 169 sendExecutionComplete(Result); 170 } 171 172 void LLIChildTarget::handleTerminate() { 173 // Release all allocated memory 174 AllocMapType::iterator Begin = m_AllocatedBufferMap.begin(); 175 AllocMapType::iterator End = m_AllocatedBufferMap.end(); 176 for (AllocMapType::iterator It = Begin; It != End; ++It) { 177 releaseMemory(It->first, It->second); 178 } 179 m_AllocatedBufferMap.clear(); 180 } 181 182 bool LLIChildTarget::isAllocatedMemory(uint64_t Address, uint32_t Size) { 183 uint64_t End = Address+Size; 184 AllocMapType::iterator ItBegin = m_AllocatedBufferMap.begin(); 185 AllocMapType::iterator ItEnd = m_AllocatedBufferMap.end(); 186 for (AllocMapType::iterator It = ItBegin; It != ItEnd; ++It) { 187 uint64_t A = It->first; 188 uint64_t E = A + It->second; 189 // Starts and finishes inside allocated region 190 if (Address >= A && End <= E) 191 return true; 192 } 193 return false; 194 } 195 196 // Outgoing message handlers 197 void LLIChildTarget::sendChildActive() { 198 // Write the message type. 199 uint32_t MsgType = (uint32_t)LLI_ChildActive; 200 int rc = WriteBytes(&MsgType, 4); 201 (void)rc; 202 assert(rc == 4); 203 204 // Write the data size. 205 uint32_t DataSize = 0; 206 rc = WriteBytes(&DataSize, 4); 207 assert(rc == 4); 208 } 209 210 void LLIChildTarget::sendAllocationResult(uint64_t Addr) { 211 // Write the message type. 212 uint32_t MsgType = (uint32_t)LLI_AllocationResult; 213 int rc = WriteBytes(&MsgType, 4); 214 (void)rc; 215 assert(rc == 4); 216 217 // Write the data size. 218 uint32_t DataSize = 8; 219 rc = WriteBytes(&DataSize, 4); 220 assert(rc == 4); 221 222 // Write the allocated address. 223 rc = WriteBytes(&Addr, 8); 224 assert(rc == 8); 225 } 226 227 void LLIChildTarget::sendLoadStatus(uint32_t Status) { 228 // Write the message type. 229 uint32_t MsgType = (uint32_t)LLI_LoadResult; 230 int rc = WriteBytes(&MsgType, 4); 231 (void)rc; 232 assert(rc == 4); 233 234 // Write the data size. 235 uint32_t DataSize = 4; 236 rc = WriteBytes(&DataSize, 4); 237 assert(rc == 4); 238 239 // Write the result. 240 rc = WriteBytes(&Status, 4); 241 assert(rc == 4); 242 } 243 244 void LLIChildTarget::sendExecutionComplete(int Result) { 245 // Write the message type. 246 uint32_t MsgType = (uint32_t)LLI_ExecutionResult; 247 int rc = WriteBytes(&MsgType, 4); 248 (void)rc; 249 assert(rc == 4); 250 251 252 // Write the data size. 253 uint32_t DataSize = 4; 254 rc = WriteBytes(&DataSize, 4); 255 assert(rc == 4); 256 257 // Write the result. 258 rc = WriteBytes(&Result, 4); 259 assert(rc == 4); 260 } 261 262 #ifdef LLVM_ON_UNIX 263 #include "Unix/ChildTarget.inc" 264 #endif 265 266 #ifdef LLVM_ON_WIN32 267 #include "Windows/ChildTarget.inc" 268 #endif 269