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 "LookasideRTDyldMM.h"
18 #include "llvm/ExecutionEngine/ExecutionEngine.h"
19 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
25 class ObjectLinkingLayerBase {
27 /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
29 /// An instance of this class will be created for each set of objects added
30 /// via JITObjectLayer::addObjectSet. Deleting the instance (via
31 /// removeObjectSet) frees its memory, removing all symbol definitions that
32 /// had been provided by this instance. Higher level layers are responsible
33 /// for taking any action required to handle the missing symbols.
34 class LinkedObjectSet {
36 LinkedObjectSet(std::unique_ptr<RTDyldMemoryManager> MM)
37 : MM(std::move(MM)), RTDyld(llvm::make_unique<RuntimeDyld>(&*this->MM)),
40 std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
41 addObject(const object::ObjectFile &Obj) {
42 return RTDyld->loadObject(Obj);
45 uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
46 if (ExportedSymbolsOnly)
47 return RTDyld->getExportedSymbolLoadAddress(Name);
48 return RTDyld->getSymbolLoadAddress(Name);
51 bool NeedsFinalization() const { return (State == Raw); }
55 RTDyld->resolveRelocations();
56 RTDyld->registerEHFrames();
61 void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) {
62 assert((State != Finalized) &&
63 "Attempting to remap sections for finalized objects.");
64 RTDyld->mapSectionAddress(LocalAddress, TargetAddress);
68 std::unique_ptr<RTDyldMemoryManager> MM;
69 std::unique_ptr<RuntimeDyld> RTDyld;
70 enum { Raw, Finalizing, Finalized } State;
73 typedef std::list<LinkedObjectSet> LinkedObjectSetListT;
76 /// @brief Handle to a set of loaded objects.
77 typedef typename LinkedObjectSetListT::iterator ObjSetHandleT;
80 /// @brief Default (no-op) action to perform when loading objects.
81 class DoNothingOnNotifyLoaded {
83 template <typename ObjSetT, typename LoadResult>
84 void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
85 const LoadResult &) {}
88 /// @brief Bare bones object linking layer.
90 /// This class is intended to be used as the base layer for a JIT. It allows
91 /// object files to be loaded into memory, linked, and the addresses of their
92 /// symbols queried. All objects added to this layer can see each other's
94 template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
95 class ObjectLinkingLayer : public ObjectLinkingLayerBase {
97 /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
98 /// RuntimeDyld::LoadedObjectInfo instances.
99 typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
102 /// @brief Default construct an ObjectLinkingLayer.
103 ObjectLinkingLayer() {}
105 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded
107 ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded)
108 : NotifyLoaded(std::move(NotifyLoaded)) {}
110 /// @brief Construct an ObjectLinkingLayer with the given NotifyFinalized
112 ObjectLinkingLayer(std::function<void(ObjSetHandleT)> NotifyFinalized)
113 : NotifyFinalized(std::move(NotifyFinalized)) {}
115 /// @brief Construct an ObjectLinkingLayer with the given CreateMemoryManager
118 std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
119 : CreateMemoryManager(std::move(CreateMemoryManager)) {}
121 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded and
122 /// NotifyFinalized functors.
123 ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded,
124 std::function<void(ObjSetHandleT)> NotifyFinalized)
125 : NotifyLoaded(std::move(NotifyLoaded)),
126 NotifyFinalized(std::move(NotifyFinalized)) {}
128 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded and
129 /// CreateMemoryManager functors.
131 NotifyLoadedFtor NotifyLoaded,
132 std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
133 : NotifyLoaded(std::move(NotifyLoaded)),
134 CreateMemoryManager(std::move(CreateMemoryManager)) {}
136 /// @brief Construct an ObjectLinkingLayer with the given NotifyFinalized and
137 /// CreateMemoryManager functors.
139 std::function<void(ObjSetHandleT)> NotifyFinalized,
140 std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
141 : NotifyFinalized(std::move(NotifyFinalized)),
142 CreateMemoryManager(std::move(CreateMemoryManager)) {}
144 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
145 /// NotifyFinalized and CreateMemoryManager functors.
147 NotifyLoadedFtor NotifyLoaded,
148 std::function<void(ObjSetHandleT)> NotifyFinalized,
149 std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
150 : NotifyLoaded(std::move(NotifyLoaded)),
151 NotifyFinalized(std::move(NotifyFinalized)),
152 CreateMemoryManager(std::move(CreateMemoryManager)) {}
154 /// @brief Add a set of objects (or archives) that will be treated as a unit
155 /// for the purposes of symbol lookup and memory management.
157 /// @return A pair containing (1) A handle that can be used to free the memory
158 /// allocated for the objects, and (2) a LoadedObjInfoList containing
159 /// one LoadedObjInfo instance for each object at the corresponding
160 /// index in the Objects list.
162 /// This version of this method allows the client to pass in an
163 /// RTDyldMemoryManager instance that will be used to allocate memory and look
164 /// up external symbol addresses for the given objects.
165 template <typename ObjSetT>
166 ObjSetHandleT addObjectSet(const ObjSetT &Objects,
167 std::unique_ptr<RTDyldMemoryManager> MM) {
170 assert(CreateMemoryManager &&
171 "No memory manager or memory manager creator provided.");
172 MM = CreateMemoryManager();
175 ObjSetHandleT Handle = LinkedObjSetList.insert(
176 LinkedObjSetList.end(), LinkedObjectSet(std::move(MM)));
177 LinkedObjectSet &LOS = *Handle;
178 LoadedObjInfoList LoadedObjInfos;
180 for (auto &Obj : Objects)
181 LoadedObjInfos.push_back(LOS.addObject(*Obj));
183 NotifyLoaded(Handle, Objects, LoadedObjInfos);
188 /// @brief Map section addresses for the objects associated with the handle H.
189 void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
190 uint64_t TargetAddress) {
191 H->mapSectionAddress(LocalAddress, TargetAddress);
194 /// @brief Remove the set of objects associated with handle H.
196 /// All memory allocated for the objects will be freed, and the sections and
197 /// symbols they provided will no longer be available. No attempt is made to
198 /// re-emit the missing symbols, and any use of these symbols (directly or
199 /// indirectly) will result in undefined behavior. If dependence tracking is
200 /// required to detect or resolve such issues it should be added at a higher
202 void removeObjectSet(ObjSetHandleT H) {
203 // How do we invalidate the symbols in H?
204 LinkedObjSetList.erase(H);
207 /// @brief Get the address of a loaded symbol.
209 /// @return The address in the target process's address space of the named
210 /// symbol. Null if no such symbol is known.
212 /// This method will trigger the finalization of the linked object set
213 /// containing the definition of the given symbol, if it is found.
214 uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
215 for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
217 if (uint64_t Addr = lookupSymbolAddressIn(I, Name, ExportedSymbolsOnly))
223 /// @brief Search for a given symbol in the context of the set of loaded
224 /// objects represented by the handle H.
226 /// @return The address in the target process's address space of the named
227 /// symbol. Null if the given object set does not contain a definition
230 /// This method will trigger the finalization of the linked object set
231 /// represented by the handle H if that set contains the requested symbol.
232 uint64_t lookupSymbolAddressIn(ObjSetHandleT H, StringRef Name,
233 bool ExportedSymbolsOnly) {
234 if (uint64_t Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly)) {
235 if (H->NeedsFinalization()) {
246 LinkedObjectSetListT LinkedObjSetList;
247 NotifyLoadedFtor NotifyLoaded;
248 std::function<void(ObjSetHandleT)> NotifyFinalized;
249 std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager;
252 } // end namespace llvm
254 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H