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