LLVM  7.0.0svn
RTDyldObjectLinkingLayer.h
Go to the documentation of this file.
1 //===- RTDyldObjectLinkingLayer.h - RTDyld-based jit linking ---*- 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 an RTDyld-based, in-process object linking layer.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
16 
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/ADT/StringRef.h"
25 #include "llvm/Object/ObjectFile.h"
26 #include "llvm/Support/Error.h"
27 #include <algorithm>
28 #include <cassert>
29 #include <functional>
30 #include <list>
31 #include <memory>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 
36 namespace llvm {
37 namespace orc {
38 
40 public:
41  /// Functor for receiving object-loaded notifications.
42  using NotifyLoadedFunction =
45 
46  /// Functor for receiving finalization notifications.
47  using NotifyFinalizedFunction = std::function<void(VModuleKey)>;
48 
49  struct Resources {
50  std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
51  std::shared_ptr<SymbolResolver> Resolver;
52  };
53 
54  using ResourcesGetterFunction = std::function<Resources(VModuleKey)>;
55 
56  /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
57  /// and NotifyFinalized functors.
59  ExecutionSession &ES, ResourcesGetterFunction GetResources,
62 
63  /// Emit the object.
65  std::unique_ptr<MemoryBuffer> O) override;
66 
67  /// Map section addresses for the object associated with the
68  /// VModuleKey K.
69  void mapSectionAddress(VModuleKey K, const void *LocalAddress,
70  JITTargetAddress TargetAddr) const;
71 
72  /// Set the 'ProcessAllSections' flag.
73  ///
74  /// If set to true, all sections in each object file will be allocated using
75  /// the memory manager, rather than just the sections required for execution.
76  ///
77  /// This is kludgy, and may be removed in the future.
78  void setProcessAllSections(bool ProcessAllSections) {
79  this->ProcessAllSections = ProcessAllSections;
80  }
81 
82 private:
83  mutable std::mutex RTDyldLayerMutex;
84  ResourcesGetterFunction GetResources;
85  NotifyLoadedFunction NotifyLoaded;
86  NotifyFinalizedFunction NotifyFinalized;
87  bool ProcessAllSections;
88  std::map<VModuleKey, RuntimeDyld *> ActiveRTDylds;
89  std::map<VModuleKey, std::shared_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
90 };
91 
93 public:
94  using ObjectPtr = std::unique_ptr<MemoryBuffer>;
95 
96 protected:
97 
98  /// Holds an object to be allocated/linked as a unit in the JIT.
99  ///
100  /// An instance of this class will be created for each object added
101  /// via JITObjectLayer::addObject. Deleting the instance (via
102  /// removeObject) frees its memory, removing all symbol definitions that
103  /// had been provided by this instance. Higher level layers are responsible
104  /// for taking any action required to handle the missing symbols.
105  class LinkedObject {
106  public:
107  LinkedObject() = default;
108  LinkedObject(const LinkedObject&) = delete;
109  void operator=(const LinkedObject&) = delete;
110  virtual ~LinkedObject() = default;
111 
112  virtual Error finalize() = 0;
113 
115  getSymbolMaterializer(std::string Name) = 0;
116 
117  virtual void mapSectionAddress(const void *LocalAddress,
118  JITTargetAddress TargetAddr) const = 0;
119 
120  JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
121  auto SymEntry = SymbolTable.find(Name);
122  if (SymEntry == SymbolTable.end())
123  return nullptr;
124  if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
125  return nullptr;
126  if (!Finalized)
127  return JITSymbol(getSymbolMaterializer(Name),
128  SymEntry->second.getFlags());
129  return JITSymbol(SymEntry->second);
130  }
131 
132  protected:
134  bool Finalized = false;
135  };
136 };
137 
138 /// Bare bones object linking layer.
139 ///
140 /// This class is intended to be used as the base layer for a JIT. It allows
141 /// object files to be loaded into memory, linked, and the addresses of their
142 /// symbols queried. All objects added to this layer can see each other's
143 /// symbols.
145 public:
146 
148 
149  /// Functor for receiving object-loaded notifications.
150  using NotifyLoadedFtor =
153 
154  /// Functor for receiving finalization notifications.
155  using NotifyFinalizedFtor =
158 
159  /// Functor for receiving deallocation notifications.
160  using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>;
161 
162 private:
164 
165  template <typename MemoryManagerPtrT>
166  class ConcreteLinkedObject : public LinkedObject {
167  public:
168  ConcreteLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
169  OwnedObject Obj, MemoryManagerPtrT MemMgr,
170  std::shared_ptr<SymbolResolver> Resolver,
171  bool ProcessAllSections)
172  : K(std::move(K)),
173  Parent(Parent),
174  MemMgr(std::move(MemMgr)),
175  PFC(llvm::make_unique<PreFinalizeContents>(
176  std::move(Obj), std::move(Resolver),
177  ProcessAllSections)) {
178  buildInitialSymbolTable(PFC->Obj);
179  }
180 
181  ~ConcreteLinkedObject() override {
182  if (this->Parent.NotifyFreed)
183  this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
184 
185  MemMgr->deregisterEHFrames();
186  }
187 
188  Error finalize() override {
189  assert(PFC && "mapSectionAddress called on finalized LinkedObject");
190 
191  JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
192  nullptr);
193  PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
194  PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
195 
196  Finalized = true;
197 
198  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
199  PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
200 
201  // Copy the symbol table out of the RuntimeDyld instance.
202  {
203  auto SymTab = PFC->RTDyld->getSymbolTable();
204  for (auto &KV : SymTab)
205  SymbolTable[KV.first] = KV.second;
206  }
207 
208  if (Parent.NotifyLoaded)
209  Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
210 
211  PFC->RTDyld->finalizeWithMemoryManagerLocking();
212 
213  if (PFC->RTDyld->hasError())
214  return make_error<StringError>(PFC->RTDyld->getErrorString(),
216 
217  if (Parent.NotifyFinalized)
218  Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info);
219 
220  // Release resources.
221  if (this->Parent.NotifyFreed)
222  ObjForNotify = std::move(PFC->Obj); // needed for callback
223  PFC = nullptr;
224  return Error::success();
225  }
226 
227  JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
228  return [this, Name]() -> Expected<JITTargetAddress> {
229  // The symbol may be materialized between the creation of this lambda
230  // and its execution, so we need to double check.
231  if (!this->Finalized)
232  if (auto Err = this->finalize())
233  return std::move(Err);
234  return this->getSymbol(Name, false).getAddress();
235  };
236  }
237 
238  void mapSectionAddress(const void *LocalAddress,
239  JITTargetAddress TargetAddr) const override {
240  assert(PFC && "mapSectionAddress called on finalized LinkedObject");
241  assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
242  PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
243  }
244 
245  private:
246  void buildInitialSymbolTable(const OwnedObject &Obj) {
247  for (auto &Symbol : Obj.getBinary()->symbols()) {
248  if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
249  continue;
251  // FIXME: Raise an error for bad symbols.
252  if (!SymbolName) {
253  consumeError(SymbolName.takeError());
254  continue;
255  }
257  SymbolTable.insert(
258  std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
259  }
260  }
261 
262  // Contains the information needed prior to finalization: the object files,
263  // memory manager, resolver, and flags needed for RuntimeDyld.
264  struct PreFinalizeContents {
265  PreFinalizeContents(OwnedObject Obj,
266  std::shared_ptr<SymbolResolver> Resolver,
267  bool ProcessAllSections)
268  : Obj(std::move(Obj)),
269  Resolver(std::move(Resolver)),
270  ProcessAllSections(ProcessAllSections) {}
271 
272  OwnedObject Obj;
273  std::shared_ptr<SymbolResolver> Resolver;
274  bool ProcessAllSections;
275  std::unique_ptr<RuntimeDyld> RTDyld;
276  };
277 
278  VModuleKey K;
279  RTDyldObjectLinkingLayer &Parent;
280  MemoryManagerPtrT MemMgr;
281  OwnedObject ObjForNotify;
282  std::unique_ptr<PreFinalizeContents> PFC;
283  };
284 
285  template <typename MemoryManagerPtrT>
286  std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>>
287  createLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
288  OwnedObject Obj, MemoryManagerPtrT MemMgr,
289  std::shared_ptr<SymbolResolver> Resolver,
290  bool ProcessAllSections) {
291  using LOS = ConcreteLinkedObject<MemoryManagerPtrT>;
292  return llvm::make_unique<LOS>(Parent, std::move(K), std::move(Obj),
293  std::move(MemMgr), std::move(Resolver),
294  ProcessAllSections);
295  }
296 
297 public:
298  struct Resources {
299  std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
300  std::shared_ptr<SymbolResolver> Resolver;
301  };
302 
303  using ResourcesGetter = std::function<Resources(VModuleKey)>;
304 
305  /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
306  /// and NotifyFinalized functors.
308  ExecutionSession &ES, ResourcesGetter GetResources,
309  NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
310  NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
311  NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
312  : ES(ES), GetResources(std::move(GetResources)),
313  NotifyLoaded(std::move(NotifyLoaded)),
314  NotifyFinalized(std::move(NotifyFinalized)),
315  NotifyFreed(std::move(NotifyFreed)),
316  ProcessAllSections(false) {
317  }
318 
319  /// Set the 'ProcessAllSections' flag.
320  ///
321  /// If set to true, all sections in each object file will be allocated using
322  /// the memory manager, rather than just the sections required for execution.
323  ///
324  /// This is kludgy, and may be removed in the future.
325  void setProcessAllSections(bool ProcessAllSections) {
326  this->ProcessAllSections = ProcessAllSections;
327  }
328 
329  /// Add an object to the JIT.
331 
332  auto Obj =
333  object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
334  if (!Obj)
335  return Obj.takeError();
336 
337  assert(!LinkedObjects.count(K) && "VModuleKey already in use");
338 
339  auto R = GetResources(K);
340 
341  LinkedObjects[K] = createLinkedObject(
342  *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
343  std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections);
344 
345  return Error::success();
346  }
347 
348  /// Remove the object associated with VModuleKey K.
349  ///
350  /// All memory allocated for the object will be freed, and the sections and
351  /// symbols it provided will no longer be available. No attempt is made to
352  /// re-emit the missing symbols, and any use of these symbols (directly or
353  /// indirectly) will result in undefined behavior. If dependence tracking is
354  /// required to detect or resolve such issues it should be added at a higher
355  /// layer.
357  assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
358  // How do we invalidate the symbols in H?
359  LinkedObjects.erase(K);
360  return Error::success();
361  }
362 
363  /// Search for the given named symbol.
364  /// @param Name The name of the symbol to search for.
365  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
366  /// @return A handle for the given named symbol, if it exists.
367  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
368  for (auto &KV : LinkedObjects)
369  if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
370  return Sym;
371  else if (auto Err = Sym.takeError())
372  return std::move(Err);
373 
374  return nullptr;
375  }
376 
377  /// Search for the given named symbol in the context of the loaded
378  /// object represented by the VModuleKey K.
379  /// @param K The VModuleKey for the object to search in.
380  /// @param Name The name of the symbol to search for.
381  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
382  /// @return A handle for the given named symbol, if it is found in the
383  /// given object.
385  bool ExportedSymbolsOnly) {
386  assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
387  return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
388  }
389 
390  /// Map section addresses for the object associated with the
391  /// VModuleKey K.
392  void mapSectionAddress(VModuleKey K, const void *LocalAddress,
393  JITTargetAddress TargetAddr) {
394  assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
395  LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
396  }
397 
398  /// Immediately emit and finalize the object represented by the given
399  /// VModuleKey.
400  /// @param K VModuleKey for object to emit/finalize.
402  assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
403  return LinkedObjects[K]->finalize();
404  }
405 
406 private:
407  ExecutionSession &ES;
408 
409  std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects;
410  ResourcesGetter GetResources;
411  NotifyLoadedFtor NotifyLoaded;
412  NotifyFinalizedFtor NotifyFinalized;
413  NotifyFreedFtor NotifyFreed;
414  bool ProcessAllSections = false;
415 };
416 
417 } // end namespace orc
418 } // end namespace llvm
419 
420 #endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:153
Information about the loaded object.
Definition: RuntimeDyld.h:69
Represents a symbol in the JIT.
Definition: JITSymbol.h:186
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
arc branch finalize
JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly)
Holds an object to be allocated/linked as a unit in the JIT.
Error emitAndFinalize(VModuleKey K)
Immediately emit and finalize the object represented by the given VModuleKey.
Bare bones object linking layer.
void setProcessAllSections(bool ProcessAllSections)
Set the &#39;ProcessAllSections&#39; flag.
This class is the base class for all object file types.
Definition: ObjectFile.h:190
Error takeError()
Take ownership of the stored error.
Definition: Error.h:537
uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:40
Definition: BitVector.h:921
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
std::function< void(VModuleKey, const object::ObjectFile &Obj)> NotifyFreedFtor
Functor for receiving deallocation notifications.
void mapSectionAddress(VModuleKey K, const void *LocalAddress, JITTargetAddress TargetAddr)
Map section addresses for the object associated with the VModuleKey K.
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:104
std::shared_ptr< RuntimeDyld::MemoryManager > MemMgr
std::function< void(VModuleKey, const object::ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &)> NotifyLoadedFtor
Functor for receiving object-loaded notifications.
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:40
Expected< const typename ELFT::Sym * > getSymbol(typename ELFT::SymRange Symbols, uint32_t Index)
Definition: ELF.h:320
void mapSectionAddress(VModuleKey K, const void *LocalAddress, JITTargetAddress TargetAddr) const
Map section addresses for the object associated with the VModuleKey K.
void emit(MaterializationResponsibility R, VModuleKey K, std::unique_ptr< MemoryBuffer > O) override
Emit the object.
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:1774
RTDyldObjectLinkingLayer(ExecutionSession &ES, ResourcesGetter GetResources, NotifyLoadedFtor NotifyLoaded=NotifyLoadedFtor(), NotifyFinalizedFtor NotifyFinalized=NotifyFinalizedFtor(), NotifyFreedFtor NotifyFreed=NotifyFreedFtor())
Construct an ObjectLinkingLayer with the given NotifyLoaded, and NotifyFinalized functors.
static JITSymbolFlags fromObjectSymbol(const object::BasicSymbolRef &Symbol)
Construct a JITSymbolFlags value based on the flags of the given libobject symbol.
Definition: JITSymbol.cpp:32
std::function< Resources(VModuleKey)> ResourcesGetter
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:962
std::function< void(VModuleKey)> NotifyFinalizedFunction
Functor for receiving finalization notifications.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
std::function< void(VModuleKey, const object::ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &)> NotifyFinalizedFtor
Functor for receiving finalization notifications.
An ExecutionSession represents a running JIT program.
Definition: Core.h:625
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:220
std::function< Resources(VModuleKey)> ResourcesGetterFunction
void setProcessAllSections(bool ProcessAllSections)
Set the &#39;ProcessAllSections&#39; flag.
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:157
JITSymbol findSymbolIn(VModuleKey K, StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol in the context of the loaded object represented by the VModuleKey K...
std::unique_ptr< MemoryBuffer > ObjectPtr
std::function< Expected< JITTargetAddress >()> GetAddressFtor
Definition: JITSymbol.h:188
symbol_iterator_range symbols() const
Definition: ObjectFile.h:270
std::shared_ptr< RuntimeDyld::MemoryManager > MemMgr
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
Error addObject(VModuleKey K, ObjectPtr ObjBuffer)
Add an object to the JIT.
RTDyldObjectLinkingLayer2(ExecutionSession &ES, ResourcesGetterFunction GetResources, NotifyLoadedFunction NotifyLoaded=NotifyLoadedFunction(), NotifyFinalizedFunction NotifyFinalized=NotifyFinalizedFunction())
Construct an ObjectLinkingLayer with the given NotifyLoaded, and NotifyFinalized functors.
Error removeObject(VModuleKey K)
Remove the object associated with VModuleKey K.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
Interface for Layers that accept object files.
Definition: Layer.h:99
std::function< void(VModuleKey, const object::ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &)> NotifyLoadedFunction
Functor for receiving object-loaded notifications.
print Print MemDeps of function
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:73