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