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