diff --git a/tools/lli/ChildTarget/CMakeLists.txt b/tools/lli/ChildTarget/CMakeLists.txt index fd1ac24f044..6191fd60166 100644 --- a/tools/lli/ChildTarget/CMakeLists.txt +++ b/tools/lli/ChildTarget/CMakeLists.txt @@ -1,3 +1,6 @@ -add_llvm_tool(lli-child-target +set(LLVM_LINK_COMPONENTS support) + +add_llvm_executable(lli-child-target ChildTarget.cpp - ) + ../RemoteTarget.cpp +) diff --git a/tools/lli/ChildTarget/ChildTarget.cpp b/tools/lli/ChildTarget/ChildTarget.cpp index ca75beb8422..de264af2cdd 100644 --- a/tools/lli/ChildTarget/ChildTarget.cpp +++ b/tools/lli/ChildTarget/ChildTarget.cpp @@ -1,4 +1,6 @@ #include "llvm/Config/config.h" +#include "llvm/Support/Memory.h" +#include "../RemoteTarget.h" #include "../RemoteTargetMessage.h" #include #include @@ -14,13 +16,13 @@ public: void initialize(); LLIMessageType waitForIncomingMessage(); void handleMessage(LLIMessageType messageType); + RemoteTarget *RT; private: // Incoming message handlers void handleAllocateSpace(); void handleLoadSection(bool IsCode); void handleExecute(); - void handleTerminate(); // Outgoing message handlers void sendChildActive(); @@ -32,15 +34,6 @@ private: void initializeConnection(); int WriteBytes(const void *Data, size_t Size); int ReadBytes(void *Data, size_t Size); - uint64_t allocate(uint32_t Alignment, uint32_t Size); - void makeSectionExecutable(uint64_t Addr, uint32_t Size); - void InvalidateInstructionCache(const void *Addr, size_t Len); - void releaseMemory(uint64_t Addr, uint32_t Size); - bool isAllocatedMemory(uint64_t Address, uint32_t Size); - - // Store a map of allocated buffers to sizes. - typedef std::map AllocMapType; - AllocMapType m_AllocatedBufferMap; // Communication handles (OS-specific) void *ConnectionData; @@ -48,6 +41,7 @@ private: int main() { LLIChildTarget ThisChild; + ThisChild.RT = new RemoteTarget(); ThisChild.initialize(); LLIMessageType MsgType; do { @@ -55,6 +49,7 @@ int main() { ThisChild.handleMessage(MsgType); } while (MsgType != LLI_Terminate && MsgType != LLI_Error); + delete ThisChild.RT; return 0; } @@ -86,7 +81,7 @@ void LLIChildTarget::handleMessage(LLIMessageType messageType) { handleExecute(); break; case LLI_Terminate: - handleTerminate(); + RT->stop(); break; default: // FIXME: Handle error! @@ -112,7 +107,8 @@ void LLIChildTarget::handleAllocateSpace() { assert(rc == 4); // Allocate the memory. - uint64_t Addr = allocate(Alignment, AllocSize); + uint64_t Addr; + RT->allocateSpace(AllocSize, Alignment, Addr); // Send AllocationResult message. sendAllocationResult(Addr); @@ -131,7 +127,7 @@ void LLIChildTarget::handleLoadSection(bool IsCode) { assert(rc == 8); size_t BufferSize = DataSize - 8; - if (!isAllocatedMemory(Addr, BufferSize)) + if (!RT->isAllocatedMemory(Addr, BufferSize)) return sendLoadStatus(LLI_Status_NotAllocated); // Read section data into previously allocated buffer @@ -141,7 +137,7 @@ void LLIChildTarget::handleLoadSection(bool IsCode) { // If IsCode, mark memory executable if (IsCode) - makeSectionExecutable(Addr, BufferSize); + sys::Memory::InvalidateInstructionCache((void *)Addr, BufferSize); // Send MarkLoadComplete message. sendLoadStatus(LLI_Status_Success); @@ -161,38 +157,13 @@ void LLIChildTarget::handleExecute() { assert(rc == 8); // Call function - int Result; - int (*fn)(void) = (int(*)(void))Addr; - Result = fn(); + int32_t Result = -1; + RT->executeCode(Addr, Result); // Send ExecutionResult message. sendExecutionComplete(Result); } -void LLIChildTarget::handleTerminate() { - // Release all allocated memory - AllocMapType::iterator Begin = m_AllocatedBufferMap.begin(); - AllocMapType::iterator End = m_AllocatedBufferMap.end(); - for (AllocMapType::iterator It = Begin; It != End; ++It) { - releaseMemory(It->first, It->second); - } - m_AllocatedBufferMap.clear(); -} - -bool LLIChildTarget::isAllocatedMemory(uint64_t Address, uint32_t Size) { - uint64_t End = Address+Size; - AllocMapType::iterator ItBegin = m_AllocatedBufferMap.begin(); - AllocMapType::iterator ItEnd = m_AllocatedBufferMap.end(); - for (AllocMapType::iterator It = ItBegin; It != ItEnd; ++It) { - uint64_t A = It->first; - uint64_t E = A + It->second; - // Starts and finishes inside allocated region - if (Address >= A && End <= E) - return true; - } - return false; -} - // Outgoing message handlers void LLIChildTarget::sendChildActive() { // Write the message type. diff --git a/tools/lli/ChildTarget/Unix/ChildTarget.inc b/tools/lli/ChildTarget/Unix/ChildTarget.inc index c71e422c1ac..67a24ece965 100644 --- a/tools/lli/ChildTarget/Unix/ChildTarget.inc +++ b/tools/lli/ChildTarget/Unix/ChildTarget.inc @@ -16,28 +16,6 @@ #include #include -#ifdef HAVE_SYS_MMAN_H -#include -#endif - -#ifdef __APPLE__ -#include -#endif - -#if defined(__mips__) -# if defined(__OpenBSD__) -# include -# else -# include -# endif -#endif - -#ifdef __APPLE__ -extern "C" void sys_icache_invalidate(const void *Addr, size_t len); -#else -extern "C" void __clear_cache(void *, void*); -#endif - namespace { struct ConnectionData_t { @@ -66,101 +44,3 @@ int LLIChildTarget::WriteBytes(const void *Data, size_t Size) { int LLIChildTarget::ReadBytes(void *Data, size_t Size) { return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size); } - -// The functions below duplicate functionality that is implemented in -// Support/Memory.cpp with the goal of avoiding a dependency on any -// llvm libraries. - -uint64_t LLIChildTarget::allocate(uint32_t Alignment, uint32_t Size) { - if (!Alignment) - Alignment = 16; - - static const size_t PageSize = getpagesize(); - const size_t NumPages = (Size+PageSize-1)/PageSize; - Size = NumPages*PageSize; - - int fd = -1; -#ifdef NEED_DEV_ZERO_FOR_MMAP - static int zero_fd = open("/dev/zero", O_RDWR); - if (zero_fd == -1) - return 0; - fd = zero_fd; -#endif - - int MMFlags = MAP_PRIVATE | -#ifdef HAVE_MMAP_ANONYMOUS - MAP_ANONYMOUS -#else - MAP_ANON -#endif - ; // Ends statement above - - uint64_t Addr = (uint64_t)::mmap(0, Size, PROT_READ | PROT_WRITE, MMFlags, fd, 0); - if (Addr == (uint64_t)MAP_FAILED) - return 0; - - // Align the address. - Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); - - m_AllocatedBufferMap[Addr] = Size; - - // Return aligned address - return Addr; -} - -void LLIChildTarget::makeSectionExecutable(uint64_t Addr, uint32_t Size) { - // FIXME: We have to mark the memory as RWX because multiple code chunks may - // be on the same page. The RemoteTarget interface should be changed to - // work around that. - int Result = ::mprotect((void*)Addr, Size, PROT_READ | PROT_WRITE | PROT_EXEC); - if (Result != 0) - InvalidateInstructionCache((const void *)Addr, Size); -} - -/// InvalidateInstructionCache - Before the JIT can run a block of code -/// that has been emitted it must invalidate the instruction cache on some -/// platforms. -void LLIChildTarget::InvalidateInstructionCache(const void *Addr, - size_t Len) { - -// icache invalidation for PPC and ARM. -#if defined(__APPLE__) - -# if (defined(__POWERPC__) || defined (__ppc__) || \ - defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__) - sys_icache_invalidate(const_cast(Addr), Len); -# endif - -#else - -# if (defined(__POWERPC__) || defined (__ppc__) || \ - defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__) - const size_t LineSize = 32; - - const intptr_t Mask = ~(LineSize - 1); - const intptr_t StartLine = ((intptr_t) Addr) & Mask; - const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask; - - for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) - asm volatile("dcbf 0, %0" : : "r"(Line)); - asm volatile("sync"); - - for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) - asm volatile("icbi 0, %0" : : "r"(Line)); - asm volatile("isync"); -# elif defined(__arm__) && defined(__GNUC__) - // FIXME: Can we safely always call this for __GNUC__ everywhere? - const char *Start = static_cast(Addr); - const char *End = Start + Len; - __clear_cache(const_cast(Start), const_cast(End)); -# elif defined(__mips__) - const char *Start = static_cast(Addr); - cacheflush(const_cast(Start), Len, BCACHE); -# endif - -#endif // end apple -} - -void LLIChildTarget::releaseMemory(uint64_t Addr, uint32_t Size) { - ::munmap((void*)Addr, Size); -} diff --git a/tools/lli/ChildTarget/Windows/ChildTarget.inc b/tools/lli/ChildTarget/Windows/ChildTarget.inc index 45db2b0a808..bea0947b7ec 100644 --- a/tools/lli/ChildTarget/Windows/ChildTarget.inc +++ b/tools/lli/ChildTarget/Windows/ChildTarget.inc @@ -32,13 +32,3 @@ int LLIChildTarget::ReadBytes(void *Data, size_t Size) { uint64_t LLIChildTarget::allocate(uint32_t Alignment, uint32_t Size) { return 0; } - -void LLIChildTarget::makeSectionExecutable(uint64_t Addr, uint32_t Size) { -} - -void LLIChildTarget::InvalidateInstructionCache(const void *Addr, - size_t Len) { -} - -void LLIChildTarget::releaseMemory(uint64_t Addr, uint32_t Size) { -} diff --git a/tools/lli/RemoteTarget.cpp b/tools/lli/RemoteTarget.cpp index 9631ef7aac2..f07534d161a 100644 --- a/tools/lli/RemoteTarget.cpp +++ b/tools/lli/RemoteTarget.cpp @@ -62,6 +62,7 @@ bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment, return false; } Address = reinterpret_cast(Mem.base()); + Allocations.push_back(Mem); return true; } diff --git a/tools/lli/RemoteTarget.h b/tools/lli/RemoteTarget.h index a7d4e59e3bf..44e649e6e14 100644 --- a/tools/lli/RemoteTarget.h +++ b/tools/lli/RemoteTarget.h @@ -27,7 +27,8 @@ namespace llvm { class RemoteTarget { bool IsRunning; - SmallVector Allocations; + typedef SmallVector AllocMapType; + AllocMapType Allocations; protected: std::string ErrorMsg; @@ -47,6 +48,18 @@ public: unsigned Alignment, uint64_t &Address); + bool isAllocatedMemory(uint64_t Address, uint32_t Size) { + uint64_t AddressEnd = Address + Size; + for (AllocMapType::const_iterator I = Allocations.begin(), + E = Allocations.end(); + I != E; ++I) { + if (Address >= (uint64_t)I->base() && + AddressEnd <= (uint64_t)I->base() + I->size()) + return true; + } + return false; + } + /// Load data into the target address space. /// /// @param Address Destination address in the target process.