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 } // namespace jitlink 39 40 namespace object { 41 class ObjectFile; 42 } // namespace object 43 44 namespace orc { 45 46 class ObjectLinkingLayerJITLinkContext; 47 48 /// An ObjectLayer implementation built on JITLink. 49 /// 50 /// Clients can use this class to add relocatable object files to an 51 /// ExecutionSession, and it typically serves as the base layer (underneath 52 /// a compiling layer like IRCompileLayer) for the rest of the JIT. 53 class ObjectLinkingLayer : public ObjectLayer { 54 friend class ObjectLinkingLayerJITLinkContext; 55 56 public: 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 virtual ~Plugin(); modifyPassConfig(MaterializationResponsibility & MR,const Triple & TT,jitlink::PassConfiguration & Config)63 virtual void modifyPassConfig(MaterializationResponsibility &MR, 64 const Triple &TT, 65 jitlink::PassConfiguration &Config) {} notifyLoaded(MaterializationResponsibility & MR)66 virtual void notifyLoaded(MaterializationResponsibility &MR) {} notifyEmitted(MaterializationResponsibility & MR)67 virtual Error notifyEmitted(MaterializationResponsibility &MR) { 68 return Error::success(); 69 } notifyRemovingModule(VModuleKey K)70 virtual Error notifyRemovingModule(VModuleKey K) { 71 return Error::success(); 72 } notifyRemovingAllModules()73 virtual Error notifyRemovingAllModules() { return Error::success(); } 74 }; 75 76 using ReturnObjectBufferFunction = 77 std::function<void(std::unique_ptr<MemoryBuffer>)>; 78 79 /// Construct an ObjectLinkingLayer with the given NotifyLoaded, 80 /// and NotifyEmitted functors. 81 ObjectLinkingLayer(ExecutionSession &ES, 82 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr); 83 84 /// Destruct an ObjectLinkingLayer. 85 ~ObjectLinkingLayer(); 86 87 /// Set an object buffer return function. By default object buffers are 88 /// deleted once the JIT has linked them. If a return function is set then 89 /// it will be called to transfer ownership of the buffer instead. setReturnObjectBuffer(ReturnObjectBufferFunction ReturnObjectBuffer)90 void setReturnObjectBuffer(ReturnObjectBufferFunction ReturnObjectBuffer) { 91 this->ReturnObjectBuffer = std::move(ReturnObjectBuffer); 92 } 93 94 /// Add a pass-config modifier. addPlugin(std::unique_ptr<Plugin> P)95 ObjectLinkingLayer &addPlugin(std::unique_ptr<Plugin> P) { 96 std::lock_guard<std::mutex> Lock(LayerMutex); 97 Plugins.push_back(std::move(P)); 98 return *this; 99 } 100 101 /// Emit the object. 102 void emit(MaterializationResponsibility R, 103 std::unique_ptr<MemoryBuffer> O) override; 104 105 /// Instructs this ObjectLinkingLayer instance to override the symbol flags 106 /// found in the AtomGraph with the flags supplied by the 107 /// MaterializationResponsibility instance. This is a workaround to support 108 /// symbol visibility in COFF, which does not use the libObject's 109 /// SF_Exported flag. Use only when generating / adding COFF object files. 110 /// 111 /// FIXME: We should be able to remove this if/when COFF properly tracks 112 /// exported symbols. 113 ObjectLinkingLayer & setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags)114 setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) { 115 this->OverrideObjectFlags = OverrideObjectFlags; 116 return *this; 117 } 118 119 /// If set, this ObjectLinkingLayer instance will claim responsibility 120 /// for any symbols provided by a given object file that were not already in 121 /// the MaterializationResponsibility instance. Setting this flag allows 122 /// higher-level program representations (e.g. LLVM IR) to be added based on 123 /// only a subset of the symbols they provide, without having to write 124 /// intervening layers to scan and add the additional symbols. This trades 125 /// diagnostic quality for convenience however: If all symbols are enumerated 126 /// up-front then clashes can be detected and reported early (and usually 127 /// deterministically). If this option is set, clashes for the additional 128 /// symbols may not be detected until late, and detection may depend on 129 /// the flow of control through JIT'd code. Use with care. 130 ObjectLinkingLayer & setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols)131 setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) { 132 this->AutoClaimObjectSymbols = AutoClaimObjectSymbols; 133 return *this; 134 } 135 136 private: 137 using AllocPtr = std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>; 138 139 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, 140 jitlink::PassConfiguration &PassConfig); 141 void notifyLoaded(MaterializationResponsibility &MR); 142 Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc); 143 144 Error removeModule(VModuleKey K); 145 Error removeAllModules(); 146 147 mutable std::mutex LayerMutex; 148 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr; 149 bool OverrideObjectFlags = false; 150 bool AutoClaimObjectSymbols = false; 151 ReturnObjectBufferFunction ReturnObjectBuffer; 152 DenseMap<VModuleKey, AllocPtr> TrackedAllocs; 153 std::vector<AllocPtr> UntrackedAllocs; 154 std::vector<std::unique_ptr<Plugin>> Plugins; 155 }; 156 157 class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin { 158 public: 159 EHFrameRegistrationPlugin(jitlink::EHFrameRegistrar &Registrar); 160 Error notifyEmitted(MaterializationResponsibility &MR) override; 161 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, 162 jitlink::PassConfiguration &PassConfig) override; 163 Error notifyRemovingModule(VModuleKey K) override; 164 Error notifyRemovingAllModules() override; 165 166 private: 167 168 struct EHFrameRange { 169 JITTargetAddress Addr = 0; 170 size_t Size; 171 }; 172 173 jitlink::EHFrameRegistrar &Registrar; 174 DenseMap<MaterializationResponsibility *, EHFrameRange> InProcessLinks; 175 DenseMap<VModuleKey, EHFrameRange> TrackedEHFrameRanges; 176 std::vector<EHFrameRange> UntrackedEHFrameRanges; 177 }; 178 179 } // end namespace orc 180 } // end namespace llvm 181 182 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H 183