Home | History | Annotate | Line # | Download | only in JITLink
      1 //===------ JITLinkGeneric.h - Generic JIT linker utilities -----*- 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 // Generic JITLinker utilities. E.g. graph pruning, eh-frame parsing.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LIB_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
     14 #define LIB_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
     15 
     16 #include "llvm/ADT/DenseSet.h"
     17 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
     18 
     19 #define DEBUG_TYPE "jitlink"
     20 
     21 namespace llvm {
     22 
     23 class MemoryBufferRef;
     24 
     25 namespace jitlink {
     26 
     27 /// Base class for a JIT linker.
     28 ///
     29 /// A JITLinkerBase instance links one object file into an ongoing JIT
     30 /// session. Symbol resolution and finalization operations are pluggable,
     31 /// and called using continuation passing (passing a continuation for the
     32 /// remaining linker work) to allow them to be performed asynchronously.
     33 class JITLinkerBase {
     34 public:
     35   JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx,
     36                 std::unique_ptr<LinkGraph> G, PassConfiguration Passes)
     37       : Ctx(std::move(Ctx)), G(std::move(G)), Passes(std::move(Passes)) {
     38     assert(this->Ctx && "Ctx can not be null");
     39     assert(this->G && "G can not be null");
     40   }
     41 
     42   virtual ~JITLinkerBase();
     43 
     44 protected:
     45   struct SegmentLayout {
     46     using BlocksList = std::vector<Block *>;
     47 
     48     BlocksList ContentBlocks;
     49     BlocksList ZeroFillBlocks;
     50   };
     51 
     52   using SegmentLayoutMap = DenseMap<unsigned, SegmentLayout>;
     53 
     54   // Returns the PassConfiguration for this instance. This can be used by
     55   // JITLinkerBase implementations to add late passes that reference their
     56   // own data structures (e.g. for ELF implementations to locate / construct
     57   // a GOT start symbol prior to fixup).
     58   PassConfiguration &getPassConfig() { return Passes; }
     59 
     60   // Phase 1:
     61   //   1.1: Run pre-prune passes
     62   //   1.2: Prune graph
     63   //   1.3: Run post-prune passes
     64   //   1.4: Sort blocks into segments
     65   //   1.5: Allocate segment memory, update node vmaddrs to target vmaddrs
     66   //   1.6: Run post-allocation passes
     67   //   1.7: Notify context of final assigned symbol addresses
     68   //   1.8: Identify external symbols and make an async call to resolve
     69   void linkPhase1(std::unique_ptr<JITLinkerBase> Self);
     70 
     71   // Phase 2:
     72   //   2.1: Apply resolution results
     73   //   2.2: Run pre-fixup passes
     74   //   2.3: Fix up block contents
     75   //   2.4: Run post-fixup passes
     76   //   2.5: Make an async call to transfer and finalize memory.
     77   void linkPhase2(std::unique_ptr<JITLinkerBase> Self,
     78                   Expected<AsyncLookupResult> LookupResult,
     79                   SegmentLayoutMap Layout);
     80 
     81   // Phase 3:
     82   //   3.1: Call OnFinalized callback, handing off allocation.
     83   void linkPhase3(std::unique_ptr<JITLinkerBase> Self, Error Err);
     84 
     85   // Align a JITTargetAddress to conform with block alignment requirements.
     86   static JITTargetAddress alignToBlock(JITTargetAddress Addr, Block &B) {
     87     uint64_t Delta = (B.getAlignmentOffset() - Addr) % B.getAlignment();
     88     return Addr + Delta;
     89   }
     90 
     91   // Align a pointer to conform with block alignment requirements.
     92   static char *alignToBlock(char *P, Block &B) {
     93     uint64_t PAddr = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(P));
     94     uint64_t Delta = (B.getAlignmentOffset() - PAddr) % B.getAlignment();
     95     return P + Delta;
     96   }
     97 
     98 private:
     99   // Run all passes in the given pass list, bailing out immediately if any pass
    100   // returns an error.
    101   Error runPasses(LinkGraphPassList &Passes);
    102 
    103   // Copy block contents and apply relocations.
    104   // Implemented in JITLinker.
    105   virtual Error fixUpBlocks(LinkGraph &G) const = 0;
    106 
    107   SegmentLayoutMap layOutBlocks();
    108   Error allocateSegments(const SegmentLayoutMap &Layout);
    109   JITLinkContext::LookupMap getExternalSymbolNames() const;
    110   void applyLookupResult(AsyncLookupResult LR);
    111   void copyBlockContentToWorkingMemory(const SegmentLayoutMap &Layout,
    112                                        JITLinkMemoryManager::Allocation &Alloc);
    113   void deallocateAndBailOut(Error Err);
    114 
    115   std::unique_ptr<JITLinkContext> Ctx;
    116   std::unique_ptr<LinkGraph> G;
    117   PassConfiguration Passes;
    118   std::unique_ptr<JITLinkMemoryManager::Allocation> Alloc;
    119 };
    120 
    121 template <typename LinkerImpl> class JITLinker : public JITLinkerBase {
    122 public:
    123   using JITLinkerBase::JITLinkerBase;
    124 
    125   /// Link constructs a LinkerImpl instance and calls linkPhase1.
    126   /// Link should be called with the constructor arguments for LinkerImpl, which
    127   /// will be forwarded to the constructor.
    128   template <typename... ArgTs> static void link(ArgTs &&... Args) {
    129     auto L = std::make_unique<LinkerImpl>(std::forward<ArgTs>(Args)...);
    130 
    131     // Ownership of the linker is passed into the linker's doLink function to
    132     // allow it to be passed on to async continuations.
    133     //
    134     // FIXME: Remove LTmp once we have c++17.
    135     // C++17 sequencing rules guarantee that function name expressions are
    136     // sequenced before arguments, so L->linkPhase1(std::move(L), ...) will be
    137     // well formed.
    138     auto &LTmp = *L;
    139     LTmp.linkPhase1(std::move(L));
    140   }
    141 
    142 private:
    143   const LinkerImpl &impl() const {
    144     return static_cast<const LinkerImpl &>(*this);
    145   }
    146 
    147   Error fixUpBlocks(LinkGraph &G) const override {
    148     LLVM_DEBUG(dbgs() << "Fixing up blocks:\n");
    149 
    150     for (auto *B : G.blocks()) {
    151       LLVM_DEBUG(dbgs() << "  " << *B << ":\n");
    152 
    153       // Copy Block data and apply fixups.
    154       LLVM_DEBUG(dbgs() << "    Applying fixups.\n");
    155       for (auto &E : B->edges()) {
    156 
    157         // Skip non-relocation edges.
    158         if (!E.isRelocation())
    159           continue;
    160 
    161         // Dispatch to LinkerImpl for fixup.
    162         auto *BlockData = const_cast<char *>(B->getContent().data());
    163         if (auto Err = impl().applyFixup(G, *B, E, BlockData))
    164           return Err;
    165       }
    166     }
    167 
    168     return Error::success();
    169   }
    170 };
    171 
    172 /// Removes dead symbols/blocks/addressables.
    173 ///
    174 /// Finds the set of symbols and addressables reachable from any symbol
    175 /// initially marked live. All symbols/addressables not marked live at the end
    176 /// of this process are removed.
    177 void prune(LinkGraph &G);
    178 
    179 } // end namespace jitlink
    180 } // end namespace llvm
    181 
    182 #undef DEBUG_TYPE // "jitlink"
    183 
    184 #endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
    185