1//===-- ExecutionUtils.h - Utilities for executing code in Orc --*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Contains utilities for executing code in Orc. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H 15#define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H 16 17#include "llvm/ADT/StringMap.h" 18#include "llvm/ADT/iterator_range.h" 19#include "llvm/ExecutionEngine/JITSymbol.h" 20#include "llvm/ExecutionEngine/RuntimeDyld.h" 21#include <vector> 22 23namespace llvm { 24 25class ConstantArray; 26class GlobalVariable; 27class Function; 28class Module; 29class Value; 30 31namespace orc { 32 33/// @brief This iterator provides a convenient way to iterate over the elements 34/// of an llvm.global_ctors/llvm.global_dtors instance. 35/// 36/// The easiest way to get hold of instances of this class is to use the 37/// getConstructors/getDestructors functions. 38class CtorDtorIterator { 39public: 40 41 /// @brief Accessor for an element of the global_ctors/global_dtors array. 42 /// 43 /// This class provides a read-only view of the element with any casts on 44 /// the function stripped away. 45 struct Element { 46 Element(unsigned Priority, Function *Func, Value *Data) 47 : Priority(Priority), Func(Func), Data(Data) {} 48 49 unsigned Priority; 50 Function *Func; 51 Value *Data; 52 }; 53 54 /// @brief Construct an iterator instance. If End is true then this iterator 55 /// acts as the end of the range, otherwise it is the beginning. 56 CtorDtorIterator(const GlobalVariable *GV, bool End); 57 58 /// @brief Test iterators for equality. 59 bool operator==(const CtorDtorIterator &Other) const; 60 61 /// @brief Test iterators for inequality. 62 bool operator!=(const CtorDtorIterator &Other) const; 63 64 /// @brief Pre-increment iterator. 65 CtorDtorIterator& operator++(); 66 67 /// @brief Post-increment iterator. 68 CtorDtorIterator operator++(int); 69 70 /// @brief Dereference iterator. The resulting value provides a read-only view 71 /// of this element of the global_ctors/global_dtors list. 72 Element operator*() const; 73 74private: 75 const ConstantArray *InitList; 76 unsigned I; 77}; 78 79/// @brief Create an iterator range over the entries of the llvm.global_ctors 80/// array. 81iterator_range<CtorDtorIterator> getConstructors(const Module &M); 82 83/// @brief Create an iterator range over the entries of the llvm.global_ctors 84/// array. 85iterator_range<CtorDtorIterator> getDestructors(const Module &M); 86 87/// @brief Convenience class for recording constructor/destructor names for 88/// later execution. 89template <typename JITLayerT> 90class CtorDtorRunner { 91public: 92 93 /// @brief Construct a CtorDtorRunner for the given range using the given 94 /// name mangling function. 95 CtorDtorRunner(std::vector<std::string> CtorDtorNames, 96 typename JITLayerT::ModuleSetHandleT H) 97 : CtorDtorNames(std::move(CtorDtorNames)), H(H) {} 98 99 /// @brief Run the recorded constructors/destructors through the given JIT 100 /// layer. 101 bool runViaLayer(JITLayerT &JITLayer) const { 102 typedef void (*CtorDtorTy)(); 103 104 bool Error = false; 105 for (const auto &CtorDtorName : CtorDtorNames) 106 if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) { 107 CtorDtorTy CtorDtor = 108 reinterpret_cast<CtorDtorTy>( 109 static_cast<uintptr_t>(CtorDtorSym.getAddress())); 110 CtorDtor(); 111 } else 112 Error = true; 113 return !Error; 114 } 115 116private: 117 std::vector<std::string> CtorDtorNames; 118 typename JITLayerT::ModuleSetHandleT H; 119}; 120 121/// @brief Support class for static dtor execution. For hosted (in-process) JITs 122/// only! 123/// 124/// If a __cxa_atexit function isn't found C++ programs that use static 125/// destructors will fail to link. However, we don't want to use the host 126/// process's __cxa_atexit, because it will schedule JIT'd destructors to run 127/// after the JIT has been torn down, which is no good. This class makes it easy 128/// to override __cxa_atexit (and the related __dso_handle). 129/// 130/// To use, clients should manually call searchOverrides from their symbol 131/// resolver. This should generally be done after attempting symbol resolution 132/// inside the JIT, but before searching the host process's symbol table. When 133/// the client determines that destructors should be run (generally at JIT 134/// teardown or after a return from main), the runDestructors method should be 135/// called. 136class LocalCXXRuntimeOverrides { 137public: 138 139 /// Create a runtime-overrides class. 140 template <typename MangleFtorT> 141 LocalCXXRuntimeOverrides(const MangleFtorT &Mangle) { 142 addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); 143 addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); 144 } 145 146 /// Search overrided symbols. 147 JITEvaluatedSymbol searchOverrides(const std::string &Name) { 148 auto I = CXXRuntimeOverrides.find(Name); 149 if (I != CXXRuntimeOverrides.end()) 150 return JITEvaluatedSymbol(I->second, JITSymbolFlags::Exported); 151 return nullptr; 152 } 153 154 /// Run any destructors recorded by the overriden __cxa_atexit function 155 /// (CXAAtExitOverride). 156 void runDestructors(); 157 158private: 159 160 template <typename PtrTy> 161 JITTargetAddress toTargetAddress(PtrTy* P) { 162 return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P)); 163 } 164 165 void addOverride(const std::string &Name, JITTargetAddress Addr) { 166 CXXRuntimeOverrides.insert(std::make_pair(Name, Addr)); 167 } 168 169 StringMap<JITTargetAddress> CXXRuntimeOverrides; 170 171 typedef void (*DestructorPtr)(void*); 172 typedef std::pair<DestructorPtr, void*> CXXDestructorDataPair; 173 typedef std::vector<CXXDestructorDataPair> CXXDestructorDataPairList; 174 CXXDestructorDataPairList DSOHandleOverride; 175 static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, 176 void *DSOHandle); 177}; 178 179} // End namespace orc. 180} // End namespace llvm. 181 182#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H 183