LLVM  10.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"
22 #include "llvm/Object/Archive.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 class ObjectLayer;
42 
43 /// This iterator provides a convenient way to iterate over the elements
44 /// of an llvm.global_ctors/llvm.global_dtors instance.
45 ///
46 /// The easiest way to get hold of instances of this class is to use the
47 /// getConstructors/getDestructors functions.
49 public:
50  /// Accessor for an element of the global_ctors/global_dtors array.
51  ///
52  /// This class provides a read-only view of the element with any casts on
53  /// the function stripped away.
54  struct Element {
56  : Priority(Priority), Func(Func), Data(Data) {}
57 
58  unsigned Priority;
61  };
62 
63  /// Construct an iterator instance. If End is true then this iterator
64  /// acts as the end of the range, otherwise it is the beginning.
65  CtorDtorIterator(const GlobalVariable *GV, bool End);
66 
67  /// Test iterators for equality.
68  bool operator==(const CtorDtorIterator &Other) const;
69 
70  /// Test iterators for inequality.
71  bool operator!=(const CtorDtorIterator &Other) const;
72 
73  /// Pre-increment iterator.
75 
76  /// Post-increment iterator.
78 
79  /// Dereference iterator. The resulting value provides a read-only view
80  /// of this element of the global_ctors/global_dtors list.
81  Element operator*() const;
82 
83 private:
84  const ConstantArray *InitList;
85  unsigned I;
86 };
87 
88 /// Create an iterator range over the entries of the llvm.global_ctors
89 /// array.
91 
92 /// Create an iterator range over the entries of the llvm.global_ctors
93 /// array.
95 
96 /// Convenience class for recording constructor/destructor names for
97 /// later execution.
98 template <typename JITLayerT>
100 public:
101  /// Construct a CtorDtorRunner for the given range using the given
102  /// name mangling function.
104  LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames,
105  VModuleKey K),
106  "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. "
107  "Please use the ORCv2 CtorDtorRunner utility instead");
108 
110  std::vector<std::string> CtorDtorNames, VModuleKey K)
111  : CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
112 
113  /// Run the recorded constructors/destructors through the given JIT
114  /// layer.
115  Error runViaLayer(JITLayerT &JITLayer) const {
116  using CtorDtorTy = void (*)();
117 
118  for (const auto &CtorDtorName : CtorDtorNames) {
119  if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) {
120  if (auto AddrOrErr = CtorDtorSym.getAddress()) {
121  CtorDtorTy CtorDtor =
122  reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr));
123  CtorDtor();
124  } else
125  return AddrOrErr.takeError();
126  } else {
127  if (auto Err = CtorDtorSym.takeError())
128  return Err;
129  else
130  return make_error<JITSymbolNotFound>(CtorDtorName);
131  }
132  }
133  return Error::success();
134  }
135 
136 private:
137  std::vector<std::string> CtorDtorNames;
138  orc::VModuleKey K;
139 };
140 
141 template <typename JITLayerT>
143  std::vector<std::string> CtorDtorNames, VModuleKey K)
144  : CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
145 
147 public:
148  CtorDtorRunner(JITDylib &JD) : JD(JD) {}
149  void add(iterator_range<CtorDtorIterator> CtorDtors);
150  Error run();
151 
152 private:
153  using CtorDtorList = std::vector<SymbolStringPtr>;
154  using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>;
155 
156  JITDylib &JD;
157  CtorDtorPriorityMap CtorDtorsByPriority;
158 };
159 
160 /// Support class for static dtor execution. For hosted (in-process) JITs
161 /// only!
162 ///
163 /// If a __cxa_atexit function isn't found C++ programs that use static
164 /// destructors will fail to link. However, we don't want to use the host
165 /// process's __cxa_atexit, because it will schedule JIT'd destructors to run
166 /// after the JIT has been torn down, which is no good. This class makes it easy
167 /// to override __cxa_atexit (and the related __dso_handle).
168 ///
169 /// To use, clients should manually call searchOverrides from their symbol
170 /// resolver. This should generally be done after attempting symbol resolution
171 /// inside the JIT, but before searching the host process's symbol table. When
172 /// the client determines that destructors should be run (generally at JIT
173 /// teardown or after a return from main), the runDestructors method should be
174 /// called.
176 public:
177  /// Run any destructors recorded by the overriden __cxa_atexit function
178  /// (CXAAtExitOverride).
179  void runDestructors();
180 
181 protected:
182  template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) {
183  return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
184  }
185 
186  using DestructorPtr = void (*)(void *);
187  using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
188  using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
190  static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
191  void *DSOHandle);
192 };
193 
195 public:
196  /// Create a runtime-overrides class.
197  template <typename MangleFtorT>
199  LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle),
200  "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. "
201  "Please use the ORCv2 LocalCXXRuntimeOverrides utility instead");
202 
203  template <typename MangleFtorT>
205  const MangleFtorT &Mangle) {
206  addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
207  addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
208  }
209 
210  /// Search overrided symbols.
212  auto I = CXXRuntimeOverrides.find(Name);
213  if (I != CXXRuntimeOverrides.end())
215  return nullptr;
216  }
217 
218 private:
219  void addOverride(const std::string &Name, JITTargetAddress Addr) {
220  CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
221  }
222 
223  StringMap<JITTargetAddress> CXXRuntimeOverrides;
224 };
225 
226 template <typename MangleFtorT>
228  const MangleFtorT &Mangle) {
229  addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
230  addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
231 }
232 
234 public:
235  Error enable(JITDylib &JD, MangleAndInterner &Mangler);
236 };
237 
238 /// A utility class to expose symbols found via dlsym to the JIT.
239 ///
240 /// If an instance of this class is attached to a JITDylib as a fallback
241 /// definition generator, then any symbol found in the given DynamicLibrary that
242 /// passes the 'Allow' predicate will be added to the JITDylib.
244 public:
245  using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
246 
247  /// Create a DynamicLibrarySearchGenerator that searches for symbols in the
248  /// given sys::DynamicLibrary.
249  ///
250  /// If the Allow predicate is given then only symbols matching the predicate
251  /// will be searched for. If the predicate is not given then all symbols will
252  /// be searched for.
254  SymbolPredicate Allow = SymbolPredicate());
255 
256  /// Permanently loads the library at the given path and, on success, returns
257  /// a DynamicLibrarySearchGenerator that will search it for symbol definitions
258  /// in the library. On failure returns the reason the library failed to load.
260  Load(const char *FileName, char GlobalPrefix,
261  SymbolPredicate Allow = SymbolPredicate());
262 
263  /// Creates a DynamicLibrarySearchGenerator that searches for symbols in
264  /// the current process.
266  GetForCurrentProcess(char GlobalPrefix,
267  SymbolPredicate Allow = SymbolPredicate()) {
268  return Load(nullptr, GlobalPrefix, std::move(Allow));
269  }
270 
271  Expected<SymbolNameSet> tryToGenerate(JITDylib &JD,
272  const SymbolNameSet &Names) override;
273 
274 private:
275  sys::DynamicLibrary Dylib;
276  SymbolPredicate Allow;
277  char GlobalPrefix;
278 };
279 
280 /// A utility class to expose symbols from a static library.
281 ///
282 /// If an instance of this class is attached to a JITDylib as a fallback
283 /// definition generator, then any symbol found in the archive will result in
284 /// the containing object being added to the JITDylib.
286 public:
287  /// Try to create a StaticLibraryDefinitionGenerator from the given path.
288  ///
289  /// This call will succeed if the file at the given path is a static library
290  /// is a valid archive, otherwise it will return an error.
292  Load(ObjectLayer &L, const char *FileName);
293 
294  /// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
295  /// Thhis call will succeed if the buffer contains a valid archive, otherwise
296  /// it will return an error.
298  Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer);
299 
300  Expected<SymbolNameSet> tryToGenerate(JITDylib &JD,
301  const SymbolNameSet &Names) override;
302 
303 private:
305  std::unique_ptr<MemoryBuffer> ArchiveBuffer,
306  Error &Err);
307 
308  ObjectLayer &L;
309  std::unique_ptr<MemoryBuffer> ArchiveBuffer;
310  object::Archive Archive;
311  size_t UnrealizedObjects = 0;
312 };
313 
314 } // end namespace orc
315 } // end namespace llvm
316 
317 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
JITTargetAddress toTargetAddress(PtrTy *P)
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
CtorDtorIterator & operator++()
Pre-increment iterator.
Definition: BitVector.h:937
A utility class to expose symbols from a static library.
Mangles symbol names then uniques them in the context of an ExecutionSession.
Definition: Core.h:996
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
CXXDestructorDataPairList DSOHandleOverride
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.
ORCv1DeprecationAcknowledgement
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
#define LLVM_ATTRIBUTE_DEPRECATED(decl, message)
Definition: Compiler.h:293
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
A utility class to expose symbols found via dlsym to the JIT.
static uint64_t add(uint64_t LeftOp, uint64_t RightOp)
Definition: FileCheck.cpp:243
This iterator provides a convenient way to iterate over the elements of an llvm.global_ctors/llvm.global_dtors instance.
LegacyCtorDtorRunner(ORCv1DeprecationAcknowledgement, std::vector< std::string > CtorDtorNames, VModuleKey K)
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:189
uint8_t uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:41
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:157
Interface for Layers that accept object files.
Definition: Layer.h:113
bool operator!=(const CtorDtorIterator &Other) const
Test iterators for inequality.
LegacyLocalCXXRuntimeOverrides(ORCv1DeprecationAcknowledgement, const MangleFtorT &Mangle)
static Expected< std::unique_ptr< DynamicLibrarySearchGenerator > > GetForCurrentProcess(char GlobalPrefix, SymbolPredicate Allow=SymbolPredicate())
Creates a DynamicLibrarySearchGenerator that searches for symbols in the current process.
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:480