ObjectLinkingLayer.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. //===- ObjectLinkingLayer.h - Add object files to a JIT process -*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // Contains the definition for the object layer of the JIT.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
  14. #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
  15. #include "JITSymbol.h"
  16. #include "llvm/ADT/STLExtras.h"
  17. #include "llvm/ExecutionEngine/ExecutionEngine.h"
  18. #include "llvm/ExecutionEngine/SectionMemoryManager.h"
  19. #include <list>
  20. #include <memory>
  21. namespace llvm {
  22. namespace orc {
  23. class ObjectLinkingLayerBase {
  24. protected:
  25. /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
  26. ///
  27. /// An instance of this class will be created for each set of objects added
  28. /// via JITObjectLayer::addObjectSet. Deleting the instance (via
  29. /// removeObjectSet) frees its memory, removing all symbol definitions that
  30. /// had been provided by this instance. Higher level layers are responsible
  31. /// for taking any action required to handle the missing symbols.
  32. class LinkedObjectSet {
  33. LinkedObjectSet(const LinkedObjectSet&) = delete;
  34. void operator=(const LinkedObjectSet&) = delete;
  35. public:
  36. LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr,
  37. RuntimeDyld::SymbolResolver &Resolver)
  38. : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),
  39. State(Raw) {}
  40. virtual ~LinkedObjectSet() {}
  41. std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
  42. addObject(const object::ObjectFile &Obj) {
  43. return RTDyld->loadObject(Obj);
  44. }
  45. RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const {
  46. return RTDyld->getSymbol(Name);
  47. }
  48. bool NeedsFinalization() const { return (State == Raw); }
  49. virtual void Finalize() = 0;
  50. void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
  51. assert((State != Finalized) &&
  52. "Attempting to remap sections for finalized objects.");
  53. RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
  54. }
  55. void takeOwnershipOfBuffer(std::unique_ptr<MemoryBuffer> B) {
  56. OwnedBuffers.push_back(std::move(B));
  57. }
  58. protected:
  59. std::unique_ptr<RuntimeDyld> RTDyld;
  60. enum { Raw, Finalizing, Finalized } State;
  61. // FIXME: This ownership hack only exists because RuntimeDyldELF still
  62. // wants to be able to inspect the original object when resolving
  63. // relocations. As soon as that can be fixed this should be removed.
  64. std::vector<std::unique_ptr<MemoryBuffer>> OwnedBuffers;
  65. };
  66. typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
  67. public:
  68. /// @brief Handle to a set of loaded objects.
  69. typedef LinkedObjectSetListT::iterator ObjSetHandleT;
  70. // Ownership hack.
  71. // FIXME: Remove this as soon as RuntimeDyldELF can apply relocations without
  72. // referencing the original object.
  73. template <typename OwningMBSet>
  74. void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) {
  75. for (auto &MB : MBs)
  76. (*H)->takeOwnershipOfBuffer(std::move(MB));
  77. }
  78. };
  79. /// @brief Default (no-op) action to perform when loading objects.
  80. class DoNothingOnNotifyLoaded {
  81. public:
  82. template <typename ObjSetT, typename LoadResult>
  83. void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
  84. const LoadResult &) {}
  85. };
  86. /// @brief Bare bones object linking layer.
  87. ///
  88. /// This class is intended to be used as the base layer for a JIT. It allows
  89. /// object files to be loaded into memory, linked, and the addresses of their
  90. /// symbols queried. All objects added to this layer can see each other's
  91. /// symbols.
  92. template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
  93. class ObjectLinkingLayer : public ObjectLinkingLayerBase {
  94. private:
  95. template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
  96. class ConcreteLinkedObjectSet : public LinkedObjectSet {
  97. public:
  98. ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,
  99. SymbolResolverPtrT Resolver)
  100. : LinkedObjectSet(*MemMgr, *Resolver), MemMgr(std::move(MemMgr)),
  101. Resolver(std::move(Resolver)) { }
  102. void Finalize() override {
  103. State = Finalizing;
  104. RTDyld->resolveRelocations();
  105. RTDyld->registerEHFrames();
  106. MemMgr->finalizeMemory();
  107. OwnedBuffers.clear();
  108. State = Finalized;
  109. }
  110. private:
  111. MemoryManagerPtrT MemMgr;
  112. SymbolResolverPtrT Resolver;
  113. };
  114. template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
  115. std::unique_ptr<LinkedObjectSet>
  116. createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver) {
  117. typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;
  118. return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver));
  119. }
  120. public:
  121. /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
  122. /// RuntimeDyld::LoadedObjectInfo instances.
  123. typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
  124. LoadedObjInfoList;
  125. /// @brief Functor for receiving finalization notifications.
  126. typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
  127. /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
  128. /// and NotifyFinalized functors.
  129. ObjectLinkingLayer(
  130. NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
  131. NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
  132. : NotifyLoaded(std::move(NotifyLoaded)),
  133. NotifyFinalized(std::move(NotifyFinalized)) {}
  134. /// @brief Add a set of objects (or archives) that will be treated as a unit
  135. /// for the purposes of symbol lookup and memory management.
  136. ///
  137. /// @return A pair containing (1) A handle that can be used to free the memory
  138. /// allocated for the objects, and (2) a LoadedObjInfoList containing
  139. /// one LoadedObjInfo instance for each object at the corresponding
  140. /// index in the Objects list.
  141. ///
  142. /// This version of this method allows the client to pass in an
  143. /// RTDyldMemoryManager instance that will be used to allocate memory and look
  144. /// up external symbol addresses for the given objects.
  145. template <typename ObjSetT,
  146. typename MemoryManagerPtrT,
  147. typename SymbolResolverPtrT>
  148. ObjSetHandleT addObjectSet(const ObjSetT &Objects,
  149. MemoryManagerPtrT MemMgr,
  150. SymbolResolverPtrT Resolver) {
  151. ObjSetHandleT Handle =
  152. LinkedObjSetList.insert(
  153. LinkedObjSetList.end(),
  154. createLinkedObjectSet(std::move(MemMgr), std::move(Resolver)));
  155. LinkedObjectSet &LOS = **Handle;
  156. LoadedObjInfoList LoadedObjInfos;
  157. for (auto &Obj : Objects)
  158. LoadedObjInfos.push_back(LOS.addObject(*Obj));
  159. NotifyLoaded(Handle, Objects, LoadedObjInfos);
  160. return Handle;
  161. }
  162. /// @brief Remove the set of objects associated with handle H.
  163. ///
  164. /// All memory allocated for the objects will be freed, and the sections and
  165. /// symbols they provided will no longer be available. No attempt is made to
  166. /// re-emit the missing symbols, and any use of these symbols (directly or
  167. /// indirectly) will result in undefined behavior. If dependence tracking is
  168. /// required to detect or resolve such issues it should be added at a higher
  169. /// layer.
  170. void removeObjectSet(ObjSetHandleT H) {
  171. // How do we invalidate the symbols in H?
  172. LinkedObjSetList.erase(H);
  173. }
  174. /// @brief Search for the given named symbol.
  175. /// @param Name The name of the symbol to search for.
  176. /// @param ExportedSymbolsOnly If true, search only for exported symbols.
  177. /// @return A handle for the given named symbol, if it exists.
  178. JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
  179. for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
  180. ++I)
  181. if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
  182. return Symbol;
  183. return nullptr;
  184. }
  185. /// @brief Search for the given named symbol in the context of the set of
  186. /// loaded objects represented by the handle H.
  187. /// @param H The handle for the object set to search in.
  188. /// @param Name The name of the symbol to search for.
  189. /// @param ExportedSymbolsOnly If true, search only for exported symbols.
  190. /// @return A handle for the given named symbol, if it is found in the
  191. /// given object set.
  192. JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
  193. bool ExportedSymbolsOnly) {
  194. if (auto Sym = (*H)->getSymbol(Name)) {
  195. if (Sym.isExported() || !ExportedSymbolsOnly) {
  196. auto Addr = Sym.getAddress();
  197. auto Flags = Sym.getFlags();
  198. if (!(*H)->NeedsFinalization()) {
  199. // If this instance has already been finalized then we can just return
  200. // the address.
  201. return JITSymbol(Addr, Flags);
  202. } else {
  203. // If this instance needs finalization return a functor that will do
  204. // it. The functor still needs to double-check whether finalization is
  205. // required, in case someone else finalizes this set before the
  206. // functor is called.
  207. auto GetAddress =
  208. [this, Addr, H]() {
  209. if ((*H)->NeedsFinalization()) {
  210. (*H)->Finalize();
  211. if (NotifyFinalized)
  212. NotifyFinalized(H);
  213. }
  214. return Addr;
  215. };
  216. return JITSymbol(std::move(GetAddress), Flags);
  217. }
  218. }
  219. }
  220. return nullptr;
  221. }
  222. /// @brief Map section addresses for the objects associated with the handle H.
  223. void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
  224. TargetAddress TargetAddr) {
  225. (*H)->mapSectionAddress(LocalAddress, TargetAddr);
  226. }
  227. /// @brief Immediately emit and finalize the object set represented by the
  228. /// given handle.
  229. /// @param H Handle for object set to emit/finalize.
  230. void emitAndFinalize(ObjSetHandleT H) {
  231. (*H)->Finalize();
  232. if (NotifyFinalized)
  233. NotifyFinalized(H);
  234. }
  235. private:
  236. LinkedObjectSetListT LinkedObjSetList;
  237. NotifyLoadedFtor NotifyLoaded;
  238. NotifyFinalizedFtor NotifyFinalized;
  239. };
  240. } // End namespace orc.
  241. } // End namespace llvm
  242. #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H