]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / ExecutionEngine / Orc / RTDyldObjectLinkingLayer.h
1 //===- RTDyldObjectLinkingLayer.h - RTDyld-based jit linking  ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains the definition for an RTDyld-based, in-process object linking layer.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
15
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ExecutionEngine/JITSymbol.h"
20 #include "llvm/ExecutionEngine/Orc/Core.h"
21 #include "llvm/ExecutionEngine/Orc/Layer.h"
22 #include "llvm/ExecutionEngine/Orc/Legacy.h"
23 #include "llvm/ExecutionEngine/RuntimeDyld.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Support/Error.h"
26 #include <algorithm>
27 #include <cassert>
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
38 class RTDyldObjectLinkingLayer : public ObjectLayer {
39 public:
40   /// Functor for receiving object-loaded notifications.
41   using NotifyLoadedFunction =
42       std::function<void(VModuleKey, const object::ObjectFile &Obj,
43                          const RuntimeDyld::LoadedObjectInfo &)>;
44
45   /// Functor for receiving finalization notifications.
46   using NotifyEmittedFunction =
47       std::function<void(VModuleKey, std::unique_ptr<MemoryBuffer>)>;
48
49   using GetMemoryManagerFunction =
50       std::function<std::unique_ptr<RuntimeDyld::MemoryManager>()>;
51
52   /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
53   ///        and NotifyEmitted functors.
54   RTDyldObjectLinkingLayer(ExecutionSession &ES,
55                            GetMemoryManagerFunction GetMemoryManager);
56
57   /// Emit the object.
58   void emit(MaterializationResponsibility R,
59             std::unique_ptr<MemoryBuffer> O) override;
60
61   /// Set the NotifyLoaded callback.
62   RTDyldObjectLinkingLayer &setNotifyLoaded(NotifyLoadedFunction NotifyLoaded) {
63     this->NotifyLoaded = std::move(NotifyLoaded);
64     return *this;
65   }
66
67   /// Set the NotifyEmitted callback.
68   RTDyldObjectLinkingLayer &
69   setNotifyEmitted(NotifyEmittedFunction NotifyEmitted) {
70     this->NotifyEmitted = std::move(NotifyEmitted);
71     return *this;
72   }
73
74   /// Set the 'ProcessAllSections' flag.
75   ///
76   /// If set to true, all sections in each object file will be allocated using
77   /// the memory manager, rather than just the sections required for execution.
78   ///
79   /// This is kludgy, and may be removed in the future.
80   RTDyldObjectLinkingLayer &setProcessAllSections(bool ProcessAllSections) {
81     this->ProcessAllSections = ProcessAllSections;
82     return *this;
83   }
84
85   /// Instructs this RTDyldLinkingLayer2 instance to override the symbol flags
86   /// returned by RuntimeDyld for any given object file with the flags supplied
87   /// by the MaterializationResponsibility instance. This is a workaround to
88   /// support symbol visibility in COFF, which does not use the libObject's
89   /// SF_Exported flag. Use only when generating / adding COFF object files.
90   ///
91   /// FIXME: We should be able to remove this if/when COFF properly tracks
92   /// exported symbols.
93   RTDyldObjectLinkingLayer &
94   setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) {
95     this->OverrideObjectFlags = OverrideObjectFlags;
96     return *this;
97   }
98
99   /// If set, this RTDyldObjectLinkingLayer instance will claim responsibility
100   /// for any symbols provided by a given object file that were not already in
101   /// the MaterializationResponsibility instance. Setting this flag allows
102   /// higher-level program representations (e.g. LLVM IR) to be added based on
103   /// only a subset of the symbols they provide, without having to write
104   /// intervening layers to scan and add the additional symbols. This trades
105   /// diagnostic quality for convenience however: If all symbols are enumerated
106   /// up-front then clashes can be detected and reported early (and usually
107   /// deterministically). If this option is set, clashes for the additional
108   /// symbols may not be detected until late, and detection may depend on
109   /// the flow of control through JIT'd code. Use with care.
110   RTDyldObjectLinkingLayer &
111   setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) {
112     this->AutoClaimObjectSymbols = AutoClaimObjectSymbols;
113     return *this;
114   }
115
116 private:
117   Error onObjLoad(VModuleKey K, MaterializationResponsibility &R,
118                   object::ObjectFile &Obj,
119                   std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
120                   std::map<StringRef, JITEvaluatedSymbol> Resolved,
121                   std::set<StringRef> &InternalSymbols);
122
123   void onObjEmit(VModuleKey K, std::unique_ptr<MemoryBuffer> ObjBuffer,
124                  MaterializationResponsibility &R, Error Err);
125
126   mutable std::mutex RTDyldLayerMutex;
127   GetMemoryManagerFunction GetMemoryManager;
128   NotifyLoadedFunction NotifyLoaded;
129   NotifyEmittedFunction NotifyEmitted;
130   bool ProcessAllSections = false;
131   bool OverrideObjectFlags = false;
132   bool AutoClaimObjectSymbols = false;
133   std::vector<std::unique_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
134 };
135
136 class LegacyRTDyldObjectLinkingLayerBase {
137 public:
138   using ObjectPtr = std::unique_ptr<MemoryBuffer>;
139
140 protected:
141
142   /// Holds an object to be allocated/linked as a unit in the JIT.
143   ///
144   /// An instance of this class will be created for each object added
145   /// via JITObjectLayer::addObject. Deleting the instance (via
146   /// removeObject) frees its memory, removing all symbol definitions that
147   /// had been provided by this instance. Higher level layers are responsible
148   /// for taking any action required to handle the missing symbols.
149   class LinkedObject {
150   public:
151     LinkedObject() = default;
152     LinkedObject(const LinkedObject&) = delete;
153     void operator=(const LinkedObject&) = delete;
154     virtual ~LinkedObject() = default;
155
156     virtual Error finalize() = 0;
157
158     virtual JITSymbol::GetAddressFtor
159     getSymbolMaterializer(std::string Name) = 0;
160
161     virtual void mapSectionAddress(const void *LocalAddress,
162                                    JITTargetAddress TargetAddr) const = 0;
163
164     JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
165       auto SymEntry = SymbolTable.find(Name);
166       if (SymEntry == SymbolTable.end())
167         return nullptr;
168       if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
169         return nullptr;
170       if (!Finalized)
171         return JITSymbol(getSymbolMaterializer(Name),
172                          SymEntry->second.getFlags());
173       return JITSymbol(SymEntry->second);
174     }
175
176   protected:
177     StringMap<JITEvaluatedSymbol> SymbolTable;
178     bool Finalized = false;
179   };
180 };
181
182 /// Bare bones object linking layer.
183 ///
184 ///   This class is intended to be used as the base layer for a JIT. It allows
185 /// object files to be loaded into memory, linked, and the addresses of their
186 /// symbols queried. All objects added to this layer can see each other's
187 /// symbols.
188 class LegacyRTDyldObjectLinkingLayer : public LegacyRTDyldObjectLinkingLayerBase {
189 public:
190
191   using LegacyRTDyldObjectLinkingLayerBase::ObjectPtr;
192
193   /// Functor for receiving object-loaded notifications.
194   using NotifyLoadedFtor =
195       std::function<void(VModuleKey, const object::ObjectFile &Obj,
196                          const RuntimeDyld::LoadedObjectInfo &)>;
197
198   /// Functor for receiving finalization notifications.
199   using NotifyFinalizedFtor =
200       std::function<void(VModuleKey, const object::ObjectFile &Obj,
201                          const RuntimeDyld::LoadedObjectInfo &)>;
202
203   /// Functor for receiving deallocation notifications.
204   using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>;
205
206 private:
207   using OwnedObject = object::OwningBinary<object::ObjectFile>;
208
209   template <typename MemoryManagerPtrT>
210   class ConcreteLinkedObject : public LinkedObject {
211   public:
212     ConcreteLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K,
213                          OwnedObject Obj, MemoryManagerPtrT MemMgr,
214                          std::shared_ptr<SymbolResolver> Resolver,
215                          bool ProcessAllSections)
216         : K(std::move(K)),
217           Parent(Parent),
218           MemMgr(std::move(MemMgr)),
219           PFC(llvm::make_unique<PreFinalizeContents>(
220               std::move(Obj), std::move(Resolver),
221               ProcessAllSections)) {
222       buildInitialSymbolTable(PFC->Obj);
223     }
224
225     ~ConcreteLinkedObject() override {
226       if (this->Parent.NotifyFreed && ObjForNotify.getBinary())
227         this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
228
229       MemMgr->deregisterEHFrames();
230     }
231
232     Error finalize() override {
233       assert(PFC && "mapSectionAddress called on finalized LinkedObject");
234
235       JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
236                                                nullptr);
237       PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
238       PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
239
240       Finalized = true;
241
242       std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
243           PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
244
245       // Copy the symbol table out of the RuntimeDyld instance.
246       {
247         auto SymTab = PFC->RTDyld->getSymbolTable();
248         for (auto &KV : SymTab)
249           SymbolTable[KV.first] = KV.second;
250       }
251
252       if (Parent.NotifyLoaded)
253         Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
254
255       PFC->RTDyld->finalizeWithMemoryManagerLocking();
256
257       if (PFC->RTDyld->hasError())
258         return make_error<StringError>(PFC->RTDyld->getErrorString(),
259                                        inconvertibleErrorCode());
260
261       if (Parent.NotifyFinalized)
262         Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info);
263
264       // Release resources.
265       if (this->Parent.NotifyFreed)
266         ObjForNotify = std::move(PFC->Obj); // needed for callback
267       PFC = nullptr;
268       return Error::success();
269     }
270
271     JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
272       return [this, Name]() -> Expected<JITTargetAddress> {
273         // The symbol may be materialized between the creation of this lambda
274         // and its execution, so we need to double check.
275         if (!this->Finalized)
276           if (auto Err = this->finalize())
277             return std::move(Err);
278         return this->getSymbol(Name, false).getAddress();
279       };
280     }
281
282     void mapSectionAddress(const void *LocalAddress,
283                            JITTargetAddress TargetAddr) const override {
284       assert(PFC && "mapSectionAddress called on finalized LinkedObject");
285       assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
286       PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
287     }
288
289   private:
290     void buildInitialSymbolTable(const OwnedObject &Obj) {
291       for (auto &Symbol : Obj.getBinary()->symbols()) {
292         if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
293           continue;
294         Expected<StringRef> SymbolName = Symbol.getName();
295         // FIXME: Raise an error for bad symbols.
296         if (!SymbolName) {
297           consumeError(SymbolName.takeError());
298           continue;
299         }
300         // FIXME: Raise an error for bad symbols.
301         auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
302         if (!Flags) {
303           consumeError(Flags.takeError());
304           continue;
305         }
306         SymbolTable.insert(
307             std::make_pair(*SymbolName, JITEvaluatedSymbol(0, *Flags)));
308       }
309     }
310
311     // Contains the information needed prior to finalization: the object files,
312     // memory manager, resolver, and flags needed for RuntimeDyld.
313     struct PreFinalizeContents {
314       PreFinalizeContents(OwnedObject Obj,
315                           std::shared_ptr<SymbolResolver> Resolver,
316                           bool ProcessAllSections)
317           : Obj(std::move(Obj)),
318             Resolver(std::move(Resolver)),
319             ProcessAllSections(ProcessAllSections) {}
320
321       OwnedObject Obj;
322       std::shared_ptr<SymbolResolver> Resolver;
323       bool ProcessAllSections;
324       std::unique_ptr<RuntimeDyld> RTDyld;
325     };
326
327     VModuleKey K;
328     LegacyRTDyldObjectLinkingLayer &Parent;
329     MemoryManagerPtrT MemMgr;
330     OwnedObject ObjForNotify;
331     std::unique_ptr<PreFinalizeContents> PFC;
332   };
333
334   template <typename MemoryManagerPtrT>
335   std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>>
336   createLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K,
337                      OwnedObject Obj, MemoryManagerPtrT MemMgr,
338                      std::shared_ptr<SymbolResolver> Resolver,
339                      bool ProcessAllSections) {
340     using LOS = ConcreteLinkedObject<MemoryManagerPtrT>;
341     return llvm::make_unique<LOS>(Parent, std::move(K), std::move(Obj),
342                                   std::move(MemMgr), std::move(Resolver),
343                                   ProcessAllSections);
344   }
345
346 public:
347   struct Resources {
348     std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
349     std::shared_ptr<SymbolResolver> Resolver;
350   };
351
352   using ResourcesGetter = std::function<Resources(VModuleKey)>;
353
354   /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
355   ///        and NotifyFinalized functors.
356   LLVM_ATTRIBUTE_DEPRECATED(
357       LegacyRTDyldObjectLinkingLayer(
358           ExecutionSession &ES, ResourcesGetter GetResources,
359           NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
360           NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
361           NotifyFreedFtor NotifyFreed = NotifyFreedFtor()),
362       "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please "
363       "use "
364       "ORCv2 (see docs/ORCv2.rst)");
365
366   // Legacy layer constructor with deprecation acknowledgement.
367   LegacyRTDyldObjectLinkingLayer(
368       ORCv1DeprecationAcknowledgement, ExecutionSession &ES,
369       ResourcesGetter GetResources,
370       NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
371       NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
372       NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
373       : ES(ES), GetResources(std::move(GetResources)),
374         NotifyLoaded(std::move(NotifyLoaded)),
375         NotifyFinalized(std::move(NotifyFinalized)),
376         NotifyFreed(std::move(NotifyFreed)), ProcessAllSections(false) {}
377
378   /// Set the 'ProcessAllSections' flag.
379   ///
380   /// If set to true, all sections in each object file will be allocated using
381   /// the memory manager, rather than just the sections required for execution.
382   ///
383   /// This is kludgy, and may be removed in the future.
384   void setProcessAllSections(bool ProcessAllSections) {
385     this->ProcessAllSections = ProcessAllSections;
386   }
387
388   /// Add an object to the JIT.
389   Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
390
391     auto Obj =
392         object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
393     if (!Obj)
394       return Obj.takeError();
395
396     assert(!LinkedObjects.count(K) && "VModuleKey already in use");
397
398     auto R = GetResources(K);
399
400     LinkedObjects[K] = createLinkedObject(
401         *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
402         std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections);
403
404     return Error::success();
405   }
406
407   /// Remove the object associated with VModuleKey K.
408   ///
409   ///   All memory allocated for the object will be freed, and the sections and
410   /// symbols it provided will no longer be available. No attempt is made to
411   /// re-emit the missing symbols, and any use of these symbols (directly or
412   /// indirectly) will result in undefined behavior. If dependence tracking is
413   /// required to detect or resolve such issues it should be added at a higher
414   /// layer.
415   Error removeObject(VModuleKey K) {
416     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
417     // How do we invalidate the symbols in H?
418     LinkedObjects.erase(K);
419     return Error::success();
420   }
421
422   /// Search for the given named symbol.
423   /// @param Name The name of the symbol to search for.
424   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
425   /// @return A handle for the given named symbol, if it exists.
426   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
427     for (auto &KV : LinkedObjects)
428       if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
429         return Sym;
430       else if (auto Err = Sym.takeError())
431         return std::move(Err);
432
433     return nullptr;
434   }
435
436   /// Search for the given named symbol in the context of the loaded
437   ///        object represented by the VModuleKey K.
438   /// @param K The VModuleKey for the object to search in.
439   /// @param Name The name of the symbol to search for.
440   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
441   /// @return A handle for the given named symbol, if it is found in the
442   ///         given object.
443   JITSymbol findSymbolIn(VModuleKey K, StringRef Name,
444                          bool ExportedSymbolsOnly) {
445     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
446     return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
447   }
448
449   /// Map section addresses for the object associated with the
450   ///        VModuleKey K.
451   void mapSectionAddress(VModuleKey K, const void *LocalAddress,
452                          JITTargetAddress TargetAddr) {
453     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
454     LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
455   }
456
457   /// Immediately emit and finalize the object represented by the given
458   ///        VModuleKey.
459   /// @param K VModuleKey for object to emit/finalize.
460   Error emitAndFinalize(VModuleKey K) {
461     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
462     return LinkedObjects[K]->finalize();
463   }
464
465 private:
466   ExecutionSession &ES;
467
468   ResourcesGetter GetResources;
469   NotifyLoadedFtor NotifyLoaded;
470   NotifyFinalizedFtor NotifyFinalized;
471   NotifyFreedFtor NotifyFreed;
472
473   // NB!  `LinkedObjects` needs to be destroyed before `NotifyFreed` because
474   // `~ConcreteLinkedObject` calls `NotifyFreed`
475   std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects;
476   bool ProcessAllSections = false;
477 };
478
479 } // end namespace orc
480 } // end namespace llvm
481
482 #endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H