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