LLVM  3.7.0
ObjectLinkingLayer.h
Go to the documentation of this file.
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 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
16 
17 #include "JITSymbol.h"
18 #include "llvm/ADT/STLExtras.h"
21 #include <list>
22 #include <memory>
23 
24 namespace llvm {
25 namespace orc {
26 
28 protected:
29 
30  /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
31  ///
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.
38  LinkedObjectSet(const LinkedObjectSet&) = delete;
39  void operator=(const LinkedObjectSet&) = delete;
40  public:
43  : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),
44  State(Raw) {}
45 
46  virtual ~LinkedObjectSet() {}
47 
48  std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
50  return RTDyld->loadObject(Obj);
51  }
52 
54  return RTDyld->getSymbol(Name);
55  }
56 
57  bool NeedsFinalization() const { return (State == Raw); }
58 
59  virtual void Finalize() = 0;
60 
61  void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
62  assert((State != Finalized) &&
63  "Attempting to remap sections for finalized objects.");
64  RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
65  }
66 
67  void takeOwnershipOfBuffer(std::unique_ptr<MemoryBuffer> B) {
68  OwnedBuffers.push_back(std::move(B));
69  }
70 
71  protected:
72  std::unique_ptr<RuntimeDyld> RTDyld;
74 
75  // FIXME: This ownership hack only exists because RuntimeDyldELF still
76  // wants to be able to inspect the original object when resolving
77  // relocations. As soon as that can be fixed this should be removed.
78  std::vector<std::unique_ptr<MemoryBuffer>> OwnedBuffers;
79  };
80 
81  typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
82 
83 public:
84  /// @brief Handle to a set of loaded objects.
85  typedef LinkedObjectSetListT::iterator ObjSetHandleT;
86 
87  // Ownership hack.
88  // FIXME: Remove this as soon as RuntimeDyldELF can apply relocations without
89  // referencing the original object.
90  template <typename OwningMBSet>
91  void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) {
92  for (auto &MB : MBs)
93  (*H)->takeOwnershipOfBuffer(std::move(MB));
94  }
95 
96 };
97 
98 /// @brief Default (no-op) action to perform when loading objects.
100 public:
101  template <typename ObjSetT, typename LoadResult>
103  const LoadResult &) {}
104 };
105 
106 /// @brief Bare bones object linking layer.
107 ///
108 /// This class is intended to be used as the base layer for a JIT. It allows
109 /// object files to be loaded into memory, linked, and the addresses of their
110 /// symbols queried. All objects added to this layer can see each other's
111 /// symbols.
112 template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
114 private:
115 
116  template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
117  class ConcreteLinkedObjectSet : public LinkedObjectSet {
118  public:
119  ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,
120  SymbolResolverPtrT Resolver)
121  : LinkedObjectSet(*MemMgr, *Resolver), MemMgr(std::move(MemMgr)),
122  Resolver(std::move(Resolver)) { }
123 
124  void Finalize() override {
125  State = Finalizing;
126  RTDyld->resolveRelocations();
127  RTDyld->registerEHFrames();
128  MemMgr->finalizeMemory();
129  OwnedBuffers.clear();
130  State = Finalized;
131  }
132 
133  private:
134  MemoryManagerPtrT MemMgr;
135  SymbolResolverPtrT Resolver;
136  };
137 
138  template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
139  std::unique_ptr<LinkedObjectSet>
140  createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver) {
141  typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;
142  return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver));
143  }
144 
145 public:
146 
147  /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
148  /// RuntimeDyld::LoadedObjectInfo instances.
149  typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
151 
152  /// @brief Functor for receiving finalization notifications.
153  typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
154 
155  /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
156  /// and NotifyFinalized functors.
158  NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
159  NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
160  : NotifyLoaded(std::move(NotifyLoaded)),
161  NotifyFinalized(std::move(NotifyFinalized)) {}
162 
163  /// @brief Add a set of objects (or archives) that will be treated as a unit
164  /// for the purposes of symbol lookup and memory management.
165  ///
166  /// @return A pair containing (1) A handle that can be used to free the memory
167  /// allocated for the objects, and (2) a LoadedObjInfoList containing
168  /// one LoadedObjInfo instance for each object at the corresponding
169  /// index in the Objects list.
170  ///
171  /// This version of this method allows the client to pass in an
172  /// RTDyldMemoryManager instance that will be used to allocate memory and look
173  /// up external symbol addresses for the given objects.
174  template <typename ObjSetT,
175  typename MemoryManagerPtrT,
176  typename SymbolResolverPtrT>
177  ObjSetHandleT addObjectSet(const ObjSetT &Objects,
178  MemoryManagerPtrT MemMgr,
179  SymbolResolverPtrT Resolver) {
180  ObjSetHandleT Handle =
181  LinkedObjSetList.insert(
182  LinkedObjSetList.end(),
183  createLinkedObjectSet(std::move(MemMgr), std::move(Resolver)));
184 
185  LinkedObjectSet &LOS = **Handle;
186  LoadedObjInfoList LoadedObjInfos;
187 
188  for (auto &Obj : Objects)
189  LoadedObjInfos.push_back(LOS.addObject(*Obj));
190 
191  NotifyLoaded(Handle, Objects, LoadedObjInfos);
192 
193  return Handle;
194  }
195 
196  /// @brief Remove the set of objects associated with handle H.
197  ///
198  /// All memory allocated for the objects will be freed, and the sections and
199  /// symbols they provided will no longer be available. No attempt is made to
200  /// re-emit the missing symbols, and any use of these symbols (directly or
201  /// indirectly) will result in undefined behavior. If dependence tracking is
202  /// required to detect or resolve such issues it should be added at a higher
203  /// layer.
205  // How do we invalidate the symbols in H?
206  LinkedObjSetList.erase(H);
207  }
208 
209  /// @brief Search for the given named symbol.
210  /// @param Name The name of the symbol to search for.
211  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
212  /// @return A handle for the given named symbol, if it exists.
213  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
214  for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
215  ++I)
216  if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
217  return Symbol;
218 
219  return nullptr;
220  }
221 
222  /// @brief Search for the given named symbol in the context of the set of
223  /// loaded objects represented by the handle H.
224  /// @param H The handle for the object set to search in.
225  /// @param Name The name of the symbol to search for.
226  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
227  /// @return A handle for the given named symbol, if it is found in the
228  /// given object set.
230  bool ExportedSymbolsOnly) {
231  if (auto Sym = (*H)->getSymbol(Name)) {
232  if (Sym.isExported() || !ExportedSymbolsOnly) {
233  auto Addr = Sym.getAddress();
234  auto Flags = Sym.getFlags();
235  if (!(*H)->NeedsFinalization()) {
236  // If this instance has already been finalized then we can just return
237  // the address.
238  return JITSymbol(Addr, Flags);
239  } else {
240  // If this instance needs finalization return a functor that will do
241  // it. The functor still needs to double-check whether finalization is
242  // required, in case someone else finalizes this set before the
243  // functor is called.
244  auto GetAddress =
245  [this, Addr, H]() {
246  if ((*H)->NeedsFinalization()) {
247  (*H)->Finalize();
248  if (NotifyFinalized)
249  NotifyFinalized(H);
250  }
251  return Addr;
252  };
253  return JITSymbol(std::move(GetAddress), Flags);
254  }
255  }
256  }
257  return nullptr;
258  }
259 
260  /// @brief Map section addresses for the objects associated with the handle H.
261  void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
262  TargetAddress TargetAddr) {
263  (*H)->mapSectionAddress(LocalAddress, TargetAddr);
264  }
265 
266  /// @brief Immediately emit and finalize the object set represented by the
267  /// given handle.
268  /// @param H Handle for object set to emit/finalize.
270  (*H)->Finalize();
271  if (NotifyFinalized)
272  NotifyFinalized(H);
273  }
274 
275 private:
276  LinkedObjectSetListT LinkedObjSetList;
277  NotifyLoadedFtor NotifyLoaded;
278  NotifyFinalizedFtor NotifyFinalized;
279 };
280 
281 } // End namespace orc.
282 } // End namespace llvm
283 
284 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded=NotifyLoadedFtor(), NotifyFinalizedFtor NotifyFinalized=NotifyFinalizedFtor())
Construct an ObjectLinkingLayer with the given NotifyLoaded, and NotifyFinalized functors.
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
TargetAddress getAddress()
Get the address of the symbol in the target address space.
Definition: JITSymbol.h:60
This class is the base class for all object file types.
Definition: ObjectFile.h:176
ObjSetHandleT addObjectSet(const ObjSetT &Objects, MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver)
Add a set of objects (or archives) that will be treated as a unit for the purposes of symbol lookup a...
RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const
void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, TargetAddress TargetAddr)
Map section addresses for the objects associated with the handle H.
std::vector< std::unique_ptr< MemoryBuffer > > OwnedBuffers
Bare bones object linking layer.
std::unique_ptr< RuntimeDyld::LoadedObjectInfo > addObject(const object::ObjectFile &Obj)
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&...args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
Definition: STLExtras.h:354
std::list< std::unique_ptr< LinkedObjectSet > > LinkedObjectSetListT
#define H(x, y, z)
Definition: MD5.cpp:53
void removeObjectSet(ObjSetHandleT H)
Remove the set of objects associated with handle H.
Represents a symbol in the JIT.
Definition: JITSymbol.h:29
Holds a set of objects to be allocated/linked as a unit in the JIT.
void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs)
JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol in the context of the set of loaded objects represented by the hand...
Default (no-op) action to perform when loading objects.
uint64_t TargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:26
std::function< void(ObjSetHandleT)> NotifyFinalizedFtor
Functor for receiving finalization notifications.
void emitAndFinalize(ObjSetHandleT H)
Immediately emit and finalize the object set represented by the given handle.
void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &, const LoadResult &)
#define I(x, y, z)
Definition: MD5.cpp:54
Information about a named symbol.
Definition: RuntimeDyld.h:47
std::vector< std::unique_ptr< RuntimeDyld::LoadedObjectInfo > > LoadedObjInfoList
LoadedObjectInfo list.
void takeOwnershipOfBuffer(std::unique_ptr< MemoryBuffer > B)
enum llvm::orc::ObjectLinkingLayerBase::LinkedObjectSet::@57 State
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr)
LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr, RuntimeDyld::SymbolResolver &Resolver)
LinkedObjectSetListT::iterator ObjSetHandleT
Handle to a set of loaded objects.