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 (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 assert(rc == 4); 126 127 // Read the target load address. 128 uint64_t Addr; 129 rc = ReadBytes(&Addr, 8); 130 assert(rc == 8); 131 132 size_t BufferSize = DataSize - 8; 133 134 // FIXME: Verify that this is in allocated space 135 136 // Read section data into previously allocated buffer 137 rc = ReadBytes((void*)Addr, DataSize - 8); 138 assert(rc == (int)(BufferSize)); 139 140 // If IsCode, mark memory executable 141 if (IsCode) 142 makeSectionExecutable(Addr, BufferSize); 143 144 // Send MarkLoadComplete message. 145 sendLoadComplete(); 146 } 147 148 void LLIChildTarget::handleExecute() { 149 // Read the message data size. 150 uint32_t DataSize; 151 int rc = ReadBytes(&DataSize, 4); 152 assert(rc == 4); 153 assert(DataSize == 8); 154 155 // Read the target address. 156 uint64_t Addr; 157 rc = ReadBytes(&Addr, 8); 158 assert(rc == 8); 159 160 // Call function 161 int Result; 162 int (*fn)(void) = (int(*)(void))Addr; 163 Result = fn(); 164 165 // Send ExecutionResult message. 166 sendExecutionComplete((int64_t)Result); 167 } 168 169 void LLIChildTarget::handleTerminate() { 170 // Release all allocated memory 171 AllocMapType::iterator Begin = m_AllocatedBufferMap.begin(); 172 AllocMapType::iterator End = m_AllocatedBufferMap.end(); 173 for (AllocMapType::iterator It = Begin; It != End; ++It) { 174 releaseMemory(It->first, It->second); 175 } 176 m_AllocatedBufferMap.clear(); 177 } 178 179 // Outgoing message handlers 180 void LLIChildTarget::sendChildActive() { 181 // Write the message type. 182 uint32_t MsgType = (uint32_t)LLI_ChildActive; 183 int rc = WriteBytes(&MsgType, 4); 184 assert(rc == 4); 185 186 // Write the data size. 187 uint32_t DataSize = 0; 188 rc = WriteBytes(&DataSize, 4); 189 assert(rc == 4); 190 } 191 192 void LLIChildTarget::sendAllocationResult(uint64_t Addr) { 193 // Write the message type. 194 uint32_t MsgType = (uint32_t)LLI_AllocationResult; 195 int rc = WriteBytes(&MsgType, 4); 196 assert(rc == 4); 197 198 // Write the data size. 199 uint32_t DataSize = 8; 200 rc = WriteBytes(&DataSize, 4); 201 assert(rc == 4); 202 203 // Write the allocated address. 204 rc = WriteBytes(&Addr, 8); 205 assert(rc == 8); 206 } 207 208 void LLIChildTarget::sendLoadComplete() { 209 // Write the message type. 210 uint32_t MsgType = (uint32_t)LLI_LoadComplete; 211 int rc = WriteBytes(&MsgType, 4); 212 assert(rc == 4); 213 214 // Write the data size. 215 uint32_t DataSize = 0; 216 rc = WriteBytes(&DataSize, 4); 217 assert(rc == 4); 218 } 219 220 void LLIChildTarget::sendExecutionComplete(uint64_t Result) { 221 // Write the message type. 222 uint32_t MsgType = (uint32_t)LLI_ExecutionResult; 223 int rc = WriteBytes(&MsgType, 4); 224 assert(rc == 4); 225 226 227 // Write the data size. 228 uint32_t DataSize = 8; 229 rc = WriteBytes(&DataSize, 4); 230 assert(rc == 4); 231 232 // Write the result. 233 rc = WriteBytes(&Result, 8); 234 assert(rc == 8); 235 } 236 237 #ifdef LLVM_ON_UNIX 238 #include "Unix/ChildTarget.inc" 239 #endif 240 241 #ifdef LLVM_ON_WIN32 242 #include "Windows/ChildTarget.inc" 243 #endif 244