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/Compiler.h" 25 #include "llvm/Support/DynamicLibrary.h" 26 #include <algorithm> 27 #include <cstdint> 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 Value; 38 39 namespace object { 40 class MachOUniversalBinary; 41 } 42 43 namespace orc { 44 45 class ObjectLayer; 46 47 /// This iterator provides a convenient way to iterate over the elements 48 /// of an llvm.global_ctors/llvm.global_dtors instance. 49 /// 50 /// The easiest way to get hold of instances of this class is to use the 51 /// getConstructors/getDestructors functions. 52 class CtorDtorIterator { 53 public: 54 /// Accessor for an element of the global_ctors/global_dtors array. 55 /// 56 /// This class provides a read-only view of the element with any casts on 57 /// the function stripped away. 58 struct Element { 59 Element(unsigned Priority, Function *Func, Value *Data) 60 : Priority(Priority), Func(Func), Data(Data) {} 61 62 unsigned Priority; 63 Function *Func; 64 Value *Data; 65 }; 66 67 /// Construct an iterator instance. If End is true then this iterator 68 /// acts as the end of the range, otherwise it is the beginning. 69 LLVM_ABI CtorDtorIterator(const GlobalVariable *GV, bool End); 70 71 /// Test iterators for equality. 72 LLVM_ABI bool operator==(const CtorDtorIterator &Other) const; 73 74 /// Test iterators for inequality. 75 LLVM_ABI bool operator!=(const CtorDtorIterator &Other) const; 76 77 /// Pre-increment iterator. 78 LLVM_ABI CtorDtorIterator &operator++(); 79 80 /// Post-increment iterator. 81 LLVM_ABI CtorDtorIterator operator++(int); 82 83 /// Dereference iterator. The resulting value provides a read-only view 84 /// of this element of the global_ctors/global_dtors list. 85 LLVM_ABI Element operator*() const; 86 87 private: 88 const ConstantArray *InitList; 89 unsigned I; 90 }; 91 92 /// Create an iterator range over the entries of the llvm.global_ctors 93 /// array. 94 LLVM_ABI iterator_range<CtorDtorIterator> getConstructors(const Module &M); 95 96 /// Create an iterator range over the entries of the llvm.global_ctors 97 /// array. 98 LLVM_ABI iterator_range<CtorDtorIterator> getDestructors(const Module &M); 99 100 /// This iterator provides a convenient way to iterate over GlobalValues that 101 /// have initialization effects. 102 class StaticInitGVIterator { 103 public: 104 StaticInitGVIterator() = default; 105 106 StaticInitGVIterator(Module &M) 107 : I(M.global_values().begin()), E(M.global_values().end()), 108 ObjFmt(M.getTargetTriple().getObjectFormat()) { 109 if (I != E) { 110 if (!isStaticInitGlobal(*I)) 111 moveToNextStaticInitGlobal(); 112 } else 113 I = E = Module::global_value_iterator(); 114 } 115 116 bool operator==(const StaticInitGVIterator &O) const { return I == O.I; } 117 bool operator!=(const StaticInitGVIterator &O) const { return I != O.I; } 118 119 StaticInitGVIterator &operator++() { 120 assert(I != E && "Increment past end of range"); 121 moveToNextStaticInitGlobal(); 122 return *this; 123 } 124 125 GlobalValue &operator*() { return *I; } 126 127 private: 128 LLVM_ABI bool isStaticInitGlobal(GlobalValue &GV); 129 void moveToNextStaticInitGlobal() { 130 ++I; 131 while (I != E && !isStaticInitGlobal(*I)) 132 ++I; 133 if (I == E) 134 I = E = Module::global_value_iterator(); 135 } 136 137 Module::global_value_iterator I, E; 138 Triple::ObjectFormatType ObjFmt; 139 }; 140 141 /// Create an iterator range over the GlobalValues that contribute to static 142 /// initialization. 143 inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) { 144 return make_range(StaticInitGVIterator(M), StaticInitGVIterator()); 145 } 146 147 class CtorDtorRunner { 148 public: 149 CtorDtorRunner(JITDylib &JD) : JD(JD) {} 150 LLVM_ABI void add(iterator_range<CtorDtorIterator> CtorDtors); 151 LLVM_ABI Error run(); 152 153 private: 154 using CtorDtorList = std::vector<SymbolStringPtr>; 155 using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>; 156 157 JITDylib &JD; 158 CtorDtorPriorityMap CtorDtorsByPriority; 159 }; 160 161 /// Support class for static dtor execution. For hosted (in-process) JITs 162 /// only! 163 /// 164 /// If a __cxa_atexit function isn't found C++ programs that use static 165 /// destructors will fail to link. However, we don't want to use the host 166 /// process's __cxa_atexit, because it will schedule JIT'd destructors to run 167 /// after the JIT has been torn down, which is no good. This class makes it easy 168 /// to override __cxa_atexit (and the related __dso_handle). 169 /// 170 /// To use, clients should manually call searchOverrides from their symbol 171 /// resolver. This should generally be done after attempting symbol resolution 172 /// inside the JIT, but before searching the host process's symbol table. When 173 /// the client determines that destructors should be run (generally at JIT 174 /// teardown or after a return from main), the runDestructors method should be 175 /// called. 176 class LocalCXXRuntimeOverridesBase { 177 public: 178 /// Run any destructors recorded by the overriden __cxa_atexit function 179 /// (CXAAtExitOverride). 180 LLVM_ABI void runDestructors(); 181 182 protected: 183 using DestructorPtr = void (*)(void *); 184 using CXXDestructorDataPair = std::pair<DestructorPtr, void *>; 185 using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>; 186 CXXDestructorDataPairList DSOHandleOverride; 187 LLVM_ABI static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, 188 void *DSOHandle); 189 }; 190 191 class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { 192 public: 193 LLVM_ABI Error enable(JITDylib &JD, MangleAndInterner &Mangler); 194 }; 195 196 /// An interface for Itanium __cxa_atexit interposer implementations. 197 class ItaniumCXAAtExitSupport { 198 public: 199 struct AtExitRecord { 200 void (*F)(void *); 201 void *Ctx; 202 }; 203 204 LLVM_ABI void registerAtExit(void (*F)(void *), void *Ctx, void *DSOHandle); 205 LLVM_ABI void runAtExits(void *DSOHandle); 206 207 private: 208 std::mutex AtExitsMutex; 209 DenseMap<void *, std::vector<AtExitRecord>> AtExitRecords; 210 }; 211 212 /// A utility class to expose symbols found via dlsym to the JIT. 213 /// 214 /// If an instance of this class is attached to a JITDylib as a fallback 215 /// definition generator, then any symbol found in the given DynamicLibrary that 216 /// passes the 'Allow' predicate will be added to the JITDylib. 217 class LLVM_ABI DynamicLibrarySearchGenerator : public DefinitionGenerator { 218 public: 219 using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>; 220 using AddAbsoluteSymbolsFn = unique_function<Error(JITDylib &, SymbolMap)>; 221 222 /// Create a DynamicLibrarySearchGenerator that searches for symbols in the 223 /// given sys::DynamicLibrary. 224 /// 225 /// If the Allow predicate is given then only symbols matching the predicate 226 /// will be searched for. If the predicate is not given then all symbols will 227 /// be searched for. 228 /// 229 /// If \p AddAbsoluteSymbols is provided, it is used to add the symbols to the 230 /// \c JITDylib; otherwise it uses JD.define(absoluteSymbols(...)). 231 DynamicLibrarySearchGenerator( 232 sys::DynamicLibrary Dylib, char GlobalPrefix, 233 SymbolPredicate Allow = SymbolPredicate(), 234 AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr); 235 236 /// Permanently loads the library at the given path and, on success, returns 237 /// a DynamicLibrarySearchGenerator that will search it for symbol definitions 238 /// in the library. On failure returns the reason the library failed to load. 239 static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 240 Load(const char *FileName, char GlobalPrefix, 241 SymbolPredicate Allow = SymbolPredicate(), 242 AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr); 243 244 /// Creates a DynamicLibrarySearchGenerator that searches for symbols in 245 /// the current process. 246 static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 247 GetForCurrentProcess(char GlobalPrefix, 248 SymbolPredicate Allow = SymbolPredicate(), 249 AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr) { 250 return Load(nullptr, GlobalPrefix, std::move(Allow), 251 std::move(AddAbsoluteSymbols)); 252 } 253 254 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, 255 JITDylibLookupFlags JDLookupFlags, 256 const SymbolLookupSet &Symbols) override; 257 258 private: 259 sys::DynamicLibrary Dylib; 260 SymbolPredicate Allow; 261 AddAbsoluteSymbolsFn AddAbsoluteSymbols; 262 char GlobalPrefix; 263 }; 264 265 /// A utility class to expose symbols from a static library. 266 /// 267 /// If an instance of this class is attached to a JITDylib as a fallback 268 /// definition generator, then any symbol found in the archive will result in 269 /// the containing object being added to the JITDylib. 270 class LLVM_ABI StaticLibraryDefinitionGenerator : public DefinitionGenerator { 271 public: 272 /// Interface builder function for objects loaded from this archive. 273 using GetObjectFileInterface = 274 unique_function<Expected<MaterializationUnit::Interface>( 275 ExecutionSession &ES, MemoryBufferRef ObjBuffer)>; 276 277 /// Callback for visiting archive members at construction time. Can be used 278 /// to pre-load members. 279 /// 280 /// Callbacks are provided with a reference to the underlying archive, a 281 /// MemoryBufferRef covering the bytes for the given member, and the index of 282 /// the given member. 283 /// 284 /// Implementations should return true if the given member file should be 285 /// loadable via the generator, false if it should not, and an Error if the 286 /// member is malformed in a way that renders the archive itself invalid. 287 /// 288 /// Note: Linkers typically ignore invalid files within archives, so it's 289 /// expected that implementations will usually return `false` (i.e. 290 /// not-loadable) for malformed buffers, and will only return an 291 /// Error in exceptional circumstances. 292 using VisitMembersFunction = unique_function<Expected<bool>( 293 object::Archive &, MemoryBufferRef, size_t)>; 294 295 /// A VisitMembersFunction that unconditionally loads all object files from 296 /// the archive. 297 /// Archive members that are not valid object files will be skipped. 298 static VisitMembersFunction loadAllObjectFileMembers(ObjectLayer &L, 299 JITDylib &JD); 300 301 static std::unique_ptr<MemoryBuffer> 302 createMemberBuffer(object::Archive &A, MemoryBufferRef BufRef, size_t Index); 303 304 /// Try to create a StaticLibraryDefinitionGenerator from the given path. 305 /// 306 /// This call will succeed if the file at the given path is a static library 307 /// or a MachO universal binary containing a static library that is compatible 308 /// with the ExecutionSession's triple. Otherwise it will return an error. 309 static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 310 Load(ObjectLayer &L, const char *FileName, 311 VisitMembersFunction VisitMembers = VisitMembersFunction(), 312 GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface()); 313 314 /// Try to create a StaticLibrarySearchGenerator from the given memory buffer 315 /// and Archive object. 316 static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 317 Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 318 std::unique_ptr<object::Archive> Archive, 319 VisitMembersFunction VisitMembers = VisitMembersFunction(), 320 GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface()); 321 322 /// Try to create a StaticLibrarySearchGenerator from the given memory buffer. 323 /// This call will succeed if the buffer contains a valid archive, otherwise 324 /// it will return an error. 325 /// 326 /// This call will succeed if the buffer contains a valid static library or a 327 /// MachO universal binary containing a static library that is compatible 328 /// with the ExecutionSession's triple. Otherwise it will return an error. 329 static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 330 Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 331 VisitMembersFunction VisitMembers = VisitMembersFunction(), 332 GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface()); 333 334 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, 335 JITDylibLookupFlags JDLookupFlags, 336 const SymbolLookupSet &Symbols) override; 337 338 private: 339 StaticLibraryDefinitionGenerator( 340 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 341 std::unique_ptr<object::Archive> Archive, 342 GetObjectFileInterface GetObjFileInterface, 343 DenseMap<SymbolStringPtr, size_t> SymbolToMemberIndexMap); 344 345 ObjectLayer &L; 346 GetObjectFileInterface GetObjFileInterface; 347 std::unique_ptr<MemoryBuffer> ArchiveBuffer; 348 std::unique_ptr<object::Archive> Archive; 349 DenseMap<SymbolStringPtr, size_t> SymbolToMemberIndexMap; 350 }; 351 352 /// A utility class to create COFF dllimport GOT symbols (__imp_*) and PLT 353 /// stubs. 354 /// 355 /// If an instance of this class is attached to a JITDylib as a fallback 356 /// definition generator, PLT stubs and dllimport __imp_ symbols will be 357 /// generated for external symbols found outside the given jitdylib. Currently 358 /// only supports x86_64 architecture. 359 class LLVM_ABI DLLImportDefinitionGenerator : public DefinitionGenerator { 360 public: 361 /// Creates a DLLImportDefinitionGenerator instance. 362 static std::unique_ptr<DLLImportDefinitionGenerator> 363 Create(ExecutionSession &ES, ObjectLinkingLayer &L); 364 365 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, 366 JITDylibLookupFlags JDLookupFlags, 367 const SymbolLookupSet &Symbols) override; 368 369 private: 370 DLLImportDefinitionGenerator(ExecutionSession &ES, ObjectLinkingLayer &L) 371 : ES(ES), L(L) {} 372 373 static Expected<unsigned> getTargetPointerSize(const Triple &TT); 374 static Expected<llvm::endianness> getEndianness(const Triple &TT); 375 Expected<std::unique_ptr<jitlink::LinkGraph>> 376 createStubsGraph(const SymbolMap &Resolved); 377 378 static StringRef getImpPrefix() { return "__imp_"; } 379 380 static StringRef getSectionName() { return "$__DLLIMPORT_STUBS"; } 381 382 ExecutionSession &ES; 383 ObjectLinkingLayer &L; 384 }; 385 386 } // end namespace orc 387 } // end namespace llvm 388 389 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H 390