LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - RTDyldObjectLinkingLayer.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 77 86 89.5 %
Date: 2018-07-13 00:08:38 Functions: 17 20 85.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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"
      20             : #include "llvm/ExecutionEngine/JITSymbol.h"
      21             : #include "llvm/ExecutionEngine/Orc/Core.h"
      22             : #include "llvm/ExecutionEngine/Orc/Layer.h"
      23             : #include "llvm/ExecutionEngine/Orc/Legacy.h"
      24             : #include "llvm/ExecutionEngine/RuntimeDyld.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             : 
      39          14 : class RTDyldObjectLinkingLayer2 : public ObjectLayer {
      40             : public:
      41             :   /// Functor for receiving object-loaded notifications.
      42             :   using NotifyLoadedFunction =
      43             :       std::function<void(VModuleKey, const object::ObjectFile &Obj,
      44             :                          const RuntimeDyld::LoadedObjectInfo &)>;
      45             : 
      46             :   /// Functor for receiving finalization notifications.
      47             :   using NotifyFinalizedFunction = std::function<void(VModuleKey)>;
      48             : 
      49          46 :   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.
      58             :   RTDyldObjectLinkingLayer2(
      59             :       ExecutionSession &ES, ResourcesGetterFunction GetResources,
      60             :       NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
      61             :       NotifyFinalizedFunction NotifyFinalized = NotifyFinalizedFunction());
      62             : 
      63             :   /// Emit the object.
      64             :   void emit(MaterializationResponsibility R, VModuleKey K,
      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             : 
      92             : class RTDyldObjectLinkingLayerBase {
      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         103 :     LinkedObject() = default;
     108             :     LinkedObject(const LinkedObject&) = delete;
     109             :     void operator=(const LinkedObject&) = delete;
     110          24 :     virtual ~LinkedObject() = default;
     111             : 
     112             :     virtual Error finalize() = 0;
     113             : 
     114             :     virtual JITSymbol::GetAddressFtor
     115             :     getSymbolMaterializer(std::string Name) = 0;
     116             : 
     117             :     virtual void mapSectionAddress(const void *LocalAddress,
     118             :                                    JITTargetAddress TargetAddr) const = 0;
     119             : 
     120         598 :     JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
     121         598 :       auto SymEntry = SymbolTable.find(Name);
     122        1196 :       if (SymEntry == SymbolTable.end())
     123             :         return nullptr;
     124         307 :       if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
     125             :         return nullptr;
     126         307 :       if (!Finalized)
     127         392 :         return JITSymbol(getSymbolMaterializer(Name),
     128             :                          SymEntry->second.getFlags());
     129             :       return JITSymbol(SymEntry->second);
     130             :     }
     131             : 
     132             :   protected:
     133             :     StringMap<JITEvaluatedSymbol> SymbolTable;
     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.
     144          38 : class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
     145             : public:
     146             : 
     147             :   using RTDyldObjectLinkingLayerBase::ObjectPtr;
     148             : 
     149             :   /// Functor for receiving object-loaded notifications.
     150             :   using NotifyLoadedFtor =
     151             :       std::function<void(VModuleKey, const object::ObjectFile &Obj,
     152             :                          const RuntimeDyld::LoadedObjectInfo &)>;
     153             : 
     154             :   /// Functor for receiving finalization notifications.
     155             :   using NotifyFinalizedFtor =
     156             :       std::function<void(VModuleKey, const object::ObjectFile &Obj,
     157             :                          const RuntimeDyld::LoadedObjectInfo &)>;
     158             : 
     159             :   /// Functor for receiving deallocation notifications.
     160             :   using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>;
     161             : 
     162             : private:
     163             :   using OwnedObject = object::OwningBinary<object::ObjectFile>;
     164             : 
     165             :   template <typename MemoryManagerPtrT>
     166             :   class ConcreteLinkedObject : public LinkedObject {
     167             :   public:
     168         103 :     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         206 :               ProcessAllSections)) {
     178         103 :       buildInitialSymbolTable(PFC->Obj);
     179         103 :     }
     180             : 
     181          48 :     ~ConcreteLinkedObject() override {
     182          48 :       if (this->Parent.NotifyFreed)
     183           4 :         this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
     184             : 
     185          24 :       MemMgr->deregisterEHFrames();
     186          96 :     }
     187             : 
     188         102 :     Error finalize() override {
     189             :       assert(PFC && "mapSectionAddress called on finalized LinkedObject");
     190             : 
     191         102 :       JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
     192             :                                                nullptr);
     193         102 :       PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
     194         102 :       PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
     195             : 
     196         102 :       Finalized = true;
     197             : 
     198         102 :       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         102 :         auto SymTab = PFC->RTDyld->getSymbolTable();
     204         302 :         for (auto &KV : SymTab)
     205         400 :           SymbolTable[KV.first] = KV.second;
     206             :       }
     207             : 
     208         204 :       if (Parent.NotifyLoaded)
     209          93 :         Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
     210             : 
     211         102 :       PFC->RTDyld->finalizeWithMemoryManagerLocking();
     212             : 
     213         102 :       if (PFC->RTDyld->hasError())
     214           0 :         return make_error<StringError>(PFC->RTDyld->getErrorString(),
     215           0 :                                        inconvertibleErrorCode());
     216             : 
     217         204 :       if (Parent.NotifyFinalized)
     218          97 :         Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info);
     219             : 
     220             :       // Release resources.
     221         204 :       if (this->Parent.NotifyFreed)
     222           4 :         ObjForNotify = std::move(PFC->Obj); // needed for callback
     223         102 :       PFC = nullptr;
     224             :       return Error::success();
     225             :     }
     226             : 
     227          98 :     JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
     228         392 :       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          98 :         if (!this->Finalized)
     232         196 :           if (auto Err = this->finalize())
     233             :             return std::move(Err);
     234         196 :         return this->getSymbol(Name, false).getAddress();
     235         196 :       };
     236             :     }
     237             : 
     238           0 :     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           0 :       PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
     243           0 :     }
     244             : 
     245             :   private:
     246         103 :     void buildInitialSymbolTable(const OwnedObject &Obj) {
     247         990 :       for (auto &Symbol : Obj.getBinary()->symbols()) {
     248         578 :         if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
     249         332 :           continue;
     250             :         Expected<StringRef> SymbolName = Symbol.getName();
     251             :         // FIXME: Raise an error for bad symbols.
     252         412 :         if (!SymbolName) {
     253           0 :           consumeError(SymbolName.takeError());
     254             :           continue;
     255             :         }
     256         412 :         auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
     257         412 :         SymbolTable.insert(
     258             :           std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
     259             :       }
     260         103 :     }
     261             : 
     262             :     // Contains the information needed prior to finalization: the object files,
     263             :     // memory manager, resolver, and flags needed for RuntimeDyld.
     264         206 :     struct PreFinalizeContents {
     265         103 :       PreFinalizeContents(OwnedObject Obj,
     266             :                           std::shared_ptr<SymbolResolver> Resolver,
     267             :                           bool ProcessAllSections)
     268             :           : Obj(std::move(Obj)),
     269             :             Resolver(std::move(Resolver)),
     270         103 :             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         103 :                                   ProcessAllSections);
     295             :   }
     296             : 
     297             : public:
     298         206 :   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.
     307          85 :   RTDyldObjectLinkingLayer(
     308             :       ExecutionSession &ES, ResourcesGetter GetResources,
     309             :       NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
     310             :       NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
     311             :       NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
     312          85 :       : ES(ES), GetResources(std::move(GetResources)),
     313             :         NotifyLoaded(std::move(NotifyLoaded)),
     314             :         NotifyFinalized(std::move(NotifyFinalized)),
     315             :         NotifyFreed(std::move(NotifyFreed)),
     316         170 :         ProcessAllSections(false) {
     317          85 :   }
     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           1 :     this->ProcessAllSections = ProcessAllSections;
     327             :   }
     328             : 
     329             :   /// Add an object to the JIT.
     330         103 :   Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
     331             : 
     332             :     auto Obj =
     333         206 :         object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
     334         103 :     if (!Obj)
     335             :       return Obj.takeError();
     336             : 
     337             :     assert(!LinkedObjects.count(K) && "VModuleKey already in use");
     338             : 
     339         206 :     auto R = GetResources(K);
     340             : 
     341         515 :     LinkedObjects[K] = createLinkedObject(
     342         103 :         *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
     343         103 :         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.
     356             :   Error removeObject(VModuleKey K) {
     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         294 :   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
     368         467 :     for (auto &KV : LinkedObjects)
     369         425 :       if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
     370         158 :         return Sym;
     371         173 :       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.
     384             :   JITSymbol findSymbolIn(VModuleKey K, StringRef Name,
     385             :                          bool ExportedSymbolsOnly) {
     386             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     387         496 :     return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
     388             :   }
     389             : 
     390             :   /// Map section addresses for the object associated with the
     391             :   ///        VModuleKey K.
     392           0 :   void mapSectionAddress(VModuleKey K, const void *LocalAddress,
     393             :                          JITTargetAddress TargetAddr) {
     394             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     395           0 :     LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
     396           0 :   }
     397             : 
     398             :   /// Immediately emit and finalize the object represented by the given
     399             :   ///        VModuleKey.
     400             :   /// @param K VModuleKey for object to emit/finalize.
     401           4 :   Error emitAndFinalize(VModuleKey K) {
     402             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     403           8 :     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

Generated by: LCOV version 1.13