LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld - RTDyldMemoryManager.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 29 37 78.4 %
Date: 2017-09-14 15:23:50 Functions: 6 9 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // Implementation of the runtime dynamic memory manager base class.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "llvm/Config/config.h"
      15             : #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
      16             : #include "llvm/Support/Compiler.h"
      17             : #include "llvm/Support/DynamicLibrary.h"
      18             : #include "llvm/Support/ErrorHandling.h"
      19             : #include <cstdlib>
      20             : 
      21             : #ifdef __linux__
      22             :   // These includes used by RTDyldMemoryManager::getPointerToNamedFunction()
      23             :   // for Glibc trickery. See comments in this function for more information.
      24             :   #ifdef HAVE_SYS_STAT_H
      25             :     #include <sys/stat.h>
      26             :   #endif
      27             :   #include <fcntl.h>
      28             :   #include <unistd.h>
      29             : #endif
      30             : 
      31             : namespace llvm {
      32             : 
      33         348 : RTDyldMemoryManager::~RTDyldMemoryManager() {}
      34             : 
      35             : // Determine whether we can register EH tables.
      36             : #if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \
      37             :      !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__))
      38             : #define HAVE_EHTABLE_SUPPORT 1
      39             : #else
      40             : #define HAVE_EHTABLE_SUPPORT 0
      41             : #endif
      42             : 
      43             : #if HAVE_EHTABLE_SUPPORT
      44             : extern "C" void __register_frame(void *);
      45             : extern "C" void __deregister_frame(void *);
      46             : #else
      47             : // The building compiler does not have __(de)register_frame but
      48             : // it may be found at runtime in a dynamically-loaded library.
      49             : // For example, this happens when building LLVM with Visual C++
      50             : // but using the MingW runtime.
      51             : void __register_frame(void *p) {
      52             :   static bool Searched = false;
      53             :   static void((*rf)(void *)) = 0;
      54             : 
      55             :   if (!Searched) {
      56             :     Searched = true;
      57             :     *(void **)&rf =
      58             :         llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
      59             :   }
      60             :   if (rf)
      61             :     rf(p);
      62             : }
      63             : 
      64             : void __deregister_frame(void *p) {
      65             :   static bool Searched = false;
      66             :   static void((*df)(void *)) = 0;
      67             : 
      68             :   if (!Searched) {
      69             :     Searched = true;
      70             :     *(void **)&df = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
      71             :         "__deregister_frame");
      72             :   }
      73             :   if (df)
      74             :     df(p);
      75             : }
      76             : #endif
      77             : 
      78             : #ifdef __APPLE__
      79             : 
      80             : static const char *processFDE(const char *Entry, bool isDeregister) {
      81             :   const char *P = Entry;
      82             :   uint32_t Length = *((const uint32_t *)P);
      83             :   P += 4;
      84             :   uint32_t Offset = *((const uint32_t *)P);
      85             :   if (Offset != 0) {
      86             :     if (isDeregister)
      87             :       __deregister_frame(const_cast<char *>(Entry));
      88             :     else
      89             :       __register_frame(const_cast<char *>(Entry));
      90             :   }
      91             :   return P + Length;
      92             : }
      93             : 
      94             : // This implementation handles frame registration for local targets.
      95             : // Memory managers for remote targets should re-implement this function
      96             : // and use the LoadAddr parameter.
      97             : void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr,
      98             :                                                     size_t Size) {
      99             :   // On OS X OS X __register_frame takes a single FDE as an argument.
     100             :   // See http://lists.llvm.org/pipermail/llvm-dev/2013-April/061737.html
     101             :   // and projects/libunwind/src/UnwindLevel1-gcc-ext.c.
     102             :   const char *P = (const char *)Addr;
     103             :   const char *End = P + Size;
     104             :   do  {
     105             :     P = processFDE(P, false);
     106             :   } while(P != End);
     107             : }
     108             : 
     109             : void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr,
     110             :                                                       size_t Size) {
     111             :   const char *P = (const char *)Addr;
     112             :   const char *End = P + Size;
     113             :   do  {
     114             :     P = processFDE(P, true);
     115             :   } while(P != End);
     116             : }
     117             : 
     118             : #else
     119             : 
     120         222 : void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr,
     121             :                                                     size_t Size) {
     122             :   // On Linux __register_frame takes a single argument: 
     123             :   // a pointer to the start of the .eh_frame section.
     124             : 
     125             :   // How can it find the end? Because crtendS.o is linked 
     126             :   // in and it has an .eh_frame section with four zero chars.
     127         222 :   __register_frame(Addr);
     128         222 : }
     129             : 
     130          67 : void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr,
     131             :                                                       size_t Size) {
     132          67 :   __deregister_frame(Addr);
     133          67 : }
     134             : 
     135             : #endif
     136             : 
     137         217 : void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
     138             :                                           size_t Size) {
     139         217 :   registerEHFramesInProcess(Addr, Size);
     140         434 :   EHFrames.push_back({Addr, Size});
     141         217 : }
     142             : 
     143          73 : void RTDyldMemoryManager::deregisterEHFrames() {
     144         359 :   for (auto &Frame : EHFrames)
     145          67 :     deregisterEHFramesInProcess(Frame.Addr, Frame.Size);
     146         146 :   EHFrames.clear();
     147          73 : }
     148             : 
     149           0 : static int jit_noop() {
     150           0 :   return 0;
     151             : }
     152             : 
     153             : // ARM math functions are statically linked on Android from libgcc.a, but not
     154             : // available at runtime for dynamic linking. On Linux these are usually placed
     155             : // in libgcc_s.so so can be found by normal dynamic lookup.
     156             : #if defined(__BIONIC__) && defined(__arm__)
     157             : // List of functions which are statically linked on Android and can be generated
     158             : // by LLVM. This is done as a nested macro which is used once to declare the
     159             : // imported functions with ARM_MATH_DECL and once to compare them to the
     160             : // user-requested symbol in getSymbolAddress with ARM_MATH_CHECK. The test
     161             : // assumes that all functions start with __aeabi_ and getSymbolAddress must be
     162             : // modified if that changes.
     163             : #define ARM_MATH_IMPORTS(PP) \
     164             :   PP(__aeabi_d2f) \
     165             :   PP(__aeabi_d2iz) \
     166             :   PP(__aeabi_d2lz) \
     167             :   PP(__aeabi_d2uiz) \
     168             :   PP(__aeabi_d2ulz) \
     169             :   PP(__aeabi_dadd) \
     170             :   PP(__aeabi_dcmpeq) \
     171             :   PP(__aeabi_dcmpge) \
     172             :   PP(__aeabi_dcmpgt) \
     173             :   PP(__aeabi_dcmple) \
     174             :   PP(__aeabi_dcmplt) \
     175             :   PP(__aeabi_dcmpun) \
     176             :   PP(__aeabi_ddiv) \
     177             :   PP(__aeabi_dmul) \
     178             :   PP(__aeabi_dsub) \
     179             :   PP(__aeabi_f2d) \
     180             :   PP(__aeabi_f2iz) \
     181             :   PP(__aeabi_f2lz) \
     182             :   PP(__aeabi_f2uiz) \
     183             :   PP(__aeabi_f2ulz) \
     184             :   PP(__aeabi_fadd) \
     185             :   PP(__aeabi_fcmpeq) \
     186             :   PP(__aeabi_fcmpge) \
     187             :   PP(__aeabi_fcmpgt) \
     188             :   PP(__aeabi_fcmple) \
     189             :   PP(__aeabi_fcmplt) \
     190             :   PP(__aeabi_fcmpun) \
     191             :   PP(__aeabi_fdiv) \
     192             :   PP(__aeabi_fmul) \
     193             :   PP(__aeabi_fsub) \
     194             :   PP(__aeabi_i2d) \
     195             :   PP(__aeabi_i2f) \
     196             :   PP(__aeabi_idiv) \
     197             :   PP(__aeabi_idivmod) \
     198             :   PP(__aeabi_l2d) \
     199             :   PP(__aeabi_l2f) \
     200             :   PP(__aeabi_lasr) \
     201             :   PP(__aeabi_ldivmod) \
     202             :   PP(__aeabi_llsl) \
     203             :   PP(__aeabi_llsr) \
     204             :   PP(__aeabi_lmul) \
     205             :   PP(__aeabi_ui2d) \
     206             :   PP(__aeabi_ui2f) \
     207             :   PP(__aeabi_uidiv) \
     208             :   PP(__aeabi_uidivmod) \
     209             :   PP(__aeabi_ul2d) \
     210             :   PP(__aeabi_ul2f) \
     211             :   PP(__aeabi_uldivmod)
     212             : 
     213             : // Declare statically linked math functions on ARM. The function declarations
     214             : // here do not have the correct prototypes for each function in
     215             : // ARM_MATH_IMPORTS, but it doesn't matter because only the symbol addresses are
     216             : // needed. In particular the __aeabi_*divmod functions do not have calling
     217             : // conventions which match any C prototype.
     218             : #define ARM_MATH_DECL(name) extern "C" void name();
     219             : ARM_MATH_IMPORTS(ARM_MATH_DECL)
     220             : #undef ARM_MATH_DECL
     221             : #endif
     222             : 
     223             : #if defined(__linux__) && defined(__GLIBC__) && \
     224             :       (defined(__i386__) || defined(__x86_64__))
     225             : extern "C" LLVM_ATTRIBUTE_WEAK void __morestack();
     226             : #endif
     227             : 
     228             : uint64_t
     229         244 : RTDyldMemoryManager::getSymbolAddressInProcess(const std::string &Name) {
     230             :   // This implementation assumes that the host program is the target.
     231             :   // Clients generating code for a remote target should implement their own
     232             :   // memory manager.
     233             : #if defined(__linux__) && defined(__GLIBC__)
     234             :   //===--------------------------------------------------------------------===//
     235             :   // Function stubs that are invoked instead of certain library calls
     236             :   //
     237             :   // Force the following functions to be linked in to anything that uses the
     238             :   // JIT. This is a hack designed to work around the all-too-clever Glibc
     239             :   // strategy of making these functions work differently when inlined vs. when
     240             :   // not inlined, and hiding their real definitions in a separate archive file
     241             :   // that the dynamic linker can't see. For more info, search for
     242             :   // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
     243         244 :   if (Name == "stat") return (uint64_t)&stat;
     244         244 :   if (Name == "fstat") return (uint64_t)&fstat;
     245         244 :   if (Name == "lstat") return (uint64_t)&lstat;
     246         244 :   if (Name == "stat64") return (uint64_t)&stat64;
     247         244 :   if (Name == "fstat64") return (uint64_t)&fstat64;
     248         244 :   if (Name == "lstat64") return (uint64_t)&lstat64;
     249         244 :   if (Name == "atexit") return (uint64_t)&atexit;
     250         244 :   if (Name == "mknod") return (uint64_t)&mknod;
     251             : 
     252             : #if defined(__i386__) || defined(__x86_64__)
     253             :   // __morestack lives in libgcc, a static library.
     254         244 :   if (&__morestack && Name == "__morestack")
     255           0 :     return (uint64_t)&__morestack;
     256             : #endif
     257             : #endif // __linux__ && __GLIBC__
     258             :   
     259             :   // See ARM_MATH_IMPORTS definition for explanation
     260             : #if defined(__BIONIC__) && defined(__arm__)
     261             :   if (Name.compare(0, 8, "__aeabi_") == 0) {
     262             :     // Check if the user has requested any of the functions listed in
     263             :     // ARM_MATH_IMPORTS, and if so redirect to the statically linked symbol.
     264             : #define ARM_MATH_CHECK(fn) if (Name == #fn) return (uint64_t)&fn;
     265             :     ARM_MATH_IMPORTS(ARM_MATH_CHECK)
     266             : #undef ARM_MATH_CHECK
     267             :   }
     268             : #endif
     269             : 
     270             :   // We should not invoke parent's ctors/dtors from generated main()!
     271             :   // On Mingw and Cygwin, the symbol __main is resolved to
     272             :   // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors
     273             :   // (and register wrong callee's dtors with atexit(3)).
     274             :   // We expect ExecutionEngine::runStaticConstructorsDestructors()
     275             :   // is called before ExecutionEngine::runFunctionAsMain() is called.
     276         244 :   if (Name == "__main") return (uint64_t)&jit_noop;
     277             : 
     278         244 :   const char *NameStr = Name.c_str();
     279             : 
     280             :   // DynamicLibrary::SearchForAddresOfSymbol expects an unmangled 'C' symbol
     281             :   // name so ff we're on Darwin, strip the leading '_' off.
     282             : #ifdef __APPLE__
     283             :   if (NameStr[0] == '_')
     284             :     ++NameStr;
     285             : #endif
     286             : 
     287         244 :   return (uint64_t)sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
     288             : }
     289             : 
     290           0 : void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name,
     291             :                                                      bool AbortOnFailure) {
     292           0 :   uint64_t Addr = getSymbolAddress(Name);
     293             : 
     294           0 :   if (!Addr && AbortOnFailure)
     295           0 :     report_fatal_error("Program used external function '" + Name +
     296             :                        "' which could not be resolved!");
     297             : 
     298           0 :   return (void*)Addr;
     299             : }
     300             : 
     301             : } // namespace llvm

Generated by: LCOV version 1.13