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