LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - RTDyldObjectLinkingLayer.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 92 97 94.8 %
Date: 2017-09-14 15:23:50 Functions: 15 16 93.8 %
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/RuntimeDyld.h"
      22             : #include "llvm/Object/ObjectFile.h"
      23             : #include "llvm/Support/Error.h"
      24             : #include <algorithm>
      25             : #include <cassert>
      26             : #include <functional>
      27             : #include <list>
      28             : #include <memory>
      29             : #include <string>
      30             : #include <utility>
      31             : #include <vector>
      32             : 
      33             : namespace llvm {
      34             : namespace orc {
      35             : 
      36             : class RTDyldObjectLinkingLayerBase {
      37             : public:
      38             : 
      39             :   using ObjectPtr =
      40             :     std::shared_ptr<object::OwningBinary<object::ObjectFile>>;
      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         266 :     LinkedObject() = default;
      54             :     LinkedObject(const LinkedObject&) = delete;
      55             :     void operator=(const LinkedObject&) = delete;
      56          54 :     virtual ~LinkedObject() = default;
      57             : 
      58             :     virtual void 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         694 :     JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
      67         694 :       auto SymEntry = SymbolTable.find(Name);
      68        1388 :       if (SymEntry == SymbolTable.end())
      69             :         return nullptr;
      70         371 :       if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
      71             :         return nullptr;
      72         371 :       if (!Finalized)
      73         508 :         return JITSymbol(getSymbolMaterializer(Name),
      74         254 :                          SymEntry->second.getFlags());
      75         244 :       return JITSymbol(SymEntry->second);
      76             :     }
      77             : 
      78             :   protected:
      79             :     StringMap<JITEvaluatedSymbol> SymbolTable;
      80             :     bool Finalized = false;
      81             :   };
      82             : 
      83             :   using LinkedObjectListT = std::list<std::unique_ptr<LinkedObject>>;
      84             : 
      85             : public:
      86             :   /// @brief Handle to a loaded object.
      87             :   using ObjHandleT = LinkedObjectListT::iterator;
      88             : };
      89             : 
      90             : /// @brief Bare bones object linking layer.
      91             : ///
      92             : ///   This class is intended to be used as the base layer for a JIT. It allows
      93             : /// object files to be loaded into memory, linked, and the addresses of their
      94             : /// symbols queried. All objects added to this layer can see each other's
      95             : /// symbols.
      96         180 : class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
      97             : public:
      98             : 
      99             :   using RTDyldObjectLinkingLayerBase::ObjectPtr;
     100             : 
     101             :   /// @brief Functor for receiving object-loaded notifications.
     102             :   using NotifyLoadedFtor = std::function<void(ObjHandleT, const ObjectPtr &Obj,
     103             :                                               const LoadedObjectInfo &)>;
     104             : 
     105             :   /// @brief Functor for receiving finalization notifications.
     106             :   using NotifyFinalizedFtor = std::function<void(ObjHandleT)>;
     107             : 
     108             : private:
     109             : 
     110             : 
     111             :   template <typename MemoryManagerPtrT, typename SymbolResolverPtrT,
     112             :             typename FinalizerFtor>
     113             :   class ConcreteLinkedObject : public LinkedObject {
     114             :   public:
     115         133 :     ConcreteLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr,
     116             :                          SymbolResolverPtrT Resolver,
     117             :                          FinalizerFtor Finalizer,
     118             :                          bool ProcessAllSections)
     119         133 :       : MemMgr(std::move(MemMgr)),
     120         133 :         PFC(llvm::make_unique<PreFinalizeContents>(std::move(Obj),
     121         133 :                                                    std::move(Resolver),
     122         133 :                                                    std::move(Finalizer),
     123         532 :                                                    ProcessAllSections)) {
     124         266 :       buildInitialSymbolTable(PFC->Obj);
     125         133 :     }
     126             : 
     127         108 :     ~ConcreteLinkedObject() override {
     128         108 :       MemMgr->deregisterEHFrames();
     129         270 :     }
     130             : 
     131             :     void setHandle(ObjHandleT H) {
     132         266 :       PFC->Handle = H;
     133             :     }
     134             : 
     135         131 :     void finalize() override {
     136             :       assert(PFC && "mapSectionAddress called on finalized LinkedObject");
     137             : 
     138         655 :       RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver);
     139         393 :       RTDyld.setProcessAllSections(PFC->ProcessAllSections);
     140         262 :       PFC->RTDyld = &RTDyld;
     141             : 
     142         131 :       this->Finalized = true;
     143         786 :       PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Obj),
     144             :                      [&]() {
     145         131 :                        this->updateSymbolTable(RTDyld);
     146             :                      });
     147             : 
     148             :       // Release resources.
     149         131 :       PFC = nullptr;
     150         131 :     }
     151             : 
     152         127 :     JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
     153             :       return
     154        1016 :         [this, Name]() {
     155             :           // The symbol may be materialized between the creation of this lambda
     156             :           // and its execution, so we need to double check.
     157         127 :           if (!this->Finalized)
     158         127 :             this->finalize();
     159         254 :           return this->getSymbol(Name, false).getAddress();
     160         508 :         };
     161             :     }
     162             : 
     163           0 :     void mapSectionAddress(const void *LocalAddress,
     164             :                            JITTargetAddress TargetAddr) const override {
     165             :       assert(PFC && "mapSectionAddress called on finalized LinkedObject");
     166             :       assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
     167           0 :       PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
     168           0 :     }
     169             : 
     170             :   private:
     171             : 
     172         133 :     void buildInitialSymbolTable(const ObjectPtr &Obj) {
     173        2211 :       for (auto &Symbol : Obj->getBinary()->symbols()) {
     174        1546 :         if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
     175         430 :           continue;
     176        1116 :         Expected<StringRef> SymbolName = Symbol.getName();
     177             :         // FIXME: Raise an error for bad symbols.
     178         558 :         if (!SymbolName) {
     179           0 :           consumeError(SymbolName.takeError());
     180             :           continue;
     181             :         }
     182         558 :         auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
     183        1674 :         SymbolTable.insert(
     184         558 :           std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
     185             :       }
     186         133 :     }
     187             : 
     188         131 :     void updateSymbolTable(const RuntimeDyld &RTDyld) {
     189        1540 :       for (auto &SymEntry : SymbolTable)
     190         508 :         SymEntry.second = RTDyld.getSymbol(SymEntry.first());
     191         131 :     }
     192             : 
     193             :     // Contains the information needed prior to finalization: the object files,
     194             :     // memory manager, resolver, and flags needed for RuntimeDyld.
     195         399 :     struct PreFinalizeContents {
     196         133 :       PreFinalizeContents(ObjectPtr Obj, SymbolResolverPtrT Resolver,
     197             :                           FinalizerFtor Finalizer, bool ProcessAllSections)
     198         266 :         : Obj(std::move(Obj)), Resolver(std::move(Resolver)),
     199         133 :           Finalizer(std::move(Finalizer)),
     200         665 :           ProcessAllSections(ProcessAllSections) {}
     201             : 
     202             :       ObjectPtr Obj;
     203             :       SymbolResolverPtrT Resolver;
     204             :       FinalizerFtor Finalizer;
     205             :       bool ProcessAllSections;
     206             :       ObjHandleT Handle;
     207             :       RuntimeDyld *RTDyld;
     208             :     };
     209             : 
     210             :     MemoryManagerPtrT MemMgr;
     211             :     std::unique_ptr<PreFinalizeContents> PFC;
     212             :   };
     213             : 
     214             :   template <typename MemoryManagerPtrT, typename SymbolResolverPtrT,
     215             :             typename FinalizerFtor>
     216             :   std::unique_ptr<
     217             :     ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT, FinalizerFtor>>
     218             :   createLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr,
     219             :                      SymbolResolverPtrT Resolver,
     220             :                      FinalizerFtor Finalizer,
     221             :                      bool ProcessAllSections) {
     222             :     using LOS = ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT,
     223             :                                      FinalizerFtor>;
     224         133 :     return llvm::make_unique<LOS>(std::move(Obj), std::move(MemMgr),
     225         133 :                                   std::move(Resolver), std::move(Finalizer),
     226         133 :                                   ProcessAllSections);
     227             :   }
     228             : 
     229             : public:
     230             : 
     231             :   /// @brief Functor for creating memory managers.
     232             :   using MemoryManagerGetter =
     233             :     std::function<std::shared_ptr<RuntimeDyld::MemoryManager>()>;
     234             : 
     235             :   /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
     236             :   ///        and NotifyFinalized functors.
     237         102 :   RTDyldObjectLinkingLayer(
     238             :       MemoryManagerGetter GetMemMgr,
     239             :       NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
     240             :       NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
     241         102 :       : GetMemMgr(GetMemMgr),
     242         102 :         NotifyLoaded(std::move(NotifyLoaded)),
     243         102 :         NotifyFinalized(std::move(NotifyFinalized)),
     244         510 :         ProcessAllSections(false) {}
     245             : 
     246             :   /// @brief Set the 'ProcessAllSections' flag.
     247             :   ///
     248             :   /// If set to true, all sections in each object file will be allocated using
     249             :   /// the memory manager, rather than just the sections required for execution.
     250             :   ///
     251             :   /// This is kludgy, and may be removed in the future.
     252             :   void setProcessAllSections(bool ProcessAllSections) {
     253          13 :     this->ProcessAllSections = ProcessAllSections;
     254             :   }
     255             : 
     256             :   /// @brief Add an object to the JIT.
     257             :   ///
     258             :   /// @return A handle that can be used to refer to the loaded object (for 
     259             :   ///         symbol searching, finalization, freeing memory, etc.).
     260         133 :   Expected<ObjHandleT> addObject(ObjectPtr Obj,
     261             :                                  std::shared_ptr<JITSymbolResolver> Resolver) {
     262             :     auto Finalizer = [&](ObjHandleT H, RuntimeDyld &RTDyld,
     263             :                          const ObjectPtr &ObjToLoad,
     264         131 :                          std::function<void()> LOSHandleLoad) {
     265             :       std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
     266         393 :         RTDyld.loadObject(*ObjToLoad->getBinary());
     267             : 
     268         131 :       LOSHandleLoad();
     269             : 
     270         393 :       if (this->NotifyLoaded)
     271         210 :         this->NotifyLoaded(H, ObjToLoad, *Info);
     272             : 
     273         131 :       RTDyld.finalizeWithMemoryManagerLocking();
     274             : 
     275         262 :       if (this->NotifyFinalized)
     276         105 :         this->NotifyFinalized(H);
     277         264 :     };
     278             : 
     279             :     auto LO =
     280         399 :       createLinkedObject(std::move(Obj), GetMemMgr(),
     281         133 :                          std::move(Resolver), std::move(Finalizer),
     282         931 :                          ProcessAllSections);
     283             :     // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle
     284             :     // below.
     285         133 :     auto *LOPtr = LO.get();
     286             : 
     287         665 :     ObjHandleT Handle = LinkedObjList.insert(LinkedObjList.end(), std::move(LO));
     288         133 :     LOPtr->setHandle(Handle);
     289             : 
     290         266 :     return Handle;
     291             :   }
     292             : 
     293             :   /// @brief Remove the object associated with handle H.
     294             :   ///
     295             :   ///   All memory allocated for the object will be freed, and the sections and
     296             :   /// symbols it provided will no longer be available. No attempt is made to
     297             :   /// re-emit the missing symbols, and any use of these symbols (directly or
     298             :   /// indirectly) will result in undefined behavior. If dependence tracking is
     299             :   /// required to detect or resolve such issues it should be added at a higher
     300             :   /// layer.
     301             :   Error removeObject(ObjHandleT H) {
     302             :     // How do we invalidate the symbols in H?
     303          52 :     LinkedObjList.erase(H);
     304          78 :     return Error::success();
     305             :   }
     306             : 
     307             :   /// @brief Search for the given named symbol.
     308             :   /// @param Name The name of the symbol to search for.
     309             :   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
     310             :   /// @return A handle for the given named symbol, if it exists.
     311         312 :   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
     312         936 :     for (auto I = LinkedObjList.begin(), E = LinkedObjList.end(); I != E;
     313             :          ++I)
     314         725 :       if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
     315          79 :         return Symbol;
     316             : 
     317             :     return nullptr;
     318             :   }
     319             : 
     320             :   /// @brief Search for the given named symbol in the context of the loaded
     321             :   ///        object represented by the handle H.
     322             :   /// @param H The handle for the object to search in.
     323             :   /// @param Name The name of the symbol to search for.
     324             :   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
     325             :   /// @return A handle for the given named symbol, if it is found in the
     326             :   ///         given object.
     327             :   JITSymbol findSymbolIn(ObjHandleT H, StringRef Name,
     328             :                          bool ExportedSymbolsOnly) {
     329        1134 :     return (*H)->getSymbol(Name, ExportedSymbolsOnly);
     330             :   }
     331             : 
     332             :   /// @brief Map section addresses for the object associated with the handle H.
     333             :   void mapSectionAddress(ObjHandleT H, const void *LocalAddress,
     334             :                          JITTargetAddress TargetAddr) {
     335           0 :     (*H)->mapSectionAddress(LocalAddress, TargetAddr);
     336             :   }
     337             : 
     338             :   /// @brief Immediately emit and finalize the object represented by the given
     339             :   ///        handle.
     340             :   /// @param H Handle for object to emit/finalize.
     341             :   Error emitAndFinalize(ObjHandleT H) {
     342           8 :     (*H)->finalize();
     343          12 :     return Error::success();
     344             :   }
     345             : 
     346             : private:
     347             : 
     348             :   LinkedObjectListT LinkedObjList;
     349             :   MemoryManagerGetter GetMemMgr;
     350             :   NotifyLoadedFtor NotifyLoaded;
     351             :   NotifyFinalizedFtor NotifyFinalized;
     352             :   bool ProcessAllSections = false;
     353             : };
     354             : 
     355             : } // end namespace orc
     356             : } // end namespace llvm
     357             : 
     358             : #endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H

Generated by: LCOV version 1.13