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