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" 17 #include "llvm/ADT/iterator_range.h" 18 #include "llvm/ExecutionEngine/JITSymbol.h" 19 #include "llvm/ExecutionEngine/Orc/Core.h" 20 #include "llvm/ExecutionEngine/Orc/Mangling.h" 21 #include "llvm/ExecutionEngine/Orc/OrcError.h" 22 #include "llvm/ExecutionEngine/RuntimeDyld.h" 23 #include "llvm/Object/Archive.h" 24 #include "llvm/Support/DynamicLibrary.h" 25 #include <algorithm> 26 #include <cstdint> 27 #include <string> 28 #include <utility> 29 #include <vector> 30 31 namespace llvm { 32 33 class ConstantArray; 34 class GlobalVariable; 35 class Function; 36 class Module; 37 class TargetMachine; 38 class Value; 39 40 namespace orc { 41 42 class ObjectLayer; 43 44 /// Run a main function, returning the result. 45 /// 46 /// If the optional ProgramName argument is given then it will be inserted 47 /// before the strings in Args as the first argument to the called function. 48 /// 49 /// It is legal to have an empty argument list and no program name, however 50 /// many main functions will expect a name argument at least, and will fail 51 /// if none is provided. 52 int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args, 53 Optional<StringRef> ProgramName = None); 54 55 /// This iterator provides a convenient way to iterate over the elements 56 /// of an llvm.global_ctors/llvm.global_dtors instance. 57 /// 58 /// The easiest way to get hold of instances of this class is to use the 59 /// getConstructors/getDestructors functions. 60 class CtorDtorIterator { 61 public: 62 /// Accessor for an element of the global_ctors/global_dtors array. 63 /// 64 /// This class provides a read-only view of the element with any casts on 65 /// the function stripped away. 66 struct Element { 67 Element(unsigned Priority, Function *Func, Value *Data) 68 : Priority(Priority), Func(Func), Data(Data) {} 69 70 unsigned Priority; 71 Function *Func; 72 Value *Data; 73 }; 74 75 /// Construct an iterator instance. If End is true then this iterator 76 /// acts as the end of the range, otherwise it is the beginning. 77 CtorDtorIterator(const GlobalVariable *GV, bool End); 78 79 /// Test iterators for equality. 80 bool operator==(const CtorDtorIterator &Other) const; 81 82 /// Test iterators for inequality. 83 bool operator!=(const CtorDtorIterator &Other) const; 84 85 /// Pre-increment iterator. 86 CtorDtorIterator& operator++(); 87 88 /// Post-increment iterator. 89 CtorDtorIterator operator++(int); 90 91 /// Dereference iterator. The resulting value provides a read-only view 92 /// of this element of the global_ctors/global_dtors list. 93 Element operator*() const; 94 95 private: 96 const ConstantArray *InitList; 97 unsigned I; 98 }; 99 100 /// Create an iterator range over the entries of the llvm.global_ctors 101 /// array. 102 iterator_range<CtorDtorIterator> getConstructors(const Module &M); 103 104 /// Create an iterator range over the entries of the llvm.global_ctors 105 /// array. 106 iterator_range<CtorDtorIterator> getDestructors(const Module &M); 107 108 /// This iterator provides a convenient way to iterate over GlobalValues that 109 /// have initialization effects. 110 class StaticInitGVIterator { 111 public: 112 StaticInitGVIterator() = default; 113 114 StaticInitGVIterator(Module &M) 115 : I(M.global_values().begin()), E(M.global_values().end()), 116 ObjFmt(Triple(M.getTargetTriple()).getObjectFormat()) { 117 if (I != E) { 118 if (!isStaticInitGlobal(*I)) 119 moveToNextStaticInitGlobal(); 120 } else 121 I = E = Module::global_value_iterator(); 122 } 123 124 bool operator==(const StaticInitGVIterator &O) const { return I == O.I; } 125 bool operator!=(const StaticInitGVIterator &O) const { return I != O.I; } 126 127 StaticInitGVIterator &operator++() { 128 assert(I != E && "Increment past end of range"); 129 moveToNextStaticInitGlobal(); 130 return *this; 131 } 132 133 GlobalValue &operator*() { return *I; } 134 135 private: 136 bool isStaticInitGlobal(GlobalValue &GV); 137 void moveToNextStaticInitGlobal() { 138 ++I; 139 while (I != E && !isStaticInitGlobal(*I)) 140 ++I; 141 if (I == E) 142 I = E = Module::global_value_iterator(); 143 } 144 145 Module::global_value_iterator I, E; 146 Triple::ObjectFormatType ObjFmt; 147 }; 148 149 /// Create an iterator range over the GlobalValues that contribute to static 150 /// initialization. 151 inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) { 152 return make_range(StaticInitGVIterator(M), StaticInitGVIterator()); 153 } 154 155 /// Convenience class for recording constructor/destructor names for 156 /// later execution. 157 template <typename JITLayerT> 158 class LegacyCtorDtorRunner { 159 public: 160 /// Construct a CtorDtorRunner for the given range using the given 161 /// name mangling function. 162 LLVM_ATTRIBUTE_DEPRECATED( 163 LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames, 164 VModuleKey K), 165 "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. " 166 "Please use the ORCv2 CtorDtorRunner utility instead"); 167 168 LegacyCtorDtorRunner(ORCv1DeprecationAcknowledgement, 169 std::vector<std::string> CtorDtorNames, VModuleKey K) 170 : CtorDtorNames(std::move(CtorDtorNames)), K(K) {} 171 172 /// Run the recorded constructors/destructors through the given JIT 173 /// layer. 174 Error runViaLayer(JITLayerT &JITLayer) const { 175 using CtorDtorTy = void (*)(); 176 177 for (const auto &CtorDtorName : CtorDtorNames) { 178 if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) { 179 if (auto AddrOrErr = CtorDtorSym.getAddress()) { 180 CtorDtorTy CtorDtor = 181 reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr)); 182 CtorDtor(); 183 } else 184 return AddrOrErr.takeError(); 185 } else { 186 if (auto Err = CtorDtorSym.takeError()) 187 return Err; 188 else 189 return make_error<JITSymbolNotFound>(CtorDtorName); 190 } 191 } 192 return Error::success(); 193 } 194 195 private: 196 std::vector<std::string> CtorDtorNames; 197 orc::VModuleKey K; 198 }; 199 200 template <typename JITLayerT> 201 LegacyCtorDtorRunner<JITLayerT>::LegacyCtorDtorRunner( 202 std::vector<std::string> CtorDtorNames, VModuleKey K) 203 : CtorDtorNames(std::move(CtorDtorNames)), K(K) {} 204 205 class CtorDtorRunner { 206 public: 207 CtorDtorRunner(JITDylib &JD) : JD(JD) {} 208 void add(iterator_range<CtorDtorIterator> CtorDtors); 209 Error run(); 210 211 private: 212 using CtorDtorList = std::vector<SymbolStringPtr>; 213 using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>; 214 215 JITDylib &JD; 216 CtorDtorPriorityMap CtorDtorsByPriority; 217 }; 218 219 /// Support class for static dtor execution. For hosted (in-process) JITs 220 /// only! 221 /// 222 /// If a __cxa_atexit function isn't found C++ programs that use static 223 /// destructors will fail to link. However, we don't want to use the host 224 /// process's __cxa_atexit, because it will schedule JIT'd destructors to run 225 /// after the JIT has been torn down, which is no good. This class makes it easy 226 /// to override __cxa_atexit (and the related __dso_handle). 227 /// 228 /// To use, clients should manually call searchOverrides from their symbol 229 /// resolver. This should generally be done after attempting symbol resolution 230 /// inside the JIT, but before searching the host process's symbol table. When 231 /// the client determines that destructors should be run (generally at JIT 232 /// teardown or after a return from main), the runDestructors method should be 233 /// called. 234 class LocalCXXRuntimeOverridesBase { 235 public: 236 /// Run any destructors recorded by the overriden __cxa_atexit function 237 /// (CXAAtExitOverride). 238 void runDestructors(); 239 240 protected: 241 template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) { 242 return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P)); 243 } 244 245 using DestructorPtr = void (*)(void *); 246 using CXXDestructorDataPair = std::pair<DestructorPtr, void *>; 247 using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>; 248 CXXDestructorDataPairList DSOHandleOverride; 249 static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, 250 void *DSOHandle); 251 }; 252 253 class LegacyLocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { 254 public: 255 /// Create a runtime-overrides class. 256 template <typename MangleFtorT> 257 LLVM_ATTRIBUTE_DEPRECATED( 258 LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle), 259 "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. " 260 "Please use the ORCv2 LocalCXXRuntimeOverrides utility instead"); 261 262 template <typename MangleFtorT> 263 LegacyLocalCXXRuntimeOverrides(ORCv1DeprecationAcknowledgement, 264 const MangleFtorT &Mangle) { 265 addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); 266 addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); 267 } 268 269 /// Search overrided symbols. 270 JITEvaluatedSymbol searchOverrides(const std::string &Name) { 271 auto I = CXXRuntimeOverrides.find(Name); 272 if (I != CXXRuntimeOverrides.end()) 273 return JITEvaluatedSymbol(I->second, JITSymbolFlags::Exported); 274 return nullptr; 275 } 276 277 private: 278 void addOverride(const std::string &Name, JITTargetAddress Addr) { 279 CXXRuntimeOverrides.insert(std::make_pair(Name, Addr)); 280 } 281 282 StringMap<JITTargetAddress> CXXRuntimeOverrides; 283 }; 284 285 template <typename MangleFtorT> 286 LegacyLocalCXXRuntimeOverrides::LegacyLocalCXXRuntimeOverrides( 287 const MangleFtorT &Mangle) { 288 addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); 289 addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); 290 } 291 292 class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { 293 public: 294 Error enable(JITDylib &JD, MangleAndInterner &Mangler); 295 }; 296 297 /// An interface for Itanium __cxa_atexit interposer implementations. 298 class ItaniumCXAAtExitSupport { 299 public: 300 struct AtExitRecord { 301 void (*F)(void *); 302 void *Ctx; 303 }; 304 305 void registerAtExit(void (*F)(void *), void *Ctx, void *DSOHandle); 306 void runAtExits(void *DSOHandle); 307 308 private: 309 std::mutex AtExitsMutex; 310 DenseMap<void *, std::vector<AtExitRecord>> AtExitRecords; 311 }; 312 313 /// A utility class to expose symbols found via dlsym to the JIT. 314 /// 315 /// If an instance of this class is attached to a JITDylib as a fallback 316 /// definition generator, then any symbol found in the given DynamicLibrary that 317 /// passes the 'Allow' predicate will be added to the JITDylib. 318 class DynamicLibrarySearchGenerator : public JITDylib::DefinitionGenerator { 319 public: 320 using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>; 321 322 /// Create a DynamicLibrarySearchGenerator that searches for symbols in the 323 /// given sys::DynamicLibrary. 324 /// 325 /// If the Allow predicate is given then only symbols matching the predicate 326 /// will be searched for. If the predicate is not given then all symbols will 327 /// be searched for. 328 DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, char GlobalPrefix, 329 SymbolPredicate Allow = SymbolPredicate()); 330 331 /// Permanently loads the library at the given path and, on success, returns 332 /// a DynamicLibrarySearchGenerator that will search it for symbol definitions 333 /// in the library. On failure returns the reason the library failed to load. 334 static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 335 Load(const char *FileName, char GlobalPrefix, 336 SymbolPredicate Allow = SymbolPredicate()); 337 338 /// Creates a DynamicLibrarySearchGenerator that searches for symbols in 339 /// the current process. 340 static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 341 GetForCurrentProcess(char GlobalPrefix, 342 SymbolPredicate Allow = SymbolPredicate()) { 343 return Load(nullptr, GlobalPrefix, std::move(Allow)); 344 } 345 346 Error tryToGenerate(LookupKind K, JITDylib &JD, 347 JITDylibLookupFlags JDLookupFlags, 348 const SymbolLookupSet &Symbols) override; 349 350 private: 351 sys::DynamicLibrary Dylib; 352 SymbolPredicate Allow; 353 char GlobalPrefix; 354 }; 355 356 /// A utility class to expose symbols from a static library. 357 /// 358 /// If an instance of this class is attached to a JITDylib as a fallback 359 /// definition generator, then any symbol found in the archive will result in 360 /// the containing object being added to the JITDylib. 361 class StaticLibraryDefinitionGenerator : public JITDylib::DefinitionGenerator { 362 public: 363 /// Try to create a StaticLibraryDefinitionGenerator from the given path. 364 /// 365 /// This call will succeed if the file at the given path is a static library 366 /// is a valid archive, otherwise it will return an error. 367 static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 368 Load(ObjectLayer &L, const char *FileName); 369 370 /// Try to create a StaticLibraryDefinitionGenerator from the given path. 371 /// 372 /// This call will succeed if the file at the given path is a static library 373 /// or a MachO universal binary containing a static library that is compatible 374 /// with the given triple. Otherwise it will return an error. 375 static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 376 Load(ObjectLayer &L, const char *FileName, const Triple &TT); 377 378 /// Try to create a StaticLibrarySearchGenerator from the given memory buffer. 379 /// This call will succeed if the buffer contains a valid archive, otherwise 380 /// it will return an error. 381 static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 382 Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer); 383 384 Error tryToGenerate(LookupKind K, JITDylib &JD, 385 JITDylibLookupFlags JDLookupFlags, 386 const SymbolLookupSet &Symbols) override; 387 388 private: 389 StaticLibraryDefinitionGenerator(ObjectLayer &L, 390 std::unique_ptr<MemoryBuffer> ArchiveBuffer, 391 Error &Err); 392 393 ObjectLayer &L; 394 std::unique_ptr<MemoryBuffer> ArchiveBuffer; 395 std::unique_ptr<object::Archive> Archive; 396 }; 397 398 } // end namespace orc 399 } // end namespace llvm 400 401 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H 402