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