LLVM  8.0.1
ExecutionUtils.h
Go to the documentation of this file.
1 //===- ExecutionUtils.h - Utilities for executing code in Orc ---*- 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 // Contains utilities for executing code in Orc.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
15 #define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
16 
17 #include "llvm/ADT/StringMap.h"
24 #include <algorithm>
25 #include <cstdint>
26 #include <string>
27 #include <utility>
28 #include <vector>
29 
30 namespace llvm {
31 
32 class ConstantArray;
33 class GlobalVariable;
34 class Function;
35 class Module;
36 class TargetMachine;
37 class Value;
38 
39 namespace orc {
40 
41 /// This iterator provides a convenient way to iterate over the elements
42 /// of an llvm.global_ctors/llvm.global_dtors instance.
43 ///
44 /// The easiest way to get hold of instances of this class is to use the
45 /// getConstructors/getDestructors functions.
47 public:
48  /// Accessor for an element of the global_ctors/global_dtors array.
49  ///
50  /// This class provides a read-only view of the element with any casts on
51  /// the function stripped away.
52  struct Element {
54  : Priority(Priority), Func(Func), Data(Data) {}
55 
56  unsigned Priority;
59  };
60 
61  /// Construct an iterator instance. If End is true then this iterator
62  /// acts as the end of the range, otherwise it is the beginning.
63  CtorDtorIterator(const GlobalVariable *GV, bool End);
64 
65  /// Test iterators for equality.
66  bool operator==(const CtorDtorIterator &Other) const;
67 
68  /// Test iterators for inequality.
69  bool operator!=(const CtorDtorIterator &Other) const;
70 
71  /// Pre-increment iterator.
73 
74  /// Post-increment iterator.
76 
77  /// Dereference iterator. The resulting value provides a read-only view
78  /// of this element of the global_ctors/global_dtors list.
79  Element operator*() const;
80 
81 private:
82  const ConstantArray *InitList;
83  unsigned I;
84 };
85 
86 /// Create an iterator range over the entries of the llvm.global_ctors
87 /// array.
89 
90 /// Create an iterator range over the entries of the llvm.global_ctors
91 /// array.
93 
94 /// Convenience class for recording constructor/destructor names for
95 /// later execution.
96 template <typename JITLayerT>
98 public:
99  /// Construct a CtorDtorRunner for the given range using the given
100  /// name mangling function.
101  LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames, VModuleKey K)
102  : CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
103 
104  /// Run the recorded constructors/destructors through the given JIT
105  /// layer.
106  Error runViaLayer(JITLayerT &JITLayer) const {
107  using CtorDtorTy = void (*)();
108 
109  for (const auto &CtorDtorName : CtorDtorNames) {
110  if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) {
111  if (auto AddrOrErr = CtorDtorSym.getAddress()) {
112  CtorDtorTy CtorDtor =
113  reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr));
114  CtorDtor();
115  } else
116  return AddrOrErr.takeError();
117  } else {
118  if (auto Err = CtorDtorSym.takeError())
119  return Err;
120  else
121  return make_error<JITSymbolNotFound>(CtorDtorName);
122  }
123  }
124  return Error::success();
125  }
126 
127 private:
128  std::vector<std::string> CtorDtorNames;
129  orc::VModuleKey K;
130 };
131 
133 public:
134  CtorDtorRunner(JITDylib &JD) : JD(JD) {}
135  void add(iterator_range<CtorDtorIterator> CtorDtors);
136  Error run();
137 
138 private:
139  using CtorDtorList = std::vector<SymbolStringPtr>;
140  using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>;
141 
142  JITDylib &JD;
143  CtorDtorPriorityMap CtorDtorsByPriority;
144 };
145 
146 /// Support class for static dtor execution. For hosted (in-process) JITs
147 /// only!
148 ///
149 /// If a __cxa_atexit function isn't found C++ programs that use static
150 /// destructors will fail to link. However, we don't want to use the host
151 /// process's __cxa_atexit, because it will schedule JIT'd destructors to run
152 /// after the JIT has been torn down, which is no good. This class makes it easy
153 /// to override __cxa_atexit (and the related __dso_handle).
154 ///
155 /// To use, clients should manually call searchOverrides from their symbol
156 /// resolver. This should generally be done after attempting symbol resolution
157 /// inside the JIT, but before searching the host process's symbol table. When
158 /// the client determines that destructors should be run (generally at JIT
159 /// teardown or after a return from main), the runDestructors method should be
160 /// called.
162 public:
163  /// Run any destructors recorded by the overriden __cxa_atexit function
164  /// (CXAAtExitOverride).
165  void runDestructors();
166 
167 protected:
168  template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) {
169  return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
170  }
171 
172  using DestructorPtr = void (*)(void *);
173  using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
174  using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
176  static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
177  void *DSOHandle);
178 };
179 
181 public:
182  /// Create a runtime-overrides class.
183  template <typename MangleFtorT>
184  LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle) {
185  addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
186  addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
187  }
188 
189  /// Search overrided symbols.
191  auto I = CXXRuntimeOverrides.find(Name);
192  if (I != CXXRuntimeOverrides.end())
194  return nullptr;
195  }
196 
197 private:
198  void addOverride(const std::string &Name, JITTargetAddress Addr) {
199  CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
200  }
201 
202  StringMap<JITTargetAddress> CXXRuntimeOverrides;
203 };
204 
206 public:
207  Error enable(JITDylib &JD, MangleAndInterner &Mangler);
208 };
209 
210 /// A utility class to expose symbols found via dlsym to the JIT.
211 ///
212 /// If an instance of this class is attached to a JITDylib as a fallback
213 /// definition generator, then any symbol found in the given DynamicLibrary that
214 /// passes the 'Allow' predicate will be added to the JITDylib.
216 public:
217  using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
218 
219  /// Create a DynamicLibrarySearchGenerator that searches for symbols in the
220  /// given sys::DynamicLibrary.
221  /// If the Allow predicate is given then only symbols matching the predicate
222  /// will be searched for in the DynamicLibrary. If the predicate is not given
223  /// then all symbols will be searched for.
225  SymbolPredicate Allow = SymbolPredicate());
226 
227  /// Permanently loads the library at the given path and, on success, returns
228  /// a DynamicLibrarySearchGenerator that will search it for symbol definitions
229  /// in the library. On failure returns the reason the library failed to load.
231  Load(const char *FileName, const DataLayout &DL,
232  SymbolPredicate Allow = SymbolPredicate());
233 
234  /// Creates a DynamicLibrarySearchGenerator that searches for symbols in
235  /// the current process.
238  SymbolPredicate Allow = SymbolPredicate()) {
239  return Load(nullptr, DL, std::move(Allow));
240  }
241 
242  SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
243 
244 private:
245  sys::DynamicLibrary Dylib;
246  SymbolPredicate Allow;
247  char GlobalPrefix;
248 };
249 
250 } // end namespace orc
251 } // end namespace llvm
252 
253 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
JITTargetAddress toTargetAddress(PtrTy *P)
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:111
Accessor for an element of the global_ctors/global_dtors array.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
bool operator==(const CtorDtorIterator &Other) const
Test iterators for equality.
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
JITEvaluatedSymbol searchOverrides(const std::string &Name)
Search overrided symbols.
Convenience class for recording constructor/destructor names for later execution. ...
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
Element(unsigned Priority, Function *Func, Value *Data)
std::vector< CXXDestructorDataPair > CXXDestructorDataPairList
uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:40
CtorDtorIterator & operator++()
Pre-increment iterator.
static Expected< DynamicLibrarySearchGenerator > GetForCurrentProcess(const DataLayout &DL, SymbolPredicate Allow=SymbolPredicate())
Creates a DynamicLibrarySearchGenerator that searches for symbols in the current process.
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Definition: BitVector.h:938
Mangles symbol names then uniques them in the context of an ExecutionSession.
Definition: Core.h:915
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
CXXDestructorDataPairList DSOHandleOverride
LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle)
Create a runtime-overrides class.
std::function< bool(SymbolStringPtr)> SymbolPredicate
iterator_range< CtorDtorIterator > getDestructors(const Module &M)
Create an iterator range over the entries of the llvm.global_ctors array.
CtorDtorIterator(const GlobalVariable *GV, bool End)
Construct an iterator instance.
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:41
#define P(N)
Support class for static dtor execution.
std::pair< DestructorPtr, void * > CXXDestructorDataPair
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
A utility class to expose symbols found via dlsym to the JIT.
This iterator provides a convenient way to iterate over the elements of an llvm.global_ctors/llvm.global_dtors instance.
A range adaptor for a pair of iterators.
ConstantArray - Constant Array Declarations.
Definition: Constants.h:414
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:209
amdgpu Simplify well known AMD library false Value Value * Arg
iterator_range< CtorDtorIterator > getConstructors(const Module &M)
Create an iterator range over the entries of the llvm.global_ctors array.
#define I(x, y, z)
Definition: MD5.cpp:58
LLVM Value Representation.
Definition: Value.h:73
Element operator*() const
Dereference iterator.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
bool operator!=(const CtorDtorIterator &Other) const
Test iterators for inequality.
LegacyCtorDtorRunner(std::vector< std::string > CtorDtorNames, VModuleKey K)
Construct a CtorDtorRunner for the given range using the given name mangling function.
Error runViaLayer(JITLayerT &JITLayer) const
Run the recorded constructors/destructors through the given JIT layer.
A symbol table that supports asynchoronous symbol queries.
Definition: Core.h:496