LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - RTDyldObjectLinkingLayer.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 73 82 89.0 %
Date: 2018-02-23 15:42:53 Functions: 16 18 88.9 %
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             :   /// @brief 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             : /// @brief 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             :   /// @brief Functor for receiving object-loaded notifications.
      96             :   using NotifyLoadedFtor =
      97             :       std::function<void(VModuleKey, const object::ObjectFile &Obj,
      98             :                          const RuntimeDyld::LoadedObjectInfo &)>;
      99             : 
     100             :   /// @brief 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         120 :       PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
     129         120 :       PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
     130             : 
     131         120 :       Finalized = true;
     132             : 
     133         120 :       std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
     134             :           PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
     135             : 
     136         120 :       updateSymbolTable(*PFC->RTDyld);
     137             : 
     138         240 :       if (PFC->Parent.NotifyLoaded)
     139          93 :         PFC->Parent.NotifyLoaded(PFC->K, *PFC->Obj.getBinary(), *Info);
     140             : 
     141         120 :       PFC->RTDyld->finalizeWithMemoryManagerLocking();
     142             : 
     143         120 :       if (PFC->RTDyld->hasError())
     144           0 :         return make_error<StringError>(PFC->RTDyld->getErrorString(),
     145           0 :                                        inconvertibleErrorCode());
     146             : 
     147         120 :       if (PFC->Parent.NotifyFinalized)
     148          93 :         PFC->Parent.NotifyFinalized(PFC->K);
     149             : 
     150             :       // Release resources.
     151         120 :       PFC = nullptr;
     152             :       return Error::success();
     153             :     }
     154             : 
     155         116 :     JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
     156         464 :       return [this, Name]() -> Expected<JITTargetAddress> {
     157             :         // The symbol may be materialized between the creation of this lambda
     158             :         // and its execution, so we need to double check.
     159         116 :         if (!this->Finalized)
     160         232 :           if (auto Err = this->finalize())
     161             :             return std::move(Err);
     162         232 :         return this->getSymbol(Name, false).getAddress();
     163         232 :       };
     164             :     }
     165             : 
     166           0 :     void mapSectionAddress(const void *LocalAddress,
     167             :                            JITTargetAddress TargetAddr) const override {
     168             :       assert(PFC && "mapSectionAddress called on finalized LinkedObject");
     169             :       assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
     170           0 :       PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
     171           0 :     }
     172             : 
     173             :   private:
     174         122 :     void buildInitialSymbolTable(const OwnedObject &Obj) {
     175        1164 :       for (auto &Symbol : Obj.getBinary()->symbols()) {
     176         676 :         if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
     177         410 :           continue;
     178             :         Expected<StringRef> SymbolName = Symbol.getName();
     179             :         // FIXME: Raise an error for bad symbols.
     180         471 :         if (!SymbolName) {
     181           0 :           consumeError(SymbolName.takeError());
     182             :           continue;
     183             :         }
     184         471 :         auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
     185         471 :         SymbolTable.insert(
     186             :           std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
     187             :       }
     188         122 :     }
     189             : 
     190         120 :     void updateSymbolTable(const RuntimeDyld &RTDyld) {
     191         690 :       for (auto &SymEntry : SymbolTable)
     192         450 :         SymEntry.second = RTDyld.getSymbol(SymEntry.first());
     193         120 :     }
     194             : 
     195             :     // Contains the information needed prior to finalization: the object files,
     196             :     // memory manager, resolver, and flags needed for RuntimeDyld.
     197         244 :     struct PreFinalizeContents {
     198         122 :       PreFinalizeContents(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
     199             :                           OwnedObject Obj,
     200             :                           std::shared_ptr<SymbolResolver> Resolver,
     201             :                           bool ProcessAllSections)
     202             :           : Parent(Parent), K(std::move(K)), Obj(std::move(Obj)),
     203             :             Resolver(std::move(Resolver)),
     204         244 :             ProcessAllSections(ProcessAllSections) {}
     205             : 
     206             :       RTDyldObjectLinkingLayer &Parent;
     207             :       VModuleKey K;
     208             :       OwnedObject Obj;
     209             :       std::shared_ptr<SymbolResolver> Resolver;
     210             :       bool ProcessAllSections;
     211             :       std::unique_ptr<RuntimeDyld> RTDyld;
     212             :     };
     213             : 
     214             :     MemoryManagerPtrT MemMgr;
     215             :     std::unique_ptr<PreFinalizeContents> PFC;
     216             :   };
     217             : 
     218             :   template <typename MemoryManagerPtrT>
     219             :   std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>>
     220             :   createLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
     221             :                      OwnedObject Obj, MemoryManagerPtrT MemMgr,
     222             :                      std::shared_ptr<SymbolResolver> Resolver,
     223             :                      bool ProcessAllSections) {
     224             :     using LOS = ConcreteLinkedObject<MemoryManagerPtrT>;
     225             :     return llvm::make_unique<LOS>(Parent, std::move(K), std::move(Obj),
     226             :                                   std::move(MemMgr), std::move(Resolver),
     227         122 :                                   ProcessAllSections);
     228             :   }
     229             : 
     230             : public:
     231         244 :   struct Resources {
     232             :     std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
     233             :     std::shared_ptr<SymbolResolver> Resolver;
     234             :   };
     235             : 
     236             :   using ResourcesGetter = std::function<Resources(VModuleKey)>;
     237             : 
     238             :   /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
     239             :   ///        and NotifyFinalized functors.
     240          92 :   RTDyldObjectLinkingLayer(
     241             :       ExecutionSession &ES, ResourcesGetter GetResources,
     242             :       NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
     243             :       NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
     244          92 :       : ES(ES), GetResources(std::move(GetResources)),
     245             :         NotifyLoaded(std::move(NotifyLoaded)),
     246         184 :         NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) {
     247          92 :   }
     248             : 
     249             :   /// @brief Set the 'ProcessAllSections' flag.
     250             :   ///
     251             :   /// If set to true, all sections in each object file will be allocated using
     252             :   /// the memory manager, rather than just the sections required for execution.
     253             :   ///
     254             :   /// This is kludgy, and may be removed in the future.
     255             :   void setProcessAllSections(bool ProcessAllSections) {
     256           1 :     this->ProcessAllSections = ProcessAllSections;
     257             :   }
     258             : 
     259             :   /// @brief Add an object to the JIT.
     260         122 :   Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
     261             : 
     262             :     auto Obj =
     263         244 :         object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
     264         122 :     if (!Obj)
     265             :       return Obj.takeError();
     266             : 
     267             :     assert(!LinkedObjects.count(K) && "VModuleKey already in use");
     268             : 
     269         244 :     auto R = GetResources(K);
     270             : 
     271         610 :     LinkedObjects[K] = createLinkedObject(
     272         122 :         *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
     273         122 :         std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections);
     274             : 
     275             :     return Error::success();
     276             :   }
     277             : 
     278             :   /// @brief Remove the object associated with VModuleKey K.
     279             :   ///
     280             :   ///   All memory allocated for the object will be freed, and the sections and
     281             :   /// symbols it provided will no longer be available. No attempt is made to
     282             :   /// re-emit the missing symbols, and any use of these symbols (directly or
     283             :   /// indirectly) will result in undefined behavior. If dependence tracking is
     284             :   /// required to detect or resolve such issues it should be added at a higher
     285             :   /// layer.
     286             :   Error removeObject(VModuleKey K) {
     287             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     288             :     // How do we invalidate the symbols in H?
     289             :     LinkedObjects.erase(K);
     290             :     return Error::success();
     291             :   }
     292             : 
     293             :   /// @brief Search for the given named symbol.
     294             :   /// @param Name The name of the symbol to search for.
     295             :   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
     296             :   /// @return A handle for the given named symbol, if it exists.
     297         302 :   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
     298         491 :     for (auto &KV : LinkedObjects)
     299         458 :       if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
     300         160 :         return Sym;
     301         189 :       else if (auto Err = Sym.takeError())
     302             :         return std::move(Err);
     303             : 
     304             :     return nullptr;
     305             :   }
     306             : 
     307             :   /// @brief Search for the given named symbol in the context of the loaded
     308             :   ///        object represented by the VModuleKey K.
     309             :   /// @param K The VModuleKey for the object to search in.
     310             :   /// @param Name The name of the symbol to search for.
     311             :   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
     312             :   /// @return A handle for the given named symbol, if it is found in the
     313             :   ///         given object.
     314             :   JITSymbol findSymbolIn(VModuleKey K, StringRef Name,
     315             :                          bool ExportedSymbolsOnly) {
     316             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     317         572 :     return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
     318             :   }
     319             : 
     320             :   /// @brief Map section addresses for the object associated with the
     321             :   ///        VModuleKey K.
     322           0 :   void mapSectionAddress(VModuleKey K, const void *LocalAddress,
     323             :                          JITTargetAddress TargetAddr) {
     324             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     325           0 :     LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
     326           0 :   }
     327             : 
     328             :   /// @brief Immediately emit and finalize the object represented by the given
     329             :   ///        VModuleKey.
     330             :   /// @param K VModuleKey for object to emit/finalize.
     331           4 :   Error emitAndFinalize(VModuleKey K) {
     332             :     assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
     333           8 :     return LinkedObjects[K]->finalize();
     334             :   }
     335             : 
     336             : private:
     337             :   ExecutionSession &ES;
     338             : 
     339             :   std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects;
     340             :   ResourcesGetter GetResources;
     341             :   NotifyLoadedFtor NotifyLoaded;
     342             :   NotifyFinalizedFtor NotifyFinalized;
     343             :   bool ProcessAllSections = false;
     344             : };
     345             : 
     346             : } // end namespace orc
     347             : } // end namespace llvm
     348             : 
     349             : #endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H

Generated by: LCOV version 1.13