LLVM  4.0.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 "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/ADT/StringRef.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Support/Error.h"
26 #include <cassert>
27 #include <algorithm>
28 #include <functional>
29 #include <list>
30 #include <memory>
31 #include <string>
32 #include <utility>
33 #include <vector>
34 
35 namespace llvm {
36 namespace orc {
37 
39 protected:
40  /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
41  ///
42  /// An instance of this class will be created for each set of objects added
43  /// via JITObjectLayer::addObjectSet. Deleting the instance (via
44  /// removeObjectSet) frees its memory, removing all symbol definitions that
45  /// had been provided by this instance. Higher level layers are responsible
46  /// for taking any action required to handle the missing symbols.
48  public:
49  LinkedObjectSet() = default;
50  LinkedObjectSet(const LinkedObjectSet&) = delete;
51  void operator=(const LinkedObjectSet&) = delete;
52  virtual ~LinkedObjectSet() = default;
53 
54  virtual void finalize() = 0;
55 
57  getSymbolMaterializer(std::string Name) = 0;
58 
59  virtual void mapSectionAddress(const void *LocalAddress,
60  JITTargetAddress TargetAddr) const = 0;
61 
62  JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
63  auto SymEntry = SymbolTable.find(Name);
64  if (SymEntry == SymbolTable.end())
65  return nullptr;
66  if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
67  return nullptr;
68  if (!Finalized)
69  return JITSymbol(getSymbolMaterializer(Name),
70  SymEntry->second.getFlags());
71  return JITSymbol(SymEntry->second);
72  }
73 
74  protected:
76  bool Finalized = false;
77  };
78 
79  typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
80 
81 public:
82  /// @brief Handle to a set of loaded objects.
83  typedef LinkedObjectSetListT::iterator ObjSetHandleT;
84 };
85 
86 /// @brief Default (no-op) action to perform when loading objects.
88 public:
89  template <typename ObjSetT, typename LoadResult>
91  const LoadResult &) {}
92 };
93 
94 /// @brief Bare bones object linking layer.
95 ///
96 /// This class is intended to be used as the base layer for a JIT. It allows
97 /// object files to be loaded into memory, linked, and the addresses of their
98 /// symbols queried. All objects added to this layer can see each other's
99 /// symbols.
100 template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
102 public:
103  /// @brief Functor for receiving finalization notifications.
104  typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
105 
106 private:
107  template <typename ObjSetT, typename MemoryManagerPtrT,
108  typename SymbolResolverPtrT, typename FinalizerFtor>
109  class ConcreteLinkedObjectSet : public LinkedObjectSet {
110  public:
111  ConcreteLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
112  SymbolResolverPtrT Resolver,
113  FinalizerFtor Finalizer,
114  bool ProcessAllSections)
115  : MemMgr(std::move(MemMgr)),
116  PFC(llvm::make_unique<PreFinalizeContents>(std::move(Objects),
117  std::move(Resolver),
118  std::move(Finalizer),
119  ProcessAllSections)) {
120  buildInitialSymbolTable(PFC->Objects);
121  }
122 
123  void setHandle(ObjSetHandleT H) {
124  PFC->Handle = H;
125  }
126 
127  void finalize() override {
128  assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
129 
130  RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver);
131  RTDyld.setProcessAllSections(PFC->ProcessAllSections);
132  PFC->RTDyld = &RTDyld;
133 
134  this->Finalized = true;
135  PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Objects),
136  [&]() {
137  this->updateSymbolTable(RTDyld);
138  });
139 
140  // Release resources.
141  PFC = nullptr;
142  }
143 
144  JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
145  return
146  [this, Name]() {
147  // The symbol may be materialized between the creation of this lambda
148  // and its execution, so we need to double check.
149  if (!this->Finalized)
150  this->finalize();
151  return this->getSymbol(Name, false).getAddress();
152  };
153  }
154 
155  void mapSectionAddress(const void *LocalAddress,
156  JITTargetAddress TargetAddr) const override {
157  assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
158  assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObjectSet");
159  PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
160  }
161 
162  private:
163  void buildInitialSymbolTable(const ObjSetT &Objects) {
164  for (const auto &Obj : Objects)
165  for (auto &Symbol : getObject(*Obj).symbols()) {
166  if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
167  continue;
168  Expected<StringRef> SymbolName = Symbol.getName();
169  // FIXME: Raise an error for bad symbols.
170  if (!SymbolName) {
171  consumeError(SymbolName.takeError());
172  continue;
173  }
175  SymbolTable.insert(
176  std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
177  }
178  }
179 
180  void updateSymbolTable(const RuntimeDyld &RTDyld) {
181  for (auto &SymEntry : SymbolTable)
182  SymEntry.second = RTDyld.getSymbol(SymEntry.first());
183  }
184 
185  // Contains the information needed prior to finalization: the object files,
186  // memory manager, resolver, and flags needed for RuntimeDyld.
187  struct PreFinalizeContents {
188  PreFinalizeContents(ObjSetT Objects, SymbolResolverPtrT Resolver,
189  FinalizerFtor Finalizer, bool ProcessAllSections)
190  : Objects(std::move(Objects)), Resolver(std::move(Resolver)),
191  Finalizer(std::move(Finalizer)),
192  ProcessAllSections(ProcessAllSections) {}
193 
194  ObjSetT Objects;
195  SymbolResolverPtrT Resolver;
196  FinalizerFtor Finalizer;
197  bool ProcessAllSections;
198  ObjSetHandleT Handle;
199  RuntimeDyld *RTDyld;
200  };
201 
202  MemoryManagerPtrT MemMgr;
203  std::unique_ptr<PreFinalizeContents> PFC;
204  };
205 
206  template <typename ObjSetT, typename MemoryManagerPtrT,
207  typename SymbolResolverPtrT, typename FinalizerFtor>
208  std::unique_ptr<
209  ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,
210  SymbolResolverPtrT, FinalizerFtor>>
211  createLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
212  SymbolResolverPtrT Resolver,
213  FinalizerFtor Finalizer,
214  bool ProcessAllSections) {
215  typedef ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,
216  SymbolResolverPtrT, FinalizerFtor> LOS;
217  return llvm::make_unique<LOS>(std::move(Objects), std::move(MemMgr),
218  std::move(Resolver), std::move(Finalizer),
219  ProcessAllSections);
220  }
221 
222 public:
223  /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
224  /// RuntimeDyld::LoadedObjectInfo instances.
225  typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
227 
228  /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
229  /// and NotifyFinalized functors.
231  NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
232  NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
233  : NotifyLoaded(std::move(NotifyLoaded)),
234  NotifyFinalized(std::move(NotifyFinalized)),
235  ProcessAllSections(false) {}
236 
237  /// @brief Set the 'ProcessAllSections' flag.
238  ///
239  /// If set to true, all sections in each object file will be allocated using
240  /// the memory manager, rather than just the sections required for execution.
241  ///
242  /// This is kludgy, and may be removed in the future.
243  void setProcessAllSections(bool ProcessAllSections) {
244  this->ProcessAllSections = ProcessAllSections;
245  }
246 
247  /// @brief Add a set of objects (or archives) that will be treated as a unit
248  /// for the purposes of symbol lookup and memory management.
249  ///
250  /// @return A handle that can be used to refer to the loaded objects (for
251  /// symbol searching, finalization, freeing memory, etc.).
252  template <typename ObjSetT,
253  typename MemoryManagerPtrT,
254  typename SymbolResolverPtrT>
255  ObjSetHandleT addObjectSet(ObjSetT Objects,
256  MemoryManagerPtrT MemMgr,
257  SymbolResolverPtrT Resolver) {
258  auto Finalizer = [&](ObjSetHandleT H, RuntimeDyld &RTDyld,
259  const ObjSetT &Objs,
260  std::function<void()> LOSHandleLoad) {
261  LoadedObjInfoList LoadedObjInfos;
262 
263  for (auto &Obj : Objs)
264  LoadedObjInfos.push_back(RTDyld.loadObject(this->getObject(*Obj)));
265 
266  LOSHandleLoad();
267 
268  this->NotifyLoaded(H, Objs, LoadedObjInfos);
269 
270  RTDyld.finalizeWithMemoryManagerLocking();
271 
272  if (this->NotifyFinalized)
273  this->NotifyFinalized(H);
274  };
275 
276  auto LOS =
277  createLinkedObjectSet(std::move(Objects), std::move(MemMgr),
278  std::move(Resolver), std::move(Finalizer),
279  ProcessAllSections);
280  // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle
281  // below.
282  auto *LOSPtr = LOS.get();
283 
284  ObjSetHandleT Handle = LinkedObjSetList.insert(LinkedObjSetList.end(),
285  std::move(LOS));
286  LOSPtr->setHandle(Handle);
287 
288  return Handle;
289  }
290 
291  /// @brief Remove the set of objects associated with handle H.
292  ///
293  /// All memory allocated for the objects will be freed, and the sections and
294  /// symbols they provided will no longer be available. No attempt is made to
295  /// re-emit the missing symbols, and any use of these symbols (directly or
296  /// indirectly) will result in undefined behavior. If dependence tracking is
297  /// required to detect or resolve such issues it should be added at a higher
298  /// layer.
300  // How do we invalidate the symbols in H?
301  LinkedObjSetList.erase(H);
302  }
303 
304  /// @brief Search for the given named symbol.
305  /// @param Name The name of the symbol to search for.
306  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
307  /// @return A handle for the given named symbol, if it exists.
308  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
309  for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
310  ++I)
311  if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
312  return Symbol;
313 
314  return nullptr;
315  }
316 
317  /// @brief Search for the given named symbol in the context of the set of
318  /// loaded objects represented by the handle H.
319  /// @param H The handle for the object set to search in.
320  /// @param Name The name of the symbol to search for.
321  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
322  /// @return A handle for the given named symbol, if it is found in the
323  /// given object set.
325  bool ExportedSymbolsOnly) {
326  return (*H)->getSymbol(Name, ExportedSymbolsOnly);
327  }
328 
329  /// @brief Map section addresses for the objects associated with the handle H.
330  void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
331  JITTargetAddress TargetAddr) {
332  (*H)->mapSectionAddress(LocalAddress, TargetAddr);
333  }
334 
335  /// @brief Immediately emit and finalize the object set represented by the
336  /// given handle.
337  /// @param H Handle for object set to emit/finalize.
339  (*H)->finalize();
340  }
341 
342 private:
343  static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {
344  return Obj;
345  }
346 
347  template <typename ObjT>
348  static const object::ObjectFile&
350  return *Obj.getBinary();
351  }
352 
353  LinkedObjectSetListT LinkedObjSetList;
354  NotifyLoadedFtor NotifyLoaded;
355  NotifyFinalizedFtor NotifyFinalized;
356  bool ProcessAllSections;
357 };
358 
359 } // end namespace orc
360 } // end namespace llvm
361 
362 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
Represents a symbol in the JIT.
Definition: JITSymbol.h:113
ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded=NotifyLoadedFtor(), NotifyFinalizedFtor NotifyFinalized=NotifyFinalizedFtor())
Construct an ObjectLinkingLayer with the given NotifyLoaded, and NotifyFinalized functors.
ObjSetHandleT addObjectSet(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...
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
static std::error_code getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, const uint64_t Size=sizeof(T))
symbol_iterator_range symbols() const
Definition: ObjectFile.h:249
This class is the base class for all object file types.
Definition: ObjectFile.h:178
struct fuzzer::@269 Flags
Bare bones object linking layer.
Function Alias Analysis false
Expected< const typename ELFT::Sym * > getSymbol(typename ELFT::SymRange Symbols, uint32_t Index)
Definition: Object/ELF.h:236
void setProcessAllSections(bool ProcessAllSections)
By default, only sections that are "required for execution" are passed to the RTDyldMemoryManager, and other sections are discarded.
Definition: RuntimeDyld.h:235
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly)
std::function< JITTargetAddress()> GetAddressFtor
Definition: JITSymbol.h:115
std::list< std::unique_ptr< LinkedObjectSet > > LinkedObjectSetListT
virtual void mapSectionAddress(const void *LocalAddress, JITTargetAddress TargetAddr) const =0
#define H(x, y, z)
Definition: MD5.cpp:53
void removeObjectSet(ObjSetHandleT H)
Remove the set of objects associated with handle H.
void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, JITTargetAddress TargetAddr)
Map section addresses for the objects associated with the handle H.
Holds a set of objects to be allocated/linked as a unit in the JIT.
static JITSymbolFlags fromObjectSymbol(const object::BasicSymbolRef &Symbol)
Construct a JITSymbolFlags value based on the flags of the given libobject symbol.
Definition: JITSymbol.cpp:32
uint64_t JITTargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:33
void operator=(const LinkedObjectSet &)=delete
void consumeError(Error Err)
Consume a Error without doing anything.
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.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:223
virtual JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name)=0
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::vector< std::unique_ptr< RuntimeDyld::LoadedObjectInfo > > LoadedObjInfoList
LoadedObjectInfo list.
void setProcessAllSections(bool ProcessAllSections)
Set the 'ProcessAllSections' flag.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
LinkedObjectSetListT::iterator ObjSetHandleT
Handle to a set of loaded objects.