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 "llvm/ADT/STLExtras.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(RuntimeDyld::MemoryManager &MemMgr,
42 RuntimeDyld::SymbolResolver &Resolver,
43 bool ProcessAllSections)
44 : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),
46 RTDyld->setProcessAllSections(ProcessAllSections);
49 virtual ~LinkedObjectSet() {}
51 std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
52 addObject(const object::ObjectFile &Obj) {
53 return RTDyld->loadObject(Obj);
56 RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const {
57 return RTDyld->getSymbol(Name);
60 bool NeedsFinalization() const { return (State == Raw); }
62 virtual void Finalize() = 0;
64 void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
65 assert((State != Finalized) &&
66 "Attempting to remap sections for finalized objects.");
67 RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
71 std::unique_ptr<RuntimeDyld> RTDyld;
72 enum { Raw, Finalizing, Finalized } State;
75 typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
78 /// @brief Handle to a set of loaded objects.
79 typedef LinkedObjectSetListT::iterator ObjSetHandleT;
82 /// @brief Default (no-op) action to perform when loading objects.
83 class DoNothingOnNotifyLoaded {
85 template <typename ObjSetT, typename LoadResult>
86 void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
87 const LoadResult &) {}
90 /// @brief Bare bones object linking layer.
92 /// This class is intended to be used as the base layer for a JIT. It allows
93 /// object files to be loaded into memory, linked, and the addresses of their
94 /// symbols queried. All objects added to this layer can see each other's
96 template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
97 class ObjectLinkingLayer : public ObjectLinkingLayerBase {
100 template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
101 class ConcreteLinkedObjectSet : public LinkedObjectSet {
103 ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,
104 SymbolResolverPtrT Resolver,
105 bool ProcessAllSections)
106 : LinkedObjectSet(*MemMgr, *Resolver, ProcessAllSections),
107 MemMgr(std::move(MemMgr)), Resolver(std::move(Resolver)) { }
109 void Finalize() override {
111 RTDyld->finalizeWithMemoryManagerLocking();
116 MemoryManagerPtrT MemMgr;
117 SymbolResolverPtrT Resolver;
120 template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
121 std::unique_ptr<LinkedObjectSet>
122 createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver,
123 bool ProcessAllSections) {
124 typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;
125 return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver),
131 /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
132 /// RuntimeDyld::LoadedObjectInfo instances.
133 typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
136 /// @brief Functor for receiving finalization notifications.
137 typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
139 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
140 /// and NotifyFinalized functors.
142 NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
143 NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
144 : NotifyLoaded(std::move(NotifyLoaded)),
145 NotifyFinalized(std::move(NotifyFinalized)),
146 ProcessAllSections(false) {}
148 /// @brief Set the 'ProcessAllSections' flag.
150 /// If set to true, all sections in each object file will be allocated using
151 /// the memory manager, rather than just the sections required for execution.
153 /// This is kludgy, and may be removed in the future.
154 void setProcessAllSections(bool ProcessAllSections) {
155 this->ProcessAllSections = ProcessAllSections;
158 /// @brief Add a set of objects (or archives) that will be treated as a unit
159 /// for the purposes of symbol lookup and memory management.
161 /// @return A pair containing (1) A handle that can be used to free the memory
162 /// allocated for the objects, and (2) a LoadedObjInfoList containing
163 /// one LoadedObjInfo instance for each object at the corresponding
164 /// index in the Objects list.
166 /// This version of this method allows the client to pass in an
167 /// RTDyldMemoryManager instance that will be used to allocate memory and look
168 /// up external symbol addresses for the given objects.
169 template <typename ObjSetT,
170 typename MemoryManagerPtrT,
171 typename SymbolResolverPtrT>
172 ObjSetHandleT addObjectSet(const ObjSetT &Objects,
173 MemoryManagerPtrT MemMgr,
174 SymbolResolverPtrT Resolver) {
175 ObjSetHandleT Handle =
176 LinkedObjSetList.insert(
177 LinkedObjSetList.end(),
178 createLinkedObjectSet(std::move(MemMgr), std::move(Resolver),
179 ProcessAllSections));
181 LinkedObjectSet &LOS = **Handle;
182 LoadedObjInfoList LoadedObjInfos;
184 for (auto &Obj : Objects)
185 LoadedObjInfos.push_back(LOS.addObject(*Obj));
187 NotifyLoaded(Handle, Objects, LoadedObjInfos);
192 /// @brief Remove the set of objects associated with handle H.
194 /// All memory allocated for the objects will be freed, and the sections and
195 /// symbols they provided will no longer be available. No attempt is made to
196 /// re-emit the missing symbols, and any use of these symbols (directly or
197 /// indirectly) will result in undefined behavior. If dependence tracking is
198 /// required to detect or resolve such issues it should be added at a higher
200 void removeObjectSet(ObjSetHandleT H) {
201 // How do we invalidate the symbols in H?
202 LinkedObjSetList.erase(H);
205 /// @brief Search for the given named symbol.
206 /// @param Name The name of the symbol to search for.
207 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
208 /// @return A handle for the given named symbol, if it exists.
209 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
210 for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
212 if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
218 /// @brief Search for the given named symbol in the context of the set of
219 /// loaded objects represented by the handle H.
220 /// @param H The handle for the object set to search in.
221 /// @param Name The name of the symbol to search for.
222 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
223 /// @return A handle for the given named symbol, if it is found in the
224 /// given object set.
225 JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
226 bool ExportedSymbolsOnly) {
227 if (auto Sym = (*H)->getSymbol(Name)) {
228 if (Sym.isExported() || !ExportedSymbolsOnly) {
229 auto Addr = Sym.getAddress();
230 auto Flags = Sym.getFlags();
231 if (!(*H)->NeedsFinalization()) {
232 // If this instance has already been finalized then we can just return
234 return JITSymbol(Addr, Flags);
236 // If this instance needs finalization return a functor that will do
237 // it. The functor still needs to double-check whether finalization is
238 // required, in case someone else finalizes this set before the
239 // functor is called.
242 if ((*H)->NeedsFinalization()) {
249 return JITSymbol(std::move(GetAddress), Flags);
256 /// @brief Map section addresses for the objects associated with the handle H.
257 void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
258 TargetAddress TargetAddr) {
259 (*H)->mapSectionAddress(LocalAddress, TargetAddr);
262 /// @brief Immediately emit and finalize the object set represented by the
264 /// @param H Handle for object set to emit/finalize.
265 void emitAndFinalize(ObjSetHandleT H) {
272 LinkedObjectSetListT LinkedObjSetList;
273 NotifyLoadedFtor NotifyLoaded;
274 NotifyFinalizedFtor NotifyFinalized;
275 bool ProcessAllSections;
278 } // End namespace orc.
279 } // End namespace llvm
281 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H