1 //===-- ObjectLinkingLayer.h - JITLink-based jit linking layer --*- 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 the definition for an JITLink-based, in-process object linking 10 // layer. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H 15 #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H 16 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/StringMap.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/ExecutionEngine/JITLink/JITLink.h" 21 #include "llvm/ExecutionEngine/JITSymbol.h" 22 #include "llvm/ExecutionEngine/Orc/Core.h" 23 #include "llvm/ExecutionEngine/Orc/Layer.h" 24 #include "llvm/Support/Error.h" 25 #include <algorithm> 26 #include <cassert> 27 #include <functional> 28 #include <list> 29 #include <memory> 30 #include <string> 31 #include <utility> 32 #include <vector> 33 34 namespace llvm { 35 36 namespace jitlink { 37 class EHFrameRegistrar; 38 class LinkGraph; 39 class Symbol; 40 } // namespace jitlink 41 42 namespace object { 43 class ObjectFile; 44 } // namespace object 45 46 namespace orc { 47 48 class ObjectLinkingLayerJITLinkContext; 49 50 /// An ObjectLayer implementation built on JITLink. 51 /// 52 /// Clients can use this class to add relocatable object files to an 53 /// ExecutionSession, and it typically serves as the base layer (underneath 54 /// a compiling layer like IRCompileLayer) for the rest of the JIT. 55 class ObjectLinkingLayer : public ObjectLayer, private ResourceManager { 56 friend class ObjectLinkingLayerJITLinkContext; 57 58 public: 59 /// Plugin instances can be added to the ObjectLinkingLayer to receive 60 /// callbacks when code is loaded or emitted, and when JITLink is being 61 /// configured. 62 class Plugin { 63 public: 64 using JITLinkSymbolVector = std::vector<const jitlink::Symbol *>; 65 using LocalDependenciesMap = DenseMap<SymbolStringPtr, JITLinkSymbolVector>; 66 67 virtual ~Plugin(); 68 virtual void modifyPassConfig(MaterializationResponsibility &MR, 69 const Triple &TT, 70 jitlink::PassConfiguration &Config) {} 71 72 virtual void notifyLoaded(MaterializationResponsibility &MR) {} 73 virtual Error notifyEmitted(MaterializationResponsibility &MR) { 74 return Error::success(); 75 } 76 virtual Error notifyFailed(MaterializationResponsibility &MR) = 0; 77 virtual Error notifyRemovingResources(ResourceKey K) = 0; 78 virtual void notifyTransferringResources(ResourceKey DstKey, 79 ResourceKey SrcKey) = 0; 80 81 /// Return any dependencies that synthetic symbols (e.g. init symbols) 82 /// have on locally scoped jitlink::Symbols. This is used by the 83 /// ObjectLinkingLayer to update the dependencies for the synthetic 84 /// symbols. 85 virtual LocalDependenciesMap 86 getSyntheticSymbolLocalDependencies(MaterializationResponsibility &MR) { 87 return LocalDependenciesMap(); 88 } 89 }; 90 91 using ReturnObjectBufferFunction = 92 std::function<void(std::unique_ptr<MemoryBuffer>)>; 93 94 /// Construct an ObjectLinkingLayer. 95 ObjectLinkingLayer(ExecutionSession &ES, 96 jitlink::JITLinkMemoryManager &MemMgr); 97 98 /// Construct an ObjectLinkingLayer. Takes ownership of the given 99 /// JITLinkMemoryManager. This method is a temporary hack to simplify 100 /// co-existence with RTDyldObjectLinkingLayer (which also owns its 101 /// allocators). 102 ObjectLinkingLayer(ExecutionSession &ES, 103 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr); 104 105 /// Destruct an ObjectLinkingLayer. 106 ~ObjectLinkingLayer(); 107 108 /// Set an object buffer return function. By default object buffers are 109 /// deleted once the JIT has linked them. If a return function is set then 110 /// it will be called to transfer ownership of the buffer instead. 111 void setReturnObjectBuffer(ReturnObjectBufferFunction ReturnObjectBuffer) { 112 this->ReturnObjectBuffer = std::move(ReturnObjectBuffer); 113 } 114 115 /// Add a pass-config modifier. 116 ObjectLinkingLayer &addPlugin(std::unique_ptr<Plugin> P) { 117 std::lock_guard<std::mutex> Lock(LayerMutex); 118 Plugins.push_back(std::move(P)); 119 return *this; 120 } 121 122 /// Emit an object file. 123 void emit(std::unique_ptr<MaterializationResponsibility> R, 124 std::unique_ptr<MemoryBuffer> O) override; 125 126 /// Emit a LinkGraph. 127 void emit(std::unique_ptr<MaterializationResponsibility> R, 128 std::unique_ptr<jitlink::LinkGraph> G); 129 130 /// Instructs this ObjectLinkingLayer instance to override the symbol flags 131 /// found in the AtomGraph with the flags supplied by the 132 /// MaterializationResponsibility instance. This is a workaround to support 133 /// symbol visibility in COFF, which does not use the libObject's 134 /// SF_Exported flag. Use only when generating / adding COFF object files. 135 /// 136 /// FIXME: We should be able to remove this if/when COFF properly tracks 137 /// exported symbols. 138 ObjectLinkingLayer & 139 setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) { 140 this->OverrideObjectFlags = OverrideObjectFlags; 141 return *this; 142 } 143 144 /// If set, this ObjectLinkingLayer instance will claim responsibility 145 /// for any symbols provided by a given object file that were not already in 146 /// the MaterializationResponsibility instance. Setting this flag allows 147 /// higher-level program representations (e.g. LLVM IR) to be added based on 148 /// only a subset of the symbols they provide, without having to write 149 /// intervening layers to scan and add the additional symbols. This trades 150 /// diagnostic quality for convenience however: If all symbols are enumerated 151 /// up-front then clashes can be detected and reported early (and usually 152 /// deterministically). If this option is set, clashes for the additional 153 /// symbols may not be detected until late, and detection may depend on 154 /// the flow of control through JIT'd code. Use with care. 155 ObjectLinkingLayer & 156 setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) { 157 this->AutoClaimObjectSymbols = AutoClaimObjectSymbols; 158 return *this; 159 } 160 161 private: 162 using AllocPtr = std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>; 163 164 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, 165 jitlink::PassConfiguration &PassConfig); 166 void notifyLoaded(MaterializationResponsibility &MR); 167 Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc); 168 169 Error handleRemoveResources(ResourceKey K) override; 170 void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override; 171 172 mutable std::mutex LayerMutex; 173 jitlink::JITLinkMemoryManager &MemMgr; 174 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgrOwnership; 175 bool OverrideObjectFlags = false; 176 bool AutoClaimObjectSymbols = false; 177 ReturnObjectBufferFunction ReturnObjectBuffer; 178 DenseMap<ResourceKey, std::vector<AllocPtr>> Allocs; 179 std::vector<std::unique_ptr<Plugin>> Plugins; 180 }; 181 182 class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin { 183 public: 184 EHFrameRegistrationPlugin( 185 ExecutionSession &ES, 186 std::unique_ptr<jitlink::EHFrameRegistrar> Registrar); 187 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, 188 jitlink::PassConfiguration &PassConfig) override; 189 Error notifyEmitted(MaterializationResponsibility &MR) override; 190 Error notifyFailed(MaterializationResponsibility &MR) override; 191 Error notifyRemovingResources(ResourceKey K) override; 192 void notifyTransferringResources(ResourceKey DstKey, 193 ResourceKey SrcKey) override; 194 195 private: 196 197 struct EHFrameRange { 198 JITTargetAddress Addr = 0; 199 size_t Size; 200 }; 201 202 std::mutex EHFramePluginMutex; 203 ExecutionSession &ES; 204 std::unique_ptr<jitlink::EHFrameRegistrar> Registrar; 205 DenseMap<MaterializationResponsibility *, EHFrameRange> InProcessLinks; 206 DenseMap<ResourceKey, std::vector<EHFrameRange>> EHFrameRanges; 207 }; 208 209 } // end namespace orc 210 } // end namespace llvm 211 212 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H 213