• 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/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