LLVM  9.0.0svn
JITLink.cpp
Go to the documentation of this file.
1 //===------------- JITLink.cpp - Core Run-time JIT linker APIs ------------===//
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 
11 
14 #include "llvm/Support/Format.h"
17 #include "llvm/Support/Process.h"
19 
20 using namespace llvm;
21 using namespace llvm::object;
22 
23 #define DEBUG_TYPE "jitlink"
24 
25 namespace {
26 
27 enum JITLinkErrorCode { GenericJITLinkError = 1 };
28 
29 // FIXME: This class is only here to support the transition to llvm::Error. It
30 // will be removed once this transition is complete. Clients should prefer to
31 // deal with the Error value directly, rather than converting to error_code.
32 class JITLinkerErrorCategory : public std::error_category {
33 public:
34  const char *name() const noexcept override { return "runtimedyld"; }
35 
36  std::string message(int Condition) const override {
37  switch (static_cast<JITLinkErrorCode>(Condition)) {
38  case GenericJITLinkError:
39  return "Generic JITLink error";
40  }
41  llvm_unreachable("Unrecognized JITLinkErrorCode");
42  }
43 };
44 
45 static ManagedStatic<JITLinkerErrorCategory> JITLinkerErrorCategory;
46 
47 } // namespace
48 
49 namespace llvm {
50 namespace jitlink {
51 
52 char JITLinkError::ID = 0;
53 
54 void JITLinkError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; }
55 
56 std::error_code JITLinkError::convertToErrorCode() const {
57  return std::error_code(GenericJITLinkError, *JITLinkerErrorCategory);
58 }
59 
60 JITLinkMemoryManager::~JITLinkMemoryManager() = default;
61 
62 JITLinkMemoryManager::Allocation::~Allocation() = default;
63 
65  switch (K) {
66  case Edge::Invalid:
67  return "INVALID RELOCATION";
68  case Edge::KeepAlive:
69  return "Keep-Alive";
70  case Edge::LayoutNext:
71  return "Layout-Next";
72  default:
73  llvm_unreachable("Unrecognized relocation kind");
74  }
75 }
76 
78  OS << "<";
79  if (A.getName().empty())
80  OS << "anon@" << format("0x%016" PRIx64, A.getAddress());
81  else
82  OS << A.getName();
83  OS << " [";
84  if (A.isDefined()) {
85  auto &DA = static_cast<const DefinedAtom &>(A);
86  OS << " section=" << DA.getSection().getName();
87  if (DA.isLive())
88  OS << " live";
89  if (DA.shouldDiscard())
90  OS << " should-discard";
91  } else
92  OS << " external";
93  OS << " ]>";
94  return OS;
95 }
96 
97 void printEdge(raw_ostream &OS, const Atom &FixupAtom, const Edge &E,
98  StringRef EdgeKindName) {
99  OS << "edge@" << formatv("{0:x16}", FixupAtom.getAddress() + E.getOffset())
100  << ": " << FixupAtom << " + " << E.getOffset() << " -- " << EdgeKindName
101  << " -> " << E.getTarget() << " + " << E.getAddend();
102 }
103 
104 Section::~Section() {
105  for (auto *DA : DefinedAtoms)
106  DA->~DefinedAtom();
107 }
108 
110  std::function<StringRef(Edge::Kind)> EdgeKindToName) {
111  if (!EdgeKindToName)
112  EdgeKindToName = [](Edge::Kind K) { return StringRef(); };
113 
114  OS << "Defined atoms:\n";
115  for (auto *DA : defined_atoms()) {
116  OS << " " << format("0x%016" PRIx64, DA->getAddress()) << ": " << *DA
117  << "\n";
118  for (auto &E : DA->edges()) {
119  OS << " ";
120  StringRef EdgeName = (E.getKind() < Edge::FirstRelocation
121  ? getGenericEdgeKindName(E.getKind())
122  : EdgeKindToName(E.getKind()));
123 
124  if (!EdgeName.empty())
125  printEdge(OS, *DA, E, EdgeName);
126  else {
127  auto EdgeNumberString = std::to_string(E.getKind());
128  printEdge(OS, *DA, E, EdgeNumberString);
129  }
130  OS << "\n";
131  }
132  }
133 
134  OS << "Absolute atoms:\n";
135  for (auto *A : absolute_atoms())
136  OS << " " << format("0x%016" PRIx64, A->getAddress()) << ": " << *A
137  << "\n";
138 
139  OS << "External atoms:\n";
140  for (auto *A : external_atoms())
141  OS << " " << format("0x%016" PRIx64, A->getAddress()) << ": " << *A
142  << "\n";
143 }
144 
146 InProcessMemoryManager::allocate(const SegmentsRequestMap &Request) {
147 
148  using AllocationMap = DenseMap<unsigned, sys::MemoryBlock>;
149 
150  // Local class for allocation.
151  class IPMMAlloc : public Allocation {
152  public:
153  IPMMAlloc(AllocationMap SegBlocks) : SegBlocks(std::move(SegBlocks)) {}
154  MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override {
155  assert(SegBlocks.count(Seg) && "No allocation for segment");
156  return {static_cast<char *>(SegBlocks[Seg].base()),
157  SegBlocks[Seg].allocatedSize()};
158  }
159  JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
160  assert(SegBlocks.count(Seg) && "No allocation for segment");
161  return reinterpret_cast<JITTargetAddress>(SegBlocks[Seg].base());
162  }
163  void finalizeAsync(FinalizeContinuation OnFinalize) override {
164  OnFinalize(applyProtections());
165  }
166  Error deallocate() override {
167  for (auto &KV : SegBlocks)
168  if (auto EC = sys::Memory::releaseMappedMemory(KV.second))
169  return errorCodeToError(EC);
170  return Error::success();
171  }
172 
173  private:
174  Error applyProtections() {
175  for (auto &KV : SegBlocks) {
176  auto &Prot = KV.first;
177  auto &Block = KV.second;
178  if (auto EC = sys::Memory::protectMappedMemory(Block, Prot))
179  return errorCodeToError(EC);
180  if (Prot & sys::Memory::MF_EXEC)
182  Block.allocatedSize());
183  }
184  return Error::success();
185  }
186 
187  AllocationMap SegBlocks;
188  };
189 
190  AllocationMap Blocks;
191  const sys::Memory::ProtectionFlags ReadWrite =
194 
195  for (auto &KV : Request) {
196  auto &Seg = KV.second;
197 
198  if (Seg.getContentAlignment() > sys::Process::getPageSizeEstimate())
199  return make_error<StringError>("Cannot request higher than page "
200  "alignment",
202 
203  if (sys::Process::getPageSizeEstimate() % Seg.getContentAlignment() != 0)
204  return make_error<StringError>("Page size is not a multiple of "
205  "alignment",
207 
208  uint64_t ZeroFillStart =
209  alignTo(Seg.getContentSize(), Seg.getZeroFillAlignment());
210  uint64_t SegmentSize = ZeroFillStart + Seg.getZeroFillSize();
211 
212  std::error_code EC;
213  auto SegMem =
214  sys::Memory::allocateMappedMemory(SegmentSize, nullptr, ReadWrite, EC);
215 
216  if (EC)
217  return errorCodeToError(EC);
218 
219  // Zero out the zero-fill memory.
220  memset(static_cast<char *>(SegMem.base()) + ZeroFillStart, 0,
221  Seg.getZeroFillSize());
222 
223  // Record the block for this segment.
224  Blocks[KV.first] = std::move(SegMem);
225  }
226  return std::unique_ptr<InProcessMemoryManager::Allocation>(
227  new IPMMAlloc(std::move(Blocks)));
228 }
229 
230 JITLinkContext::~JITLinkContext() {}
231 
232 bool JITLinkContext::shouldAddDefaultTargetPasses(const Triple &TT) const {
233  return true;
234 }
235 
236 AtomGraphPassFunction JITLinkContext::getMarkLivePass(const Triple &TT) const {
237  return AtomGraphPassFunction();
238 }
239 
240 Error JITLinkContext::modifyPassConfig(const Triple &TT,
241  PassConfiguration &Config) {
242  return Error::success();
243 }
244 
246  for (auto *DA : G.defined_atoms())
247  DA->setLive(true);
248  return Error::success();
249 }
250 
251 void jitLink(std::unique_ptr<JITLinkContext> Ctx) {
252  auto Magic = identify_magic(Ctx->getObjectBuffer().getBuffer());
253  switch (Magic) {
255  return jitLink_MachO(std::move(Ctx));
256  default:
257  Ctx->notifyFailed(make_error<JITLinkError>("Unsupported file format"));
258  };
259 }
260 
261 } // end namespace jitlink
262 } // end namespace llvm
Mach-O Object file.
Definition: Magic.h:30
This class represents lattice values for constants.
Definition: AllocatorList.h:23
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:123
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
static void dump(StringRef Title, SpillInfo const &Spills)
Definition: CoroFrame.cpp:298
static std::error_code releaseMappedMemory(MemoryBlock &Block)
This method releases a block of memory that was allocated with the allocateMappedMemory method...
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:684
static MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, std::error_code &EC)
This method allocates a block of memory that is suitable for loading dynamically generated code (e...
static void InvalidateInstructionCache(const void *Addr, size_t Len)
InvalidateInstructionCache - Before the JIT can run a block of code that has been emitted it must inv...
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition: Magic.cpp:34
Tagged union holding either a T or a Error.
Definition: CachePruning.h:22
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:126
static unsigned getPageSizeEstimate()
Get the process&#39;s estimated page size.
Definition: Process.h:56
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:40
Invalid file type.
Definition: InterfaceFile.h:67
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:290
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:87
static ManagedStatic< _object_error_category > error_category
Definition: Error.cpp:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:43
static const char *const Magic
Definition: Archive.cpp:41
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
Provides a library for accessing information about this process and other processes on the operating ...
const std::string to_string(const T &Value)
Definition: ScopedPrinter.h:61
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
OStream & operator<<(OStream &OS, const DataRefImpl &D)
Definition: SymbolicFile.h:46
static const char * name
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
print Print MemDeps of function
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:77
static std::error_code protectMappedMemory(const MemoryBlock &Block, unsigned Flags)
This method sets the protection flags for a block of memory to the state specified by /p Flags...