1259698Sdim//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===//
2259698Sdim//
3259698Sdim//                     The LLVM Compiler Infrastructure
4259698Sdim//
5259698Sdim// This file is distributed under the University of Illinois Open Source
6259698Sdim// License. See LICENSE.TXT for details.
7259698Sdim//
8259698Sdim//===----------------------------------------------------------------------===//
9259698Sdim//
10259698Sdim// Implementation of the runtime dynamic memory manager base class.
11259698Sdim//
12259698Sdim//===----------------------------------------------------------------------===//
13259698Sdim
14259698Sdim#include "llvm/Config/config.h"
15259698Sdim#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
16259698Sdim#include "llvm/Support/DynamicLibrary.h"
17259698Sdim#include "llvm/Support/ErrorHandling.h"
18259698Sdim
19259698Sdim#include <cstdlib>
20259698Sdim
21259698Sdim#ifdef __linux__
22259698Sdim  // These includes used by RTDyldMemoryManager::getPointerToNamedFunction()
23259698Sdim  // for Glibc trickery. See comments in this function for more information.
24259698Sdim  #ifdef HAVE_SYS_STAT_H
25259698Sdim    #include <sys/stat.h>
26259698Sdim  #endif
27259698Sdim  #include <fcntl.h>
28259698Sdim  #include <unistd.h>
29259698Sdim#endif
30259698Sdim
31259698Sdimnamespace llvm {
32259698Sdim
33259698SdimRTDyldMemoryManager::~RTDyldMemoryManager() {}
34259698Sdim
35259698Sdim// Determine whether we can register EH tables.
36259698Sdim#if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \
37261991Sdim     !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__))
38259698Sdim#define HAVE_EHTABLE_SUPPORT 1
39259698Sdim#else
40259698Sdim#define HAVE_EHTABLE_SUPPORT 0
41259698Sdim#endif
42259698Sdim
43259698Sdim#if HAVE_EHTABLE_SUPPORT
44259698Sdimextern "C" void __register_frame(void*);
45259698Sdimextern "C" void __deregister_frame(void*);
46259698Sdim#else
47259698Sdim// The building compiler does not have __(de)register_frame but
48259698Sdim// it may be found at runtime in a dynamically-loaded library.
49259698Sdim// For example, this happens when building LLVM with Visual C++
50259698Sdim// but using the MingW runtime.
51259698Sdimvoid __register_frame(void *p) {
52259698Sdim  static bool Searched = false;
53259698Sdim  static void *rf = 0;
54259698Sdim
55259698Sdim  if (!Searched) {
56259698Sdim    Searched = true;
57259698Sdim    rf = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
58259698Sdim                                                      "__register_frame");
59259698Sdim  }
60259698Sdim  if (rf)
61259698Sdim    ((void (*)(void *))rf)(p);
62259698Sdim}
63259698Sdim
64259698Sdimvoid __deregister_frame(void *p) {
65259698Sdim  static bool Searched = false;
66259698Sdim  static void *df = 0;
67259698Sdim
68259698Sdim  if (!Searched) {
69259698Sdim    Searched = true;
70259698Sdim    df = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
71259698Sdim                                                      "__deregister_frame");
72259698Sdim  }
73259698Sdim  if (df)
74259698Sdim    ((void (*)(void *))df)(p);
75259698Sdim}
76259698Sdim#endif
77259698Sdim
78259698Sdim#ifdef __APPLE__
79259698Sdim
80259698Sdimstatic const char *processFDE(const char *Entry, bool isDeregister) {
81259698Sdim  const char *P = Entry;
82259698Sdim  uint32_t Length = *((const uint32_t *)P);
83259698Sdim  P += 4;
84259698Sdim  uint32_t Offset = *((const uint32_t *)P);
85259698Sdim  if (Offset != 0) {
86259698Sdim    if (isDeregister)
87259698Sdim      __deregister_frame(const_cast<char *>(Entry));
88259698Sdim    else
89259698Sdim      __register_frame(const_cast<char *>(Entry));
90259698Sdim  }
91259698Sdim  return P + Length;
92259698Sdim}
93259698Sdim
94259698Sdim// This implementation handles frame registration for local targets.
95259698Sdim// Memory managers for remote targets should re-implement this function
96259698Sdim// and use the LoadAddr parameter.
97259698Sdimvoid RTDyldMemoryManager::registerEHFrames(uint8_t *Addr,
98259698Sdim                                           uint64_t LoadAddr,
99259698Sdim                                           size_t Size) {
100259698Sdim  // On OS X OS X __register_frame takes a single FDE as an argument.
101259698Sdim  // See http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061768.html
102259698Sdim  const char *P = (const char *)Addr;
103259698Sdim  const char *End = P + Size;
104259698Sdim  do  {
105259698Sdim    P = processFDE(P, false);
106259698Sdim  } while(P != End);
107259698Sdim}
108259698Sdim
109259698Sdimvoid RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr,
110259698Sdim                                           uint64_t LoadAddr,
111259698Sdim                                           size_t Size) {
112259698Sdim  const char *P = (const char *)Addr;
113259698Sdim  const char *End = P + Size;
114259698Sdim  do  {
115259698Sdim    P = processFDE(P, true);
116259698Sdim  } while(P != End);
117259698Sdim}
118259698Sdim
119259698Sdim#else
120259698Sdim
121259698Sdimvoid RTDyldMemoryManager::registerEHFrames(uint8_t *Addr,
122259698Sdim                                           uint64_t LoadAddr,
123259698Sdim                                           size_t Size) {
124259698Sdim  // On Linux __register_frame takes a single argument:
125259698Sdim  // a pointer to the start of the .eh_frame section.
126259698Sdim
127259698Sdim  // How can it find the end? Because crtendS.o is linked
128259698Sdim  // in and it has an .eh_frame section with four zero chars.
129259698Sdim  __register_frame(Addr);
130259698Sdim}
131259698Sdim
132259698Sdimvoid RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr,
133259698Sdim                                           uint64_t LoadAddr,
134259698Sdim                                           size_t Size) {
135259698Sdim  __deregister_frame(Addr);
136259698Sdim}
137259698Sdim
138259698Sdim#endif
139259698Sdim
140259698Sdimstatic int jit_noop() {
141259698Sdim  return 0;
142259698Sdim}
143259698Sdim
144259698Sdim// ARM math functions are statically linked on Android from libgcc.a, but not
145259698Sdim// available at runtime for dynamic linking. On Linux these are usually placed
146259698Sdim// in libgcc_s.so so can be found by normal dynamic lookup.
147259698Sdim#if defined(__BIONIC__) && defined(__arm__)
148259698Sdim// List of functions which are statically linked on Android and can be generated
149259698Sdim// by LLVM. This is done as a nested macro which is used once to declare the
150259698Sdim// imported functions with ARM_MATH_DECL and once to compare them to the
151259698Sdim// user-requested symbol in getSymbolAddress with ARM_MATH_CHECK. The test
152259698Sdim// assumes that all functions start with __aeabi_ and getSymbolAddress must be
153259698Sdim// modified if that changes.
154259698Sdim#define ARM_MATH_IMPORTS(PP) \
155259698Sdim  PP(__aeabi_d2f) \
156259698Sdim  PP(__aeabi_d2iz) \
157259698Sdim  PP(__aeabi_d2lz) \
158259698Sdim  PP(__aeabi_d2uiz) \
159259698Sdim  PP(__aeabi_d2ulz) \
160259698Sdim  PP(__aeabi_dadd) \
161259698Sdim  PP(__aeabi_dcmpeq) \
162259698Sdim  PP(__aeabi_dcmpge) \
163259698Sdim  PP(__aeabi_dcmpgt) \
164259698Sdim  PP(__aeabi_dcmple) \
165259698Sdim  PP(__aeabi_dcmplt) \
166259698Sdim  PP(__aeabi_dcmpun) \
167259698Sdim  PP(__aeabi_ddiv) \
168259698Sdim  PP(__aeabi_dmul) \
169259698Sdim  PP(__aeabi_dsub) \
170259698Sdim  PP(__aeabi_f2d) \
171259698Sdim  PP(__aeabi_f2iz) \
172259698Sdim  PP(__aeabi_f2lz) \
173259698Sdim  PP(__aeabi_f2uiz) \
174259698Sdim  PP(__aeabi_f2ulz) \
175259698Sdim  PP(__aeabi_fadd) \
176259698Sdim  PP(__aeabi_fcmpeq) \
177259698Sdim  PP(__aeabi_fcmpge) \
178259698Sdim  PP(__aeabi_fcmpgt) \
179259698Sdim  PP(__aeabi_fcmple) \
180259698Sdim  PP(__aeabi_fcmplt) \
181259698Sdim  PP(__aeabi_fcmpun) \
182259698Sdim  PP(__aeabi_fdiv) \
183259698Sdim  PP(__aeabi_fmul) \
184259698Sdim  PP(__aeabi_fsub) \
185259698Sdim  PP(__aeabi_i2d) \
186259698Sdim  PP(__aeabi_i2f) \
187259698Sdim  PP(__aeabi_idiv) \
188259698Sdim  PP(__aeabi_idivmod) \
189259698Sdim  PP(__aeabi_l2d) \
190259698Sdim  PP(__aeabi_l2f) \
191259698Sdim  PP(__aeabi_lasr) \
192259698Sdim  PP(__aeabi_ldivmod) \
193259698Sdim  PP(__aeabi_llsl) \
194259698Sdim  PP(__aeabi_llsr) \
195259698Sdim  PP(__aeabi_lmul) \
196259698Sdim  PP(__aeabi_ui2d) \
197259698Sdim  PP(__aeabi_ui2f) \
198259698Sdim  PP(__aeabi_uidiv) \
199259698Sdim  PP(__aeabi_uidivmod) \
200259698Sdim  PP(__aeabi_ul2d) \
201259698Sdim  PP(__aeabi_ul2f) \
202259698Sdim  PP(__aeabi_uldivmod)
203259698Sdim
204259698Sdim// Declare statically linked math functions on ARM. The function declarations
205259698Sdim// here do not have the correct prototypes for each function in
206259698Sdim// ARM_MATH_IMPORTS, but it doesn't matter because only the symbol addresses are
207259698Sdim// needed. In particular the __aeabi_*divmod functions do not have calling
208259698Sdim// conventions which match any C prototype.
209259698Sdim#define ARM_MATH_DECL(name) extern "C" void name();
210259698SdimARM_MATH_IMPORTS(ARM_MATH_DECL)
211259698Sdim#undef ARM_MATH_DECL
212259698Sdim#endif
213259698Sdim
214259698Sdimuint64_t RTDyldMemoryManager::getSymbolAddress(const std::string &Name) {
215259698Sdim  // This implementation assumes that the host program is the target.
216259698Sdim  // Clients generating code for a remote target should implement their own
217259698Sdim  // memory manager.
218259698Sdim#if defined(__linux__) && defined(__GLIBC__)
219259698Sdim  //===--------------------------------------------------------------------===//
220259698Sdim  // Function stubs that are invoked instead of certain library calls
221259698Sdim  //
222259698Sdim  // Force the following functions to be linked in to anything that uses the
223259698Sdim  // JIT. This is a hack designed to work around the all-too-clever Glibc
224259698Sdim  // strategy of making these functions work differently when inlined vs. when
225259698Sdim  // not inlined, and hiding their real definitions in a separate archive file
226259698Sdim  // that the dynamic linker can't see. For more info, search for
227259698Sdim  // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
228259698Sdim  if (Name == "stat") return (uint64_t)&stat;
229259698Sdim  if (Name == "fstat") return (uint64_t)&fstat;
230259698Sdim  if (Name == "lstat") return (uint64_t)&lstat;
231259698Sdim  if (Name == "stat64") return (uint64_t)&stat64;
232259698Sdim  if (Name == "fstat64") return (uint64_t)&fstat64;
233259698Sdim  if (Name == "lstat64") return (uint64_t)&lstat64;
234259698Sdim  if (Name == "atexit") return (uint64_t)&atexit;
235259698Sdim  if (Name == "mknod") return (uint64_t)&mknod;
236259698Sdim#endif // __linux__ && __GLIBC__
237259698Sdim
238259698Sdim  // See ARM_MATH_IMPORTS definition for explanation
239259698Sdim#if defined(__BIONIC__) && defined(__arm__)
240259698Sdim  if (Name.compare(0, 8, "__aeabi_") == 0) {
241259698Sdim    // Check if the user has requested any of the functions listed in
242259698Sdim    // ARM_MATH_IMPORTS, and if so redirect to the statically linked symbol.
243259698Sdim#define ARM_MATH_CHECK(fn) if (Name == #fn) return (uint64_t)&fn;
244259698Sdim    ARM_MATH_IMPORTS(ARM_MATH_CHECK)
245259698Sdim#undef ARM_MATH_CHECK
246259698Sdim  }
247259698Sdim#endif
248259698Sdim
249259698Sdim  // We should not invoke parent's ctors/dtors from generated main()!
250259698Sdim  // On Mingw and Cygwin, the symbol __main is resolved to
251259698Sdim  // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors
252259698Sdim  // (and register wrong callee's dtors with atexit(3)).
253259698Sdim  // We expect ExecutionEngine::runStaticConstructorsDestructors()
254259698Sdim  // is called before ExecutionEngine::runFunctionAsMain() is called.
255259698Sdim  if (Name == "__main") return (uint64_t)&jit_noop;
256259698Sdim
257259698Sdim  const char *NameStr = Name.c_str();
258259698Sdim  void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
259259698Sdim  if (Ptr)
260259698Sdim    return (uint64_t)Ptr;
261259698Sdim
262259698Sdim  // If it wasn't found and if it starts with an underscore ('_') character,
263259698Sdim  // try again without the underscore.
264259698Sdim  if (NameStr[0] == '_') {
265259698Sdim    Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
266259698Sdim    if (Ptr)
267259698Sdim      return (uint64_t)Ptr;
268259698Sdim  }
269259698Sdim  return 0;
270259698Sdim}
271259698Sdim
272259698Sdimvoid *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name,
273259698Sdim                                                     bool AbortOnFailure) {
274259698Sdim  uint64_t Addr = getSymbolAddress(Name);
275259698Sdim
276259698Sdim  if (!Addr && AbortOnFailure)
277259698Sdim    report_fatal_error("Program used external function '" + Name +
278259698Sdim                       "' which could not be resolved!");
279259698Sdim  return (void*)Addr;
280259698Sdim}
281259698Sdim
282259698Sdim} // namespace llvm
283