RTDyldMemoryManager.cpp revision 263508
118316Swollman//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===// 218316Swollman// 318316Swollman// The LLVM Compiler Infrastructure 418316Swollman// 518316Swollman// This file is distributed under the University of Illinois Open Source 618316Swollman// License. See LICENSE.TXT for details. 718316Swollman// 818316Swollman//===----------------------------------------------------------------------===// 918316Swollman// 1018316Swollman// Implementation of the runtime dynamic memory manager base class. 1118316Swollman// 1218316Swollman//===----------------------------------------------------------------------===// 1318316Swollman 1418316Swollman#include "llvm/Config/config.h" 1518316Swollman#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" 1618316Swollman#include "llvm/Support/DynamicLibrary.h" 1718316Swollman#include "llvm/Support/ErrorHandling.h" 1818316Swollman 1918316Swollman#include <cstdlib> 2018316Swollman 2118316Swollman#ifdef __linux__ 2218316Swollman // These includes used by RTDyldMemoryManager::getPointerToNamedFunction() 2318316Swollman // for Glibc trickery. See comments in this function for more information. 2418316Swollman #ifdef HAVE_SYS_STAT_H 2518316Swollman #include <sys/stat.h> 2618316Swollman #endif 2718316Swollman #include <fcntl.h> 2846303Smarkm #include <unistd.h> 2950476Speter#endif 3018316Swollman 3118316Swollmannamespace llvm { 3246303Smarkm 3346303SmarkmRTDyldMemoryManager::~RTDyldMemoryManager() {} 34126250Sbms 3546303Smarkm// Determine whether we can register EH tables. 36126250Sbms#if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \ 37126250Sbms !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)) 38126250Sbms#define HAVE_EHTABLE_SUPPORT 1 39126250Sbms#else 40126250Sbms#define HAVE_EHTABLE_SUPPORT 0 4118316Swollman#endif 4218316Swollman 4319880Swollman#if HAVE_EHTABLE_SUPPORT 4419880Swollmanextern "C" void __register_frame(void*); 4546303Smarkmextern "C" void __deregister_frame(void*); 4619880Swollman#else 4719880Swollman// The building compiler does not have __(de)register_frame but 4818316Swollman// it may be found at runtime in a dynamically-loaded library. 4918316Swollman// For example, this happens when building LLVM with Visual C++ 5018316Swollman// but using the MingW runtime. 5118316Swollmanvoid __register_frame(void *p) { 5218316Swollman static bool Searched = false; 5318316Swollman static void *rf = 0; 5419880Swollman 5518316Swollman if (!Searched) { 5618316Swollman Searched = true; 5719880Swollman rf = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol( 58148726Sstefanf "__register_frame"); 59148726Sstefanf } 6020339Swollman if (rf) 6120339Swollman ((void (*)(void *))rf)(p); 6219880Swollman} 6319880Swollman 6419880Swollmanvoid __deregister_frame(void *p) { 6519880Swollman static bool Searched = false; 6620339Swollman static void *df = 0; 6720339Swollman 6820339Swollman if (!Searched) { 6920339Swollman Searched = true; 7020339Swollman df = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol( 7118316Swollman "__deregister_frame"); 7218316Swollman } 7318316Swollman if (df) 7418316Swollman ((void (*)(void *))df)(p); 7518316Swollman} 7618316Swollman#endif 7718316Swollman 7818316Swollman#ifdef __APPLE__ 7918316Swollman 8018316Swollmanstatic const char *processFDE(const char *Entry, bool isDeregister) { 8118316Swollman const char *P = Entry; 8218316Swollman uint32_t Length = *((const uint32_t *)P); 8318316Swollman P += 4; 84148726Sstefanf uint32_t Offset = *((const uint32_t *)P); 8518316Swollman if (Offset != 0) { 8619880Swollman if (isDeregister) 8719880Swollman __deregister_frame(const_cast<char *>(Entry)); 8819880Swollman else 8919880Swollman __register_frame(const_cast<char *>(Entry)); 9019880Swollman } 9119880Swollman return P + Length; 9219880Swollman} 9319880Swollman 9419880Swollman// This implementation handles frame registration for local targets. 9519880Swollman// Memory managers for remote targets should re-implement this function 9619880Swollman// and use the LoadAddr parameter. 9719880Swollmanvoid RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, 9819880Swollman uint64_t LoadAddr, 99190713Sphk size_t Size) { 10019880Swollman // On OS X OS X __register_frame takes a single FDE as an argument. 10119880Swollman // See http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061768.html 10219880Swollman const char *P = (const char *)Addr; 10319880Swollman const char *End = P + Size; 10419880Swollman do { 10519880Swollman P = processFDE(P, false); 10620606Swollman } while(P != End); 10720606Swollman} 10820606Swollman 10920606Swollmanvoid RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr, 11020606Swollman uint64_t LoadAddr, 11120606Swollman size_t Size) { 11220606Swollman const char *P = (const char *)Addr; 11320606Swollman const char *End = P + Size; 11420606Swollman do { 11520606Swollman P = processFDE(P, true); 11620606Swollman } while(P != End); 11720606Swollman} 11820606Swollman 11919880Swollman#else 12019880Swollman 12119880Swollmanvoid RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, 12219880Swollman uint64_t LoadAddr, 12319880Swollman size_t Size) { 12419880Swollman // On Linux __register_frame takes a single argument: 12519880Swollman // a pointer to the start of the .eh_frame section. 12619880Swollman 12719880Swollman // How can it find the end? Because crtendS.o is linked 12818316Swollman // in and it has an .eh_frame section with four zero chars. 12918316Swollman __register_frame(Addr); 13018316Swollman} 13118316Swollman 13218316Swollmanvoid RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr, 13318316Swollman uint64_t LoadAddr, 13418316Swollman size_t Size) { 13518316Swollman __deregister_frame(Addr); 13619880Swollman} 13719880Swollman 13818316Swollman#endif 13919880Swollman 14018316Swollmanstatic int jit_noop() { 14118316Swollman return 0; 14219880Swollman} 14346303Smarkm 14418316Swollman// ARM math functions are statically linked on Android from libgcc.a, but not 14518316Swollman// available at runtime for dynamic linking. On Linux these are usually placed 14646303Smarkm// in libgcc_s.so so can be found by normal dynamic lookup. 14718316Swollman#if defined(__BIONIC__) && defined(__arm__) 14818316Swollman// List of functions which are statically linked on Android and can be generated 14946303Smarkm// by LLVM. This is done as a nested macro which is used once to declare the 15020339Swollman// imported functions with ARM_MATH_DECL and once to compare them to the 15146303Smarkm// user-requested symbol in getSymbolAddress with ARM_MATH_CHECK. The test 15246303Smarkm// assumes that all functions start with __aeabi_ and getSymbolAddress must be 15346303Smarkm// modified if that changes. 15418316Swollman#define ARM_MATH_IMPORTS(PP) \ 15519880Swollman PP(__aeabi_d2f) \ 15619880Swollman PP(__aeabi_d2iz) \ 15719880Swollman PP(__aeabi_d2lz) \ 15819880Swollman PP(__aeabi_d2uiz) \ 15919880Swollman PP(__aeabi_d2ulz) \ 16018316Swollman PP(__aeabi_dadd) \ 16119880Swollman PP(__aeabi_dcmpeq) \ 16218316Swollman PP(__aeabi_dcmpge) \ 163286348Sdelphij PP(__aeabi_dcmpgt) \ 164286348Sdelphij PP(__aeabi_dcmple) \ 165286348Sdelphij PP(__aeabi_dcmplt) \ 166286348Sdelphij PP(__aeabi_dcmpun) \ 167286348Sdelphij PP(__aeabi_ddiv) \ 168286348Sdelphij PP(__aeabi_dmul) \ 16918316Swollman PP(__aeabi_dsub) \ 17019880Swollman PP(__aeabi_f2d) \ 17119880Swollman PP(__aeabi_f2iz) \ 17219880Swollman PP(__aeabi_f2lz) \ 17318316Swollman PP(__aeabi_f2uiz) \ 17418316Swollman PP(__aeabi_f2ulz) \ 17518316Swollman PP(__aeabi_fadd) \ 17618316Swollman PP(__aeabi_fcmpeq) \ 17746303Smarkm PP(__aeabi_fcmpge) \ 17819880Swollman PP(__aeabi_fcmpgt) \ 17919880Swollman PP(__aeabi_fcmple) \ 18019880Swollman PP(__aeabi_fcmplt) \ 18118316Swollman PP(__aeabi_fcmpun) \ 18218316Swollman PP(__aeabi_fdiv) \ 18318316Swollman PP(__aeabi_fmul) \ 18418316Swollman PP(__aeabi_fsub) \ 18519880Swollman PP(__aeabi_i2d) \ 18618316Swollman PP(__aeabi_i2f) \ 18718316Swollman PP(__aeabi_idiv) \ 18818316Swollman PP(__aeabi_idivmod) \ 18918316Swollman PP(__aeabi_l2d) \ 19018316Swollman PP(__aeabi_l2f) \ 19119880Swollman PP(__aeabi_lasr) \ 19218316Swollman PP(__aeabi_ldivmod) \ 19337908Scharnier PP(__aeabi_llsl) \ 19418316Swollman PP(__aeabi_llsr) \ 19518316Swollman PP(__aeabi_lmul) \ 19618316Swollman PP(__aeabi_ui2d) \ 19718316Swollman PP(__aeabi_ui2f) \ 19818316Swollman PP(__aeabi_uidiv) \ 19919880Swollman PP(__aeabi_uidivmod) \ 20019880Swollman PP(__aeabi_ul2d) \ 20119880Swollman PP(__aeabi_ul2f) \ 20218316Swollman PP(__aeabi_uldivmod) 20318316Swollman 20418316Swollman// Declare statically linked math functions on ARM. The function declarations 20518316Swollman// here do not have the correct prototypes for each function in 20618316Swollman// ARM_MATH_IMPORTS, but it doesn't matter because only the symbol addresses are 20719880Swollman// needed. In particular the __aeabi_*divmod functions do not have calling 20818316Swollman// conventions which match any C prototype. 20919880Swollman#define ARM_MATH_DECL(name) extern "C" void name(); 21019880SwollmanARM_MATH_IMPORTS(ARM_MATH_DECL) 21119880Swollman#undef ARM_MATH_DECL 21219880Swollman#endif 21319880Swollman 21419880Swollmanuint64_t RTDyldMemoryManager::getSymbolAddress(const std::string &Name) { 21519880Swollman // This implementation assumes that the host program is the target. 21619880Swollman // Clients generating code for a remote target should implement their own 21719880Swollman // memory manager. 21819880Swollman#if defined(__linux__) && defined(__GLIBC__) 21919880Swollman //===--------------------------------------------------------------------===// 22019880Swollman // Function stubs that are invoked instead of certain library calls 22119880Swollman // 22219880Swollman // Force the following functions to be linked in to anything that uses the 22319880Swollman // JIT. This is a hack designed to work around the all-too-clever Glibc 22419880Swollman // strategy of making these functions work differently when inlined vs. when 22518316Swollman // not inlined, and hiding their real definitions in a separate archive file 22618316Swollman // that the dynamic linker can't see. For more info, search for 22719880Swollman // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. 22818316Swollman if (Name == "stat") return (uint64_t)&stat; 22919880Swollman if (Name == "fstat") return (uint64_t)&fstat; 23019880Swollman if (Name == "lstat") return (uint64_t)&lstat; 23119880Swollman if (Name == "stat64") return (uint64_t)&stat64; 23219880Swollman if (Name == "fstat64") return (uint64_t)&fstat64; 23319880Swollman if (Name == "lstat64") return (uint64_t)&lstat64; 23418316Swollman if (Name == "atexit") return (uint64_t)&atexit; 23519880Swollman if (Name == "mknod") return (uint64_t)&mknod; 23619880Swollman#endif // __linux__ && __GLIBC__ 23719880Swollman 23819880Swollman // See ARM_MATH_IMPORTS definition for explanation 23918316Swollman#if defined(__BIONIC__) && defined(__arm__) 24018316Swollman if (Name.compare(0, 8, "__aeabi_") == 0) { 24118316Swollman // Check if the user has requested any of the functions listed in 24218316Swollman // ARM_MATH_IMPORTS, and if so redirect to the statically linked symbol. 24337908Scharnier#define ARM_MATH_CHECK(fn) if (Name == #fn) return (uint64_t)&fn; 24418316Swollman ARM_MATH_IMPORTS(ARM_MATH_CHECK) 24519880Swollman#undef ARM_MATH_CHECK 24619880Swollman } 24719880Swollman#endif 24819880Swollman 24919880Swollman // We should not invoke parent's ctors/dtors from generated main()! 25018316Swollman // On Mingw and Cygwin, the symbol __main is resolved to 25118316Swollman // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors 25218316Swollman // (and register wrong callee's dtors with atexit(3)). 25318316Swollman // We expect ExecutionEngine::runStaticConstructorsDestructors() 25419880Swollman // is called before ExecutionEngine::runFunctionAsMain() is called. 25519880Swollman if (Name == "__main") return (uint64_t)&jit_noop; 25619880Swollman 25719880Swollman const char *NameStr = Name.c_str(); 25818316Swollman void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); 25919880Swollman if (Ptr) 26019880Swollman return (uint64_t)Ptr; 26119880Swollman 26219880Swollman // If it wasn't found and if it starts with an underscore ('_') character, 26319880Swollman // try again without the underscore. 26418316Swollman if (NameStr[0] == '_') { 26519880Swollman Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); 26619880Swollman if (Ptr) 26719880Swollman return (uint64_t)Ptr; 26819880Swollman } 26919880Swollman return 0; 27019880Swollman} 27119880Swollman 27220339Swollmanvoid *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name, 27320735Sache bool AbortOnFailure) { 27420339Swollman uint64_t Addr = getSymbolAddress(Name); 27519880Swollman 27619880Swollman if (!Addr && AbortOnFailure) 27719880Swollman report_fatal_error("Program used external function '" + Name + 27819880Swollman "' which could not be resolved!"); 27919880Swollman return (void*)Addr; 28019880Swollman} 28120339Swollman 28219880Swollman} // namespace llvm 28319880Swollman