1 //===- RTDyldObjectLinkingLayer.h - RTDyld-based jit linking  ---*- 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 RTDyld-based, in-process object linking layer.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
15 
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ExecutionEngine/JITEventListener.h"
20 #include "llvm/ExecutionEngine/JITSymbol.h"
21 #include "llvm/ExecutionEngine/Orc/Core.h"
22 #include "llvm/ExecutionEngine/Orc/Layer.h"
23 #include "llvm/ExecutionEngine/RuntimeDyld.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Support/Error.h"
26 #include <algorithm>
27 #include <cassert>
28 #include <functional>
29 #include <list>
30 #include <memory>
31 #include <string>
32 #include <utility>
33 #include <vector>
34 
35 namespace llvm {
36 namespace orc {
37 
38 class RTDyldObjectLinkingLayer
39     : public RTTIExtends<RTDyldObjectLinkingLayer, ObjectLayer>,
40       private ResourceManager {
41 public:
42   static char ID;
43 
44   /// Functor for receiving object-loaded notifications.
45   using NotifyLoadedFunction = std::function<void(
46       MaterializationResponsibility &R, const object::ObjectFile &Obj,
47       const RuntimeDyld::LoadedObjectInfo &)>;
48 
49   /// Functor for receiving finalization notifications.
50   using NotifyEmittedFunction = std::function<void(
51       MaterializationResponsibility &R, std::unique_ptr<MemoryBuffer>)>;
52 
53   using GetMemoryManagerFunction =
54       std::function<std::unique_ptr<RuntimeDyld::MemoryManager>()>;
55 
56   /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
57   ///        and NotifyEmitted functors.
58   RTDyldObjectLinkingLayer(ExecutionSession &ES,
59                            GetMemoryManagerFunction GetMemoryManager);
60 
61   ~RTDyldObjectLinkingLayer();
62 
63   /// Emit the object.
64   void emit(std::unique_ptr<MaterializationResponsibility> R,
65             std::unique_ptr<MemoryBuffer> O) override;
66 
67   /// Set the NotifyLoaded callback.
setNotifyLoaded(NotifyLoadedFunction NotifyLoaded)68   RTDyldObjectLinkingLayer &setNotifyLoaded(NotifyLoadedFunction NotifyLoaded) {
69     this->NotifyLoaded = std::move(NotifyLoaded);
70     return *this;
71   }
72 
73   /// Set the NotifyEmitted callback.
74   RTDyldObjectLinkingLayer &
setNotifyEmitted(NotifyEmittedFunction NotifyEmitted)75   setNotifyEmitted(NotifyEmittedFunction NotifyEmitted) {
76     this->NotifyEmitted = std::move(NotifyEmitted);
77     return *this;
78   }
79 
80   /// Set the 'ProcessAllSections' flag.
81   ///
82   /// If set to true, all sections in each object file will be allocated using
83   /// the memory manager, rather than just the sections required for execution.
84   ///
85   /// This is kludgy, and may be removed in the future.
setProcessAllSections(bool ProcessAllSections)86   RTDyldObjectLinkingLayer &setProcessAllSections(bool ProcessAllSections) {
87     this->ProcessAllSections = ProcessAllSections;
88     return *this;
89   }
90 
91   /// Instructs this RTDyldLinkingLayer2 instance to override the symbol flags
92   /// returned by RuntimeDyld for any given object file with the flags supplied
93   /// by the MaterializationResponsibility instance. This is a workaround to
94   /// support symbol visibility in COFF, which does not use the libObject's
95   /// SF_Exported flag. Use only when generating / adding COFF object files.
96   ///
97   /// FIXME: We should be able to remove this if/when COFF properly tracks
98   /// exported symbols.
99   RTDyldObjectLinkingLayer &
setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags)100   setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) {
101     this->OverrideObjectFlags = OverrideObjectFlags;
102     return *this;
103   }
104 
105   /// If set, this RTDyldObjectLinkingLayer instance will claim responsibility
106   /// for any symbols provided by a given object file that were not already in
107   /// the MaterializationResponsibility instance. Setting this flag allows
108   /// higher-level program representations (e.g. LLVM IR) to be added based on
109   /// only a subset of the symbols they provide, without having to write
110   /// intervening layers to scan and add the additional symbols. This trades
111   /// diagnostic quality for convenience however: If all symbols are enumerated
112   /// up-front then clashes can be detected and reported early (and usually
113   /// deterministically). If this option is set, clashes for the additional
114   /// symbols may not be detected until late, and detection may depend on
115   /// the flow of control through JIT'd code. Use with care.
116   RTDyldObjectLinkingLayer &
setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols)117   setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) {
118     this->AutoClaimObjectSymbols = AutoClaimObjectSymbols;
119     return *this;
120   }
121 
122   /// Register a JITEventListener.
123   void registerJITEventListener(JITEventListener &L);
124 
125   /// Unregister a JITEventListener.
126   void unregisterJITEventListener(JITEventListener &L);
127 
128 private:
129   using MemoryManagerUP = std::unique_ptr<RuntimeDyld::MemoryManager>;
130 
131   Error onObjLoad(MaterializationResponsibility &R,
132                   const object::ObjectFile &Obj,
133                   RuntimeDyld::MemoryManager &MemMgr,
134                   RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
135                   std::map<StringRef, JITEvaluatedSymbol> Resolved,
136                   std::set<StringRef> &InternalSymbols);
137 
138   void onObjEmit(MaterializationResponsibility &R,
139                  object::OwningBinary<object::ObjectFile> O,
140                  std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
141                  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
142                  Error Err);
143 
144   Error handleRemoveResources(ResourceKey K) override;
145   void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override;
146 
147   mutable std::mutex RTDyldLayerMutex;
148   GetMemoryManagerFunction GetMemoryManager;
149   NotifyLoadedFunction NotifyLoaded;
150   NotifyEmittedFunction NotifyEmitted;
151   bool ProcessAllSections = false;
152   bool OverrideObjectFlags = false;
153   bool AutoClaimObjectSymbols = false;
154   DenseMap<ResourceKey, std::vector<MemoryManagerUP>> MemMgrs;
155   std::vector<JITEventListener *> EventListeners;
156 };
157 
158 } // end namespace orc
159 } // end namespace llvm
160 
161 #endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
162