LLVM  10.0.0svn
JITLinkGeneric.h
Go to the documentation of this file.
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"
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.
34 public:
35  JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx, PassConfiguration Passes)
36  : Ctx(std::move(Ctx)), Passes(std::move(Passes)) {
37  assert(this->Ctx && "Ctx can not be null");
38  }
39 
40  virtual ~JITLinkerBase();
41 
42 protected:
43  struct SegmentLayout {
44  using BlocksList = std::vector<Block *>;
45 
48  };
49 
51 
52  // Phase 1:
53  // 1.1: Build link graph
54  // 1.2: Run pre-prune passes
55  // 1.2: Prune graph
56  // 1.3: Run post-prune passes
57  // 1.4: Sort blocks into segments
58  // 1.5: Allocate segment memory
59  // 1.6: Identify externals and make an async call to resolve function
60  void linkPhase1(std::unique_ptr<JITLinkerBase> Self);
61 
62  // Phase 2:
63  // 2.1: Apply resolution results
64  // 2.2: Fix up block contents
65  // 2.3: Call OnResolved callback
66  // 2.3: Make an async call to transfer and finalize memory.
67  void linkPhase2(std::unique_ptr<JITLinkerBase> Self,
68  Expected<AsyncLookupResult> LookupResult,
69  SegmentLayoutMap Layout);
70 
71  // Phase 3:
72  // 3.1: Call OnFinalized callback, handing off allocation.
73  void linkPhase3(std::unique_ptr<JITLinkerBase> Self, Error Err);
74 
75  // Build a graph from the given object buffer.
76  // To be implemented by the client.
78  buildGraph(MemoryBufferRef ObjBuffer) = 0;
79 
80  // For debug dumping of the link graph.
81  virtual StringRef getEdgeKindName(Edge::Kind K) const = 0;
82 
83  // Alight a JITTargetAddress to conform with block alignment requirements.
85  uint64_t Delta = (B.getAlignmentOffset() - Addr) % B.getAlignment();
86  return Addr + Delta;
87  }
88 
89  // Alight a pointer to conform with block alignment requirements.
90  static char *alignToBlock(char *P, Block &B) {
91  uint64_t PAddr = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(P));
92  uint64_t Delta = (B.getAlignmentOffset() - PAddr) % B.getAlignment();
93  return P + Delta;
94  }
95 
96 private:
97  // Run all passes in the given pass list, bailing out immediately if any pass
98  // returns an error.
99  Error runPasses(LinkGraphPassList &Passes);
100 
101  // Copy block contents and apply relocations.
102  // Implemented in JITLinker.
103  virtual Error
104  copyAndFixUpBlocks(const SegmentLayoutMap &Layout,
105  JITLinkMemoryManager::Allocation &Alloc) const = 0;
106 
107  SegmentLayoutMap layOutBlocks();
108  Error allocateSegments(const SegmentLayoutMap &Layout);
109  DenseSet<StringRef> getExternalSymbolNames() const;
110  void applyLookupResult(AsyncLookupResult LR);
111  void deallocateAndBailOut(Error Err);
112 
113  void dumpGraph(raw_ostream &OS);
114 
115  std::unique_ptr<JITLinkContext> Ctx;
116  PassConfiguration Passes;
117  std::unique_ptr<LinkGraph> G;
118  std::unique_ptr<JITLinkMemoryManager::Allocation> Alloc;
119 };
120 
121 template <typename LinkerImpl> class JITLinker : public JITLinkerBase {
122 public:
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
148  copyAndFixUpBlocks(const SegmentLayoutMap &Layout,
149  JITLinkMemoryManager::Allocation &Alloc) const override {
150  LLVM_DEBUG(dbgs() << "Copying and fixing up blocks:\n");
151  for (auto &KV : Layout) {
152  auto &Prot = KV.first;
153  auto &SegLayout = KV.second;
154 
155  auto SegMem = Alloc.getWorkingMemory(
156  static_cast<sys::Memory::ProtectionFlags>(Prot));
157  char *LastBlockEnd = SegMem.data();
158  char *BlockDataPtr = LastBlockEnd;
159 
160  LLVM_DEBUG({
161  dbgs() << " Processing segment "
162  << static_cast<sys::Memory::ProtectionFlags>(Prot) << " [ "
163  << (const void *)SegMem.data() << " .. "
164  << (const void *)((char *)SegMem.data() + SegMem.size())
165  << " ]\n Processing content sections:\n";
166  });
167 
168  for (auto *B : SegLayout.ContentBlocks) {
169  LLVM_DEBUG(dbgs() << " " << *B << ":\n");
170 
171  // Pad to alignment/alignment-offset.
172  BlockDataPtr = alignToBlock(BlockDataPtr, *B);
173 
174  LLVM_DEBUG({
175  dbgs() << " Bumped block pointer to "
176  << (const void *)BlockDataPtr << " to meet block alignment "
177  << B->getAlignment() << " and alignment offset "
178  << B->getAlignmentOffset() << "\n";
179  });
180 
181  // Zero pad up to alignment.
182  LLVM_DEBUG({
183  if (LastBlockEnd != BlockDataPtr)
184  dbgs() << " Zero padding from " << (const void *)LastBlockEnd
185  << " to " << (const void *)BlockDataPtr << "\n";
186  });
187 
188  while (LastBlockEnd != BlockDataPtr)
189  *LastBlockEnd++ = 0;
190 
191  // Copy initial block content.
192  LLVM_DEBUG({
193  dbgs() << " Copying block " << *B << " content, "
194  << B->getContent().size() << " bytes, from "
195  << (const void *)B->getContent().data() << " to "
196  << (const void *)BlockDataPtr << "\n";
197  });
198  memcpy(BlockDataPtr, B->getContent().data(), B->getContent().size());
199 
200  // Copy Block data and apply fixups.
201  LLVM_DEBUG(dbgs() << " Applying fixups.\n");
202  for (auto &E : B->edges()) {
203 
204  // Skip non-relocation edges.
205  if (!E.isRelocation())
206  continue;
207 
208  // Dispatch to LinkerImpl for fixup.
209  if (auto Err = impl().applyFixup(*B, E, BlockDataPtr))
210  return Err;
211  }
212 
213  // Point the block's content to the fixed up buffer.
214  B->setContent(StringRef(BlockDataPtr, B->getContent().size()));
215 
216  // Update block end pointer.
217  LastBlockEnd = BlockDataPtr + B->getContent().size();
218  BlockDataPtr = LastBlockEnd;
219  }
220 
221  // Zero pad the rest of the segment.
222  LLVM_DEBUG({
223  dbgs() << " Zero padding end of segment from "
224  << (const void *)LastBlockEnd << " to "
225  << (const void *)((char *)SegMem.data() + SegMem.size()) << "\n";
226  });
227  while (LastBlockEnd != SegMem.data() + SegMem.size())
228  *LastBlockEnd++ = 0;
229  }
230 
231  return Error::success();
232  }
233 };
234 
235 /// Removes dead symbols/blocks/addressables.
236 ///
237 /// Finds the set of symbols and addressables reachable from any symbol
238 /// initially marked live. All symbols/addressables not marked live at the end
239 /// of this process are removed.
240 void prune(LinkGraph &G);
241 
242 } // end namespace jitlink
243 } // end namespace llvm
244 
245 #undef DEBUG_TYPE // "jitlink"
246 
247 #endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Implements a dense probed hash-table based set.
Definition: DenseSet.h:249
Definition: BitVector.h:937
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
#define G(x, y, z)
Definition: MD5.cpp:56
place backedge safepoints impl
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:41
#define P(N)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
#define LLVM_DEBUG(X)
Definition: Debug.h:122
constexpr char Args[]
Key for Kernel::Metadata::mArgs.