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/iterator_range.h" 17 #include "llvm/ExecutionEngine/JITSymbol.h" 18 #include "llvm/ExecutionEngine/Orc/Core.h" 19 #include "llvm/ExecutionEngine/Orc/Mangling.h" 20 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 21 #include "llvm/ExecutionEngine/Orc/Shared/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 <utility> 28 #include <vector> 29 30 namespace llvm { 31 32 class ConstantArray; 33 class GlobalVariable; 34 class Function; 35 class Module; 36 class Value; 37 38 namespace object { 39 class MachOUniversalBinary; 40 } 41 42 namespace orc { 43 44 class ObjectLayer; 45 46 /// This iterator provides a convenient way to iterate over the elements 47 /// of an llvm.global_ctors/llvm.global_dtors instance. 48 /// 49 /// The easiest way to get hold of instances of this class is to use the 50 /// getConstructors/getDestructors functions. 51 class CtorDtorIterator { 52 public: 53 /// Accessor for an element of the global_ctors/global_dtors array. 54 /// 55 /// This class provides a read-only view of the element with any casts on 56 /// the function stripped away. 57 struct Element { 58 Element(unsigned Priority, Function *Func, Value *Data) 59 : Priority(Priority), Func(Func), Data(Data) {} 60 61 unsigned Priority; 62 Function *Func; 63 Value *Data; 64 }; 65 66 /// Construct an iterator instance. If End is true then this iterator 67 /// acts as the end of the range, otherwise it is the beginning. 68 CtorDtorIterator(const GlobalVariable *GV, bool End); 69 70 /// Test iterators for equality. 71 bool operator==(const CtorDtorIterator &Other) const; 72 73 /// Test iterators for inequality. 74 bool operator!=(const CtorDtorIterator &Other) const; 75 76 /// Pre-increment iterator. 77 CtorDtorIterator& operator++(); 78 79 /// Post-increment iterator. 80 CtorDtorIterator operator++(int); 81 82 /// Dereference iterator. The resulting value provides a read-only view 83 /// of this element of the global_ctors/global_dtors list. 84 Element operator*() const; 85 86 private: 87 const ConstantArray *InitList; 88 unsigned I; 89 }; 90 91 /// Create an iterator range over the entries of the llvm.global_ctors 92 /// array. 93 iterator_range<CtorDtorIterator> getConstructors(const Module &M); 94 95 /// Create an iterator range over the entries of the llvm.global_ctors 96 /// array. 97 iterator_range<CtorDtorIterator> getDestructors(const Module &M); 98 99 /// This iterator provides a convenient way to iterate over GlobalValues that 100 /// have initialization effects. 101 class StaticInitGVIterator { 102 public: 103 StaticInitGVIterator() = default; 104 105 StaticInitGVIterator(Module &M) 106 : I(M.global_values().begin()), E(M.global_values().end()), 107 ObjFmt(Triple(M.getTargetTriple()).getObjectFormat()) { 108 if (I != E) { 109 if (!isStaticInitGlobal(*I)) 110 moveToNextStaticInitGlobal(); 111 } else 112 I = E = Module::global_value_iterator(); 113 } 114 115 bool operator==(const StaticInitGVIterator &O) const { return I == O.I; } 116 bool operator!=(const StaticInitGVIterator &O) const { return I != O.I; } 117 118 StaticInitGVIterator &operator++() { 119 assert(I != E && "Increment past end of range"); 120 moveToNextStaticInitGlobal(); 121 return *this; 122 } 123 124 GlobalValue &operator*() { return *I; } 125 126 private: 127 bool isStaticInitGlobal(GlobalValue &GV); 128 void moveToNextStaticInitGlobal() { 129 ++I; 130 while (I != E && !isStaticInitGlobal(*I)) 131 ++I; 132 if (I == E) 133 I = E = Module::global_value_iterator(); 134 } 135 136 Module::global_value_iterator I, E; 137 Triple::ObjectFormatType ObjFmt; 138 }; 139 140 /// Create an iterator range over the GlobalValues that contribute to static 141 /// initialization. 142 inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) { 143 return make_range(StaticInitGVIterator(M), StaticInitGVIterator()); 144 } 145 146 class CtorDtorRunner { 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. 175 class LocalCXXRuntimeOverridesBase { 176 public: 177 /// Run any destructors recorded by the overriden __cxa_atexit function 178 /// (CXAAtExitOverride). 179 void runDestructors(); 180 181 protected: 182 using DestructorPtr = void (*)(void *); 183 using CXXDestructorDataPair = std::pair<DestructorPtr, void *>; 184 using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>; 185 CXXDestructorDataPairList DSOHandleOverride; 186 static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, 187 void *DSOHandle); 188 }; 189 190 class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { 191 public: 192 Error enable(JITDylib &JD, MangleAndInterner &Mangler); 193 }; 194 195 /// An interface for Itanium __cxa_atexit interposer implementations. 196 class ItaniumCXAAtExitSupport { 197 public: 198 struct AtExitRecord { 199 void (*F)(void *); 200 void *Ctx; 201 }; 202 203 void registerAtExit(void (*F)(void *), void *Ctx, void *DSOHandle); 204 void runAtExits(void *DSOHandle); 205 206 private: 207 std::mutex AtExitsMutex; 208 DenseMap<void *, std::vector<AtExitRecord>> AtExitRecords; 209 }; 210 211 /// A utility class to expose symbols found via dlsym to the JIT. 212 /// 213 /// If an instance of this class is attached to a JITDylib as a fallback 214 /// definition generator, then any symbol found in the given DynamicLibrary that 215 /// passes the 'Allow' predicate will be added to the JITDylib. 216 class DynamicLibrarySearchGenerator : public DefinitionGenerator { 217 public: 218 using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>; 219 using AddAbsoluteSymbolsFn = unique_function<Error(JITDylib &, SymbolMap)>; 220 221 /// Create a DynamicLibrarySearchGenerator that searches for symbols in the 222 /// given sys::DynamicLibrary. 223 /// 224 /// If the Allow predicate is given then only symbols matching the predicate 225 /// will be searched for. If the predicate is not given then all symbols will 226 /// be searched for. 227 /// 228 /// If \p AddAbsoluteSymbols is provided, it is used to add the symbols to the 229 /// \c JITDylib; otherwise it uses JD.define(absoluteSymbols(...)). 230 DynamicLibrarySearchGenerator( 231 sys::DynamicLibrary Dylib, char GlobalPrefix, 232 SymbolPredicate Allow = SymbolPredicate(), 233 AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr); 234 235 /// Permanently loads the library at the given path and, on success, returns 236 /// a DynamicLibrarySearchGenerator that will search it for symbol definitions 237 /// in the library. On failure returns the reason the library failed to load. 238 static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 239 Load(const char *FileName, char GlobalPrefix, 240 SymbolPredicate Allow = SymbolPredicate(), 241 AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr); 242 243 /// Creates a DynamicLibrarySearchGenerator that searches for symbols in 244 /// the current process. 245 static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 246 GetForCurrentProcess(char GlobalPrefix, 247 SymbolPredicate Allow = SymbolPredicate(), 248 AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr) { 249 return Load(nullptr, GlobalPrefix, std::move(Allow), 250 std::move(AddAbsoluteSymbols)); 251 } 252 253 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, 254 JITDylibLookupFlags JDLookupFlags, 255 const SymbolLookupSet &Symbols) override; 256 257 private: 258 sys::DynamicLibrary Dylib; 259 SymbolPredicate Allow; 260 AddAbsoluteSymbolsFn AddAbsoluteSymbols; 261 char GlobalPrefix; 262 }; 263 264 /// A utility class to expose symbols from a static library. 265 /// 266 /// If an instance of this class is attached to a JITDylib as a fallback 267 /// definition generator, then any symbol found in the archive will result in 268 /// the containing object being added to the JITDylib. 269 class StaticLibraryDefinitionGenerator : public DefinitionGenerator { 270 public: 271 // Interface builder function for objects loaded from this archive. 272 using GetObjectFileInterface = 273 unique_function<Expected<MaterializationUnit::Interface>( 274 ExecutionSession &ES, MemoryBufferRef ObjBuffer)>; 275 276 /// Try to create a StaticLibraryDefinitionGenerator from the given path. 277 /// 278 /// This call will succeed if the file at the given path is a static library 279 /// or a MachO universal binary containing a static library that is compatible 280 /// with the ExecutionSession's triple. Otherwise it will return an error. 281 static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 282 Load(ObjectLayer &L, const char *FileName, 283 GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface()); 284 285 /// Try to create a StaticLibrarySearchGenerator from the given memory buffer 286 /// and Archive object. 287 static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 288 Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 289 std::unique_ptr<object::Archive> Archive, 290 GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface()); 291 292 /// Try to create a StaticLibrarySearchGenerator from the given memory buffer. 293 /// This call will succeed if the buffer contains a valid archive, otherwise 294 /// it will return an error. 295 /// 296 /// This call will succeed if the buffer contains a valid static library or a 297 /// MachO universal binary containing a static library that is compatible 298 /// with the ExecutionSession's triple. Otherwise it will return an error. 299 static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 300 Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 301 GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface()); 302 303 /// Returns a list of filenames of dynamic libraries that this archive has 304 /// imported. This class does not load these libraries by itself. User is 305 /// responsible for making sure these libraries are avaliable to the JITDylib. 306 const std::set<std::string> &getImportedDynamicLibraries() const { 307 return ImportedDynamicLibraries; 308 } 309 310 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, 311 JITDylibLookupFlags JDLookupFlags, 312 const SymbolLookupSet &Symbols) override; 313 314 private: 315 StaticLibraryDefinitionGenerator(ObjectLayer &L, 316 std::unique_ptr<MemoryBuffer> ArchiveBuffer, 317 std::unique_ptr<object::Archive> Archive, 318 GetObjectFileInterface GetObjFileInterface, 319 Error &Err); 320 Error buildObjectFilesMap(); 321 322 static Expected<std::pair<size_t, size_t>> 323 getSliceRangeForArch(object::MachOUniversalBinary &UB, const Triple &TT); 324 325 ObjectLayer &L; 326 GetObjectFileInterface GetObjFileInterface; 327 std::set<std::string> ImportedDynamicLibraries; 328 std::unique_ptr<MemoryBuffer> ArchiveBuffer; 329 std::unique_ptr<object::Archive> Archive; 330 DenseMap<SymbolStringPtr, MemoryBufferRef> ObjectFilesMap; 331 }; 332 333 /// A utility class to create COFF dllimport GOT symbols (__imp_*) and PLT 334 /// stubs. 335 /// 336 /// If an instance of this class is attached to a JITDylib as a fallback 337 /// definition generator, PLT stubs and dllimport __imp_ symbols will be 338 /// generated for external symbols found outside the given jitdylib. Currently 339 /// only supports x86_64 architecture. 340 class DLLImportDefinitionGenerator : public DefinitionGenerator { 341 public: 342 /// Creates a DLLImportDefinitionGenerator instance. 343 static std::unique_ptr<DLLImportDefinitionGenerator> 344 Create(ExecutionSession &ES, ObjectLinkingLayer &L); 345 346 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, 347 JITDylibLookupFlags JDLookupFlags, 348 const SymbolLookupSet &Symbols) override; 349 350 private: 351 DLLImportDefinitionGenerator(ExecutionSession &ES, ObjectLinkingLayer &L) 352 : ES(ES), L(L) {} 353 354 static Expected<unsigned> getTargetPointerSize(const Triple &TT); 355 static Expected<llvm::endianness> getTargetEndianness(const Triple &TT); 356 Expected<std::unique_ptr<jitlink::LinkGraph>> 357 createStubsGraph(const SymbolMap &Resolved); 358 359 static StringRef getImpPrefix() { return "__imp_"; } 360 361 static StringRef getSectionName() { return "$__DLLIMPORT_STUBS"; } 362 363 ExecutionSession &ES; 364 ObjectLinkingLayer &L; 365 }; 366 367 } // end namespace orc 368 } // end namespace llvm 369 370 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H 371