1 //===----------- JITSymbol.h - JIT symbol abstraction -----------*- 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 // Abstraction for target process addresses. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_EXECUTIONENGINE_JITSYMBOL_H 15 #define LLVM_EXECUTIONENGINE_JITSYMBOL_H 16 17 #include <algorithm> 18 #include <cassert> 19 #include <cstddef> 20 #include <cstdint> 21 #include <functional> 22 #include <string> 23 24 namespace llvm { 25 26 class GlobalValue; 27 28 namespace object { 29 class BasicSymbolRef; 30 } // end namespace object 31 32 /// @brief Represents an address in the target process's address space. 33 typedef uint64_t JITTargetAddress; 34 35 /// @brief Flags for symbols in the JIT. 36 class JITSymbolFlags { 37 public: 38 typedef uint8_t UnderlyingType; 39 40 enum FlagNames : UnderlyingType { 41 None = 0, 42 Weak = 1U << 0, 43 Common = 1U << 1, 44 Absolute = 1U << 2, 45 Exported = 1U << 3 46 }; 47 48 /// @brief Default-construct a JITSymbolFlags instance. 49 JITSymbolFlags() : Flags(None) {} 50 51 /// @brief Construct a JITSymbolFlags instance from the given flags. 52 JITSymbolFlags(FlagNames Flags) : Flags(Flags) {} 53 54 /// @brief Returns true is the Weak flag is set. 55 bool isWeak() const { 56 return (Flags & Weak) == Weak; 57 } 58 59 /// @brief Returns true is the Weak flag is set. 60 bool isCommon() const { 61 return (Flags & Common) == Common; 62 } 63 64 bool isStrongDefinition() const { 65 return !isWeak() && !isCommon(); 66 } 67 68 /// @brief Returns true is the Weak flag is set. 69 bool isExported() const { 70 return (Flags & Exported) == Exported; 71 } 72 73 operator UnderlyingType&() { return Flags; } 74 75 /// Construct a JITSymbolFlags value based on the flags of the given global 76 /// value. 77 static JITSymbolFlags fromGlobalValue(const GlobalValue &GV); 78 79 /// Construct a JITSymbolFlags value based on the flags of the given libobject 80 /// symbol. 81 static JITSymbolFlags fromObjectSymbol(const object::BasicSymbolRef &Symbol); 82 83 private: 84 UnderlyingType Flags; 85 }; 86 87 /// @brief Represents a symbol that has been evaluated to an address already. 88 class JITEvaluatedSymbol { 89 public: 90 /// @brief Create a 'null' symbol. 91 JITEvaluatedSymbol(std::nullptr_t) 92 : Address(0) {} 93 94 /// @brief Create a symbol for the given address and flags. 95 JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags) 96 : Address(Address), Flags(Flags) {} 97 98 /// @brief An evaluated symbol converts to 'true' if its address is non-zero. 99 explicit operator bool() const { return Address != 0; } 100 101 /// @brief Return the address of this symbol. 102 JITTargetAddress getAddress() const { return Address; } 103 104 /// @brief Return the flags for this symbol. 105 JITSymbolFlags getFlags() const { return Flags; } 106 107 private: 108 JITTargetAddress Address; 109 JITSymbolFlags Flags; 110 }; 111 112 /// @brief Represents a symbol in the JIT. 113 class JITSymbol { 114 public: 115 typedef std::function<JITTargetAddress()> GetAddressFtor; 116 117 /// @brief Create a 'null' symbol that represents failure to find a symbol 118 /// definition. 119 JITSymbol(std::nullptr_t) 120 : CachedAddr(0) {} 121 122 /// @brief Create a symbol for a definition with a known address. 123 JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags) 124 : CachedAddr(Addr), Flags(Flags) {} 125 126 /// @brief Construct a JITSymbol from a JITEvaluatedSymbol. 127 JITSymbol(JITEvaluatedSymbol Sym) 128 : CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {} 129 130 /// @brief Create a symbol for a definition that doesn't have a known address 131 /// yet. 132 /// @param GetAddress A functor to materialize a definition (fixing the 133 /// address) on demand. 134 /// 135 /// This constructor allows a JIT layer to provide a reference to a symbol 136 /// definition without actually materializing the definition up front. The 137 /// user can materialize the definition at any time by calling the getAddress 138 /// method. 139 JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags) 140 : GetAddress(std::move(GetAddress)), CachedAddr(0), Flags(Flags) {} 141 142 /// @brief Returns true if the symbol exists, false otherwise. 143 explicit operator bool() const { return CachedAddr || GetAddress; } 144 145 /// @brief Get the address of the symbol in the target address space. Returns 146 /// '0' if the symbol does not exist. 147 JITTargetAddress getAddress() { 148 if (GetAddress) { 149 CachedAddr = GetAddress(); 150 assert(CachedAddr && "Symbol could not be materialized."); 151 GetAddress = nullptr; 152 } 153 return CachedAddr; 154 } 155 156 JITSymbolFlags getFlags() const { return Flags; } 157 158 private: 159 GetAddressFtor GetAddress; 160 JITTargetAddress CachedAddr; 161 JITSymbolFlags Flags; 162 }; 163 164 /// \brief Symbol resolution. 165 class JITSymbolResolver { 166 public: 167 virtual ~JITSymbolResolver() = default; 168 169 /// This method returns the address of the specified symbol if it exists 170 /// within the logical dynamic library represented by this JITSymbolResolver. 171 /// Unlike findSymbol, queries through this interface should return addresses 172 /// for hidden symbols. 173 /// 174 /// This is of particular importance for the Orc JIT APIs, which support lazy 175 /// compilation by breaking up modules: Each of those broken out modules 176 /// must be able to resolve hidden symbols provided by the others. Clients 177 /// writing memory managers for MCJIT can usually ignore this method. 178 /// 179 /// This method will be queried by RuntimeDyld when checking for previous 180 /// definitions of common symbols. 181 virtual JITSymbol findSymbolInLogicalDylib(const std::string &Name) = 0; 182 183 /// This method returns the address of the specified function or variable. 184 /// It is used to resolve symbols during module linking. 185 /// 186 /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will 187 /// skip all relocations for that symbol, and the client will be responsible 188 /// for handling them manually. 189 virtual JITSymbol findSymbol(const std::string &Name) = 0; 190 191 private: 192 virtual void anchor(); 193 }; 194 195 } // end namespace llvm 196 197 #endif // LLVM_EXECUTIONENGINE_JITSYMBOL_H 198