LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - RTDyldObjectLinkingLayer.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 70 79 88.6 %
Date: 2018-05-20 00:06:23 Functions: 15 17 88.2 %
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/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 RTDyldObjectLinkingLayerBase {
      39             : public:
      40             :   using ObjectPtr = std::unique_ptr<MemoryBuffer>;
      41             : 
      42             : protected:
      43             : 
      44             :   /// Holds an object to be allocated/linked as a unit in the JIT.
      45             :   ///
      46             :   /// An instance of this class will be created for each object added
      47             :   /// via JITObjectLayer::addObject. Deleting the instance (via
      48             :   /// removeObject) frees its memory, removing all symbol definitions that
      49             :   /// had been provided by this instance. Higher level layers are responsible
      50             :   /// for taking any action required to handle the missing symbols.
      51             :   class LinkedObject {
      52             :   public:
      53         122 :     LinkedObject() = default;
      54             :     LinkedObject(const LinkedObject&) = delete;
      55             :     void operator=(const LinkedObject&) = delete;
      56          43 :     virtual ~LinkedObject() = default;
      57             : 
      58             :     virtual Error finalize() = 0;
      59             : 
      60             :     virtual JITSymbol::GetAddressFtor
      61             :     getSymbolMaterializer(std::string Name) = 0;
      62             : 
      63             :     virtual void mapSectionAddress(const void *LocalAddress,
      64             :                                    JITTargetAddress TargetAddr) const = 0;
      65             : 
      66         671 :     JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
      67         671 :       auto SymEntry = SymbolTable.find(Name);
      68        1342 :       if (SymEntry == SymbolTable.end())
      69             :         return nullptr;
      70         349 :       if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
      71             :         return nullptr;
      72         349 :       if (!Finalized)
      73         464 :         return JITSymbol(getSymbolMaterializer(Name),
      74             :                          SymEntry->second.getFlags());
      75             :       return JITSymbol(SymEntry->second);
      76             :     }
      77             : 
      78             :   protected:
      79             :     StringMap<JITEvaluatedSymbol> SymbolTable;
      80             :     bool Finalized = false;
      81             :   };
      82             : };
      83             : 
      84             : /// Bare bones object linking layer.
      85             : ///
      86             : ///   This class is intended to be used as the base layer for a JIT. It allows
      87             : /// object files to be loaded into memory, linked, and the addresses of their
      88             : /// symbols queried. All objects added to this layer can see each other's
      89             : /// symbols.
      90          52 : class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
      91             : public:
      92             : 
      93             :   using RTDyldObjectLinkingLayerBase::ObjectPtr;
      94             : 
      95             :   /// Functor for receiving object-loaded notifications.
      96             :   using NotifyLoadedFtor =
      97             :       std::function<void(VModuleKey, const object::ObjectFile &Obj,
      98             :                          const RuntimeDyld::LoadedObjectInfo &)>;
      99             : 
     100             :   /// Functor for receiving finalization notifications.
     101             :   using NotifyFinalizedFtor = std::function<void(VModuleKey)>;
     102             : 
     103             : private:
     104             :   using OwnedObject = object::OwningBinary<object::ObjectFile>;
     105             : 
     106             :   template <typename MemoryManagerPtrT>
     107             :   class ConcreteLinkedObject : public LinkedObject {
     108             :   public:
     109         122 :     ConcreteLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
     110             :                          OwnedObject Obj, MemoryManagerPtrT MemMgr,
     111             :                          std::shared_ptr<SymbolResolver> Resolver,
     112             :                          bool ProcessAllSections)
     113             :         : MemMgr(std::move(MemMgr)),
     114             :           PFC(llvm::make_unique<PreFinalizeContents>(
     115             :               Parent, std::move(K), std::move(Obj), std::move(Resolver),
     116         244 :               ProcessAllSections)) {
     117         122 :       buildInitialSymbolTable(PFC->Obj);
     118         122 :     }
     119             : 
     120          86 :     ~ConcreteLinkedObject() override {
     121          43 :       MemMgr->deregisterEHFrames();
     122         172 :     }
     123             : 
     124         120 :     Error finalize() override {
     125             :       assert(PFC && "mapSectionAddress called on finalized LinkedObject");
     126             : 
     127         120 :       JITSymbolResolverAdapter ResolverAdapter(PFC->Parent.ES, *PFC->Resolver,
     128             :                                                nullptr);
     129         120 :       PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
     130         120 :       PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
     131             : 
     132         120 :       Finalized = true;
     133             : 
     134         120 :       std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
     135             :           PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
     136             : 
     137             :       // Copy the symbol table out of the RuntimeDyld instance.
     138             :       {
     139         120 :         auto SymTab = PFC->RTDyld->getSymbolTable();
     140         345 :         for (auto &KV : SymTab)
     141         450 :           SymbolTable[KV.first] = KV.second;
     142             :       }
     143             : 
     144         240 :       if (PFC->Parent.NotifyLoaded)
     145          93 :         PFC->Parent.NotifyLoaded(PFC->K, *PFC->Obj.getBinary(), *Info);
     146             : 
     147             :       PFC->RTDyld->finalizeWithMemoryManagerLocking();
     148             : 
     149         120 :       if (PFC->RTDyld->hasError())
     150           0 :         return make_error<StringError>(PFC->RTDyld->getErrorString(),
     151           0 :                                        inconvertibleErrorCode());
     152             : 
     153         240 :       if (PFC->Parent.NotifyFinalized)
     154          93 :         PFC->Parent.NotifyFinalized(PFC->K);
     155             : 
     156             :       // Release resources.
     157         120 :       PFC = nullptr;
     158             :       return Error::success();
     159             :     }
     160             : 
     161         116 :     JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
     162         464 :       return [this, Name]() -> Expected<JITTargetAddress> {
     163             :         // The symbol may be materialized between the creation of this lambda
     164             :         // and its execution, so we need to double check.
     165         116 :         if (!this->Finalized)
     166         232 :           if (auto Err = this->finalize())
     167             :             return std::move(Err);
     168         232 :         return this->getSymbol(Name, false).getAddress();
     169         232 :       };
     170             :     }
     171             : 
     172           0 :     void mapSectionAddress(const void *LocalAddress,
     173             :                            JITTargetAddress TargetAddr) const override {
     174             :       assert(PFC && "mapSectionAddress called on finalized LinkedObject");
     175             :       assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
     176           0 :       PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
     177           0 :     }
     178             : 
     179             :   private:
     180         122 :     void buildInitialSymbolTable(const OwnedObject &Obj) {
     181        1164 :       for (auto &Symbol : Obj.getBinary()->symbols()) {
     182         676 :         if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
     183         410 :           continue;
     184             :         Expected<StringRef> SymbolName = Symbol.getName();
     185             :         // FIXME: Raise an error for bad symbols.
     186         471 :         if (!SymbolName) {
     187           0 :           consumeError(SymbolName.takeError());
     188             :           continue;
     189             :         }
     190         471 :         auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
     191         471 :         SymbolTable.insert(
     192             :           std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
     193             :       }
     194         122 :     }
     195             : 
     196             :     // Contains the information needed prior to finalization: the object files,
     197             :     // memory manager, resolver, and flags needed for RuntimeDyld.
     198         244 :     struct PreFinalizeContents {
     199         122 :       PreFinalizeContents(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
     200             :                           OwnedObject Obj,
     201             :                           std::shared_ptr<SymbolResolver> Resolver,
     202             :                           bool ProcessAllSections)
     203             :           : Parent(Parent), K(std::move(K)), Obj(std::move(Obj)),
     204             :             Resolver(std::move(Resolver)),
     205         244 :             ProcessAllSections(ProcessAllSections) {}
     206             : 
     207             :       RTDyldObjectLinkingLayer &Parent;
     208             :       VModuleKey K;
     209             :       OwnedObject Obj;
     210             :       std::shared_ptr<SymbolResolver> Resolver;
     211             :       bool ProcessAllSections;
     212             :       std::unique_ptr<RuntimeDyld> RTDyld;
     213             :     };
     214             : 
     215             :     MemoryManagerPtrT MemMgr;
     216             :     std::unique_ptr<PreFinalizeContents> PFC;
     217             :   };
     218             : 
     219             :   template <typename MemoryManagerPtrT>
     220             :   std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>>
     221             :   createLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
     222             :                      OwnedObject Obj, MemoryManagerPtrT MemMgr,
     223             :                      std::shared_ptr<SymbolResolver> Resolver,
     224             :                      bool ProcessAllSections) {
     225             :     using LOS = ConcreteLinkedObject<MemoryManagerPtrT>;
     226             :     return llvm::make_unique<LOS>(Parent, std::move(K), std::move(Obj),
     227             :                                   std::move(MemMgr), std::move(Resolver),
     228         122 :                                   ProcessAllSections);
     229             :   }
     230             : 
     231             : public:
     232         244 :   struct Resources {
     233             :     std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
     234             :     std::shared_ptr<SymbolResolver> Resolver;
     235             :   };
     236             : 
     237             :   using ResourcesGetter = std::function<Resources(VModuleKey)>;
     238             : 
     239             :   /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
     240             :   ///        and NotifyFinalized functors.
     241          92 :   RTDyldObjectLinkingLayer(
     242             :       ExecutionSession &ES, ResourcesGetter GetResources,
     243             :       NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
     244             :       NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
     245          92 :       : ES(ES), GetResources(std::move(GetResources)),
     246             :         NotifyLoaded(std::move(NotifyLoaded)),
     247         184 :         NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) {
     248          92 :   }
     249             : 
     250             :   /// Set the 'ProcessAllSections' flag.
     251             :   ///
     252             :   /// If set to true, all sections in each object file will be allocated using
     253             :   /// the memory manager, rather than just the sections required for execution.
     254             :   ///
     255             :   /// This is kludgy, and may be removed in the future.
     256             :   void setProcessAllSections(bool ProcessAllSections) {
     257           1 :     this->ProcessAllSections = ProcessAllSections;
     258             :   }
     259             : 
     260             :   /// Add an object to the JIT.
     261         122 :   Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
     262             : 
     263             :     auto Obj =
     264         244 :         object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
     265         122 :     if (!Obj)
     266             :       return Obj.takeError();
     267             : 
     268             :     assert(!LinkedObjects.count(K) && "VModuleKey already in use");
     269             : 
     270         244 :     auto R = GetResources(K);
     271             : 
     272         610 :     LinkedObjects[K] = createLinkedObject(
     273         122 :         *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
     274         122 :         std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections);
     275             : 
     276             :     return Error::success();
     277             :   }
     278             : 
     279             :   /// Remove the object associated with VModuleKey K.
     280             :   ///
     281             :   ///   All memory allocated for the object will be freed, and the sections and
     282             :   /// symbols it provided will no longer be available. No attempt is made to
     283             :   /// re-emit the missing symbols, and any use of these symbols (directly or
     284             :   /// indirectly) will result in undefined behavior. If dependence tracking is
     285             :   /// required to detect or resolve such issues it should be added at a higher
     286             :   /// layer.
     287             :   Error removeObject(VModuleKey K) {
     288             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     289             :     // How do we invalidate the symbols in H?
     290             :     LinkedObjects.erase(K);
     291             :     return Error::success();
     292             :   }
     293             : 
     294             :   /// Search for the given named symbol.
     295             :   /// @param Name The name of the symbol to search for.
     296             :   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
     297             :   /// @return A handle for the given named symbol, if it exists.
     298         300 :   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
     299         489 :     for (auto &KV : LinkedObjects)
     300         457 :       if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
     301         158 :         return Sym;
     302         189 :       else if (auto Err = Sym.takeError())
     303             :         return std::move(Err);
     304             : 
     305             :     return nullptr;
     306             :   }
     307             : 
     308             :   /// Search for the given named symbol in the context of the loaded
     309             :   ///        object represented by the VModuleKey K.
     310             :   /// @param K The VModuleKey for the object to search in.
     311             :   /// @param Name The name of the symbol to search for.
     312             :   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
     313             :   /// @return A handle for the given named symbol, if it is found in the
     314             :   ///         given object.
     315             :   JITSymbol findSymbolIn(VModuleKey K, StringRef Name,
     316             :                          bool ExportedSymbolsOnly) {
     317             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     318         574 :     return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
     319             :   }
     320             : 
     321             :   /// Map section addresses for the object associated with the
     322             :   ///        VModuleKey K.
     323           0 :   void mapSectionAddress(VModuleKey K, const void *LocalAddress,
     324             :                          JITTargetAddress TargetAddr) {
     325             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     326           0 :     LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
     327           0 :   }
     328             : 
     329             :   /// Immediately emit and finalize the object represented by the given
     330             :   ///        VModuleKey.
     331             :   /// @param K VModuleKey for object to emit/finalize.
     332           4 :   Error emitAndFinalize(VModuleKey K) {
     333             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     334           8 :     return LinkedObjects[K]->finalize();
     335             :   }
     336             : 
     337             : private:
     338             :   ExecutionSession &ES;
     339             : 
     340             :   std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects;
     341             :   ResourcesGetter GetResources;
     342             :   NotifyLoadedFtor NotifyLoaded;
     343             :   NotifyFinalizedFtor NotifyFinalized;
     344             :   bool ProcessAllSections = false;
     345             : };
     346             : 
     347             : } // end namespace orc
     348             : } // end namespace llvm
     349             : 
     350             : #endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H

Generated by: LCOV version 1.13