1 //===- ObjectLinkingLayer.h - Add object files to a JIT process -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Contains the definition for the object layer of the JIT.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
17 #include "JITSymbol.h"
18 #include "LookasideRTDyldMM.h"
19 #include "llvm/ExecutionEngine/ExecutionEngine.h"
20 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
27 class ObjectLinkingLayerBase {
30 /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
32 /// An instance of this class will be created for each set of objects added
33 /// via JITObjectLayer::addObjectSet. Deleting the instance (via
34 /// removeObjectSet) frees its memory, removing all symbol definitions that
35 /// had been provided by this instance. Higher level layers are responsible
36 /// for taking any action required to handle the missing symbols.
37 class LinkedObjectSet {
38 LinkedObjectSet(const LinkedObjectSet&) = delete;
39 void operator=(const LinkedObjectSet&) = delete;
41 LinkedObjectSet(std::unique_ptr<RTDyldMemoryManager> MM)
42 : MM(std::move(MM)), RTDyld(llvm::make_unique<RuntimeDyld>(&*this->MM)),
45 // MSVC 2012 cannot infer a move constructor, so write it out longhand.
46 LinkedObjectSet(LinkedObjectSet &&O)
47 : MM(std::move(O.MM)), RTDyld(std::move(O.RTDyld)), State(O.State) {}
49 std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
50 addObject(const object::ObjectFile &Obj) {
51 return RTDyld->loadObject(Obj);
54 RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const {
55 return RTDyld->getSymbol(Name);
58 bool NeedsFinalization() const { return (State == Raw); }
62 RTDyld->resolveRelocations();
63 RTDyld->registerEHFrames();
69 void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
70 assert((State != Finalized) &&
71 "Attempting to remap sections for finalized objects.");
72 RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
75 void takeOwnershipOfBuffer(std::unique_ptr<MemoryBuffer> B) {
76 OwnedBuffers.push_back(std::move(B));
80 std::unique_ptr<RTDyldMemoryManager> MM;
81 std::unique_ptr<RuntimeDyld> RTDyld;
82 enum { Raw, Finalizing, Finalized } State;
84 // FIXME: This ownership hack only exists because RuntimeDyldELF still
85 // wants to be able to inspect the original object when resolving
86 // relocations. As soon as that can be fixed this should be removed.
87 std::vector<std::unique_ptr<MemoryBuffer>> OwnedBuffers;
90 typedef std::list<LinkedObjectSet> LinkedObjectSetListT;
93 /// @brief Handle to a set of loaded objects.
94 typedef LinkedObjectSetListT::iterator ObjSetHandleT;
97 // FIXME: Remove this as soon as RuntimeDyldELF can apply relocations without
98 // referencing the original object.
99 template <typename OwningMBSet>
100 void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) {
102 H->takeOwnershipOfBuffer(std::move(MB));
107 /// @brief Default (no-op) action to perform when loading objects.
108 class DoNothingOnNotifyLoaded {
110 template <typename ObjSetT, typename LoadResult>
111 void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
112 const LoadResult &) {}
115 /// @brief Bare bones object linking layer.
117 /// This class is intended to be used as the base layer for a JIT. It allows
118 /// object files to be loaded into memory, linked, and the addresses of their
119 /// symbols queried. All objects added to this layer can see each other's
121 template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
122 class ObjectLinkingLayer : public ObjectLinkingLayerBase {
125 /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
126 /// RuntimeDyld::LoadedObjectInfo instances.
127 typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
130 /// @brief Functor to create RTDyldMemoryManager instances.
131 typedef std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateRTDyldMMFtor;
133 /// @brief Functor for receiving finalization notifications.
134 typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
136 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
137 /// NotifyFinalized and CreateMemoryManager functors.
139 CreateRTDyldMMFtor CreateMemoryManager = CreateRTDyldMMFtor(),
140 NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
141 NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
142 : NotifyLoaded(std::move(NotifyLoaded)),
143 NotifyFinalized(std::move(NotifyFinalized)),
144 CreateMemoryManager(std::move(CreateMemoryManager)) {}
146 /// @brief Add a set of objects (or archives) that will be treated as a unit
147 /// for the purposes of symbol lookup and memory management.
149 /// @return A pair containing (1) A handle that can be used to free the memory
150 /// allocated for the objects, and (2) a LoadedObjInfoList containing
151 /// one LoadedObjInfo instance for each object at the corresponding
152 /// index in the Objects list.
154 /// This version of this method allows the client to pass in an
155 /// RTDyldMemoryManager instance that will be used to allocate memory and look
156 /// up external symbol addresses for the given objects.
157 template <typename ObjSetT>
158 ObjSetHandleT addObjectSet(const ObjSetT &Objects,
159 std::unique_ptr<RTDyldMemoryManager> MM) {
162 assert(CreateMemoryManager &&
163 "No memory manager or memory manager creator provided.");
164 MM = CreateMemoryManager();
167 ObjSetHandleT Handle = LinkedObjSetList.insert(
168 LinkedObjSetList.end(), LinkedObjectSet(std::move(MM)));
169 LinkedObjectSet &LOS = *Handle;
170 LoadedObjInfoList LoadedObjInfos;
172 for (auto &Obj : Objects)
173 LoadedObjInfos.push_back(LOS.addObject(*Obj));
175 NotifyLoaded(Handle, Objects, LoadedObjInfos);
180 /// @brief Remove the set of objects associated with handle H.
182 /// All memory allocated for the objects will be freed, and the sections and
183 /// symbols they provided will no longer be available. No attempt is made to
184 /// re-emit the missing symbols, and any use of these symbols (directly or
185 /// indirectly) will result in undefined behavior. If dependence tracking is
186 /// required to detect or resolve such issues it should be added at a higher
188 void removeObjectSet(ObjSetHandleT H) {
189 // How do we invalidate the symbols in H?
190 LinkedObjSetList.erase(H);
193 /// @brief Search for the given named symbol.
194 /// @param Name The name of the symbol to search for.
195 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
196 /// @return A handle for the given named symbol, if it exists.
197 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
198 for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
200 if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
206 /// @brief Search for the given named symbol in the context of the set of
207 /// loaded objects represented by the handle H.
208 /// @param H The handle for the object set to search in.
209 /// @param Name The name of the symbol to search for.
210 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
211 /// @return A handle for the given named symbol, if it is found in the
212 /// given object set.
213 JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
214 bool ExportedSymbolsOnly) {
215 if (auto Sym = H->getSymbol(Name)) {
216 if (Sym.isExported() || !ExportedSymbolsOnly) {
217 auto Addr = Sym.getAddress();
218 auto Flags = Sym.getFlags();
219 if (!H->NeedsFinalization()) {
220 // If this instance has already been finalized then we can just return
222 return JITSymbol(Addr, Flags);
224 // If this instance needs finalization return a functor that will do
225 // it. The functor still needs to double-check whether finalization is
226 // required, in case someone else finalizes this set before the
227 // functor is called.
230 if (H->NeedsFinalization()) {
237 return JITSymbol(std::move(GetAddress), Flags);
244 /// @brief Map section addresses for the objects associated with the handle H.
245 void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
246 TargetAddress TargetAddr) {
247 H->mapSectionAddress(LocalAddress, TargetAddr);
250 /// @brief Immediately emit and finalize the object set represented by the
252 /// @param H Handle for object set to emit/finalize.
253 void emitAndFinalize(ObjSetHandleT H) {
260 LinkedObjectSetListT LinkedObjSetList;
261 NotifyLoadedFtor NotifyLoaded;
262 NotifyFinalizedFtor NotifyFinalized;
263 CreateRTDyldMMFtor CreateMemoryManager;
266 } // End namespace orc.
267 } // End namespace llvm
269 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H