xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
1 //===---- MachO_x86_64.cpp -JIT linker implementation for MachO/x86-64 ----===//
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 // MachO/x86-64 jit-link implementation.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h"
14 
15 #include "BasicGOTAndStubsBuilder.h"
16 #include "MachOLinkGraphBuilder.h"
17 
18 #define DEBUG_TYPE "jitlink"
19 
20 using namespace llvm;
21 using namespace llvm::jitlink;
22 using namespace llvm::jitlink::MachO_x86_64_Edges;
23 
24 namespace {
25 
26 class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
27 public:
28   MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj)
29       : MachOLinkGraphBuilder(Obj) {
30     addCustomSectionParser(
31         "__eh_frame", [this](NormalizedSection &EHFrameSection) {
32           if (!EHFrameSection.Data)
33             return make_error<JITLinkError>(
34                 "__eh_frame section is marked zero-fill");
35           return MachOEHFrameBinaryParser(
36                      *this, EHFrameSection.Address,
37                      StringRef(EHFrameSection.Data, EHFrameSection.Size),
38                      *EHFrameSection.GraphSection, 8, 4, NegDelta32, Delta64)
39               .addToGraph();
40         });
41   }
42 
43 private:
44   static Expected<MachOX86RelocationKind>
45   getRelocationKind(const MachO::relocation_info &RI) {
46     switch (RI.r_type) {
47     case MachO::X86_64_RELOC_UNSIGNED:
48       if (!RI.r_pcrel) {
49         if (RI.r_length == 3)
50           return RI.r_extern ? Pointer64 : Pointer64Anon;
51         else if (RI.r_extern && RI.r_length == 2)
52           return Pointer32;
53       }
54       break;
55     case MachO::X86_64_RELOC_SIGNED:
56       if (RI.r_pcrel && RI.r_length == 2)
57         return RI.r_extern ? PCRel32 : PCRel32Anon;
58       break;
59     case MachO::X86_64_RELOC_BRANCH:
60       if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
61         return Branch32;
62       break;
63     case MachO::X86_64_RELOC_GOT_LOAD:
64       if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
65         return PCRel32GOTLoad;
66       break;
67     case MachO::X86_64_RELOC_GOT:
68       if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
69         return PCRel32GOT;
70       break;
71     case MachO::X86_64_RELOC_SUBTRACTOR:
72       // SUBTRACTOR must be non-pc-rel, extern, with length 2 or 3.
73       // Initially represent SUBTRACTOR relocations with 'Delta<W>'. They may
74       // be turned into NegDelta<W> by parsePairRelocation.
75       if (!RI.r_pcrel && RI.r_extern) {
76         if (RI.r_length == 2)
77           return Delta32;
78         else if (RI.r_length == 3)
79           return Delta64;
80       }
81       break;
82     case MachO::X86_64_RELOC_SIGNED_1:
83       if (RI.r_pcrel && RI.r_length == 2)
84         return RI.r_extern ? PCRel32Minus1 : PCRel32Minus1Anon;
85       break;
86     case MachO::X86_64_RELOC_SIGNED_2:
87       if (RI.r_pcrel && RI.r_length == 2)
88         return RI.r_extern ? PCRel32Minus2 : PCRel32Minus2Anon;
89       break;
90     case MachO::X86_64_RELOC_SIGNED_4:
91       if (RI.r_pcrel && RI.r_length == 2)
92         return RI.r_extern ? PCRel32Minus4 : PCRel32Minus4Anon;
93       break;
94     case MachO::X86_64_RELOC_TLV:
95       if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
96         return PCRel32TLV;
97       break;
98     }
99 
100     return make_error<JITLinkError>(
101         "Unsupported x86-64 relocation: address=" +
102         formatv("{0:x8}", RI.r_address) +
103         ", symbolnum=" + formatv("{0:x6}", RI.r_symbolnum) +
104         ", kind=" + formatv("{0:x1}", RI.r_type) +
105         ", pc_rel=" + (RI.r_pcrel ? "true" : "false") +
106         ", extern=" + (RI.r_extern ? "true" : "false") +
107         ", length=" + formatv("{0:d}", RI.r_length));
108   }
109 
110   MachO::relocation_info
111   getRelocationInfo(const object::relocation_iterator RelItr) {
112     MachO::any_relocation_info ARI =
113         getObject().getRelocation(RelItr->getRawDataRefImpl());
114     MachO::relocation_info RI;
115     memcpy(&RI, &ARI, sizeof(MachO::relocation_info));
116     return RI;
117   }
118 
119   using PairRelocInfo = std::tuple<MachOX86RelocationKind, Symbol *, uint64_t>;
120 
121   // Parses paired SUBTRACTOR/UNSIGNED relocations and, on success,
122   // returns the edge kind and addend to be used.
123   Expected<PairRelocInfo>
124   parsePairRelocation(Block &BlockToFix, Edge::Kind SubtractorKind,
125                       const MachO::relocation_info &SubRI,
126                       JITTargetAddress FixupAddress, const char *FixupContent,
127                       object::relocation_iterator &UnsignedRelItr,
128                       object::relocation_iterator &RelEnd) {
129     using namespace support;
130 
131     assert(((SubtractorKind == Delta32 && SubRI.r_length == 2) ||
132             (SubtractorKind == Delta64 && SubRI.r_length == 3)) &&
133            "Subtractor kind should match length");
134     assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern");
135     assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel");
136 
137     if (UnsignedRelItr == RelEnd)
138       return make_error<JITLinkError>("x86_64 SUBTRACTOR without paired "
139                                       "UNSIGNED relocation");
140 
141     auto UnsignedRI = getRelocationInfo(UnsignedRelItr);
142 
143     if (SubRI.r_address != UnsignedRI.r_address)
144       return make_error<JITLinkError>("x86_64 SUBTRACTOR and paired UNSIGNED "
145                                       "point to different addresses");
146 
147     if (SubRI.r_length != UnsignedRI.r_length)
148       return make_error<JITLinkError>("length of x86_64 SUBTRACTOR and paired "
149                                       "UNSIGNED reloc must match");
150 
151     Symbol *FromSymbol;
152     if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum))
153       FromSymbol = FromSymbolOrErr->GraphSymbol;
154     else
155       return FromSymbolOrErr.takeError();
156 
157     // Read the current fixup value.
158     uint64_t FixupValue = 0;
159     if (SubRI.r_length == 3)
160       FixupValue = *(const little64_t *)FixupContent;
161     else
162       FixupValue = *(const little32_t *)FixupContent;
163 
164     // Find 'ToSymbol' using symbol number or address, depending on whether the
165     // paired UNSIGNED relocation is extern.
166     Symbol *ToSymbol = nullptr;
167     if (UnsignedRI.r_extern) {
168       // Find target symbol by symbol index.
169       if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))
170         ToSymbol = ToSymbolOrErr->GraphSymbol;
171       else
172         return ToSymbolOrErr.takeError();
173     } else {
174       if (auto ToSymbolOrErr = findSymbolByAddress(FixupValue))
175         ToSymbol = &*ToSymbolOrErr;
176       else
177         return ToSymbolOrErr.takeError();
178       FixupValue -= ToSymbol->getAddress();
179     }
180 
181     MachOX86RelocationKind DeltaKind;
182     Symbol *TargetSymbol;
183     uint64_t Addend;
184     if (&BlockToFix == &FromSymbol->getAddressable()) {
185       TargetSymbol = ToSymbol;
186       DeltaKind = (SubRI.r_length == 3) ? Delta64 : Delta32;
187       Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());
188       // FIXME: handle extern 'from'.
189     } else if (&BlockToFix == &ToSymbol->getAddressable()) {
190       TargetSymbol = FromSymbol;
191       DeltaKind = (SubRI.r_length == 3) ? NegDelta64 : NegDelta32;
192       Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());
193     } else {
194       // BlockToFix was neither FromSymbol nor ToSymbol.
195       return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
196                                       "either 'A' or 'B' (or a symbol in one "
197                                       "of their alt-entry chains)");
198     }
199 
200     return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
201   }
202 
203   Error addRelocations() override {
204     using namespace support;
205     auto &Obj = getObject();
206 
207     for (auto &S : Obj.sections()) {
208 
209       JITTargetAddress SectionAddress = S.getAddress();
210 
211       if (S.isVirtual()) {
212         if (S.relocation_begin() != S.relocation_end())
213           return make_error<JITLinkError>("Virtual section contains "
214                                           "relocations");
215         continue;
216       }
217 
218       for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
219            RelItr != RelEnd; ++RelItr) {
220 
221         MachO::relocation_info RI = getRelocationInfo(RelItr);
222 
223         // Sanity check the relocation kind.
224         auto Kind = getRelocationKind(RI);
225         if (!Kind)
226           return Kind.takeError();
227 
228         // Find the address of the value to fix up.
229         JITTargetAddress FixupAddress = SectionAddress + (uint32_t)RI.r_address;
230 
231         LLVM_DEBUG({
232           dbgs() << "Processing relocation at "
233                  << format("0x%016" PRIx64, FixupAddress) << "\n";
234         });
235 
236         // Find the block that the fixup points to.
237         Block *BlockToFix = nullptr;
238         {
239           auto SymbolToFixOrErr = findSymbolByAddress(FixupAddress);
240           if (!SymbolToFixOrErr)
241             return SymbolToFixOrErr.takeError();
242           BlockToFix = &SymbolToFixOrErr->getBlock();
243         }
244 
245         if (FixupAddress + static_cast<JITTargetAddress>(1ULL << RI.r_length) >
246             BlockToFix->getAddress() + BlockToFix->getContent().size())
247           return make_error<JITLinkError>(
248               "Relocation extends past end of fixup block");
249 
250         // Get a pointer to the fixup content.
251         const char *FixupContent = BlockToFix->getContent().data() +
252                                    (FixupAddress - BlockToFix->getAddress());
253 
254         // The target symbol and addend will be populated by the switch below.
255         Symbol *TargetSymbol = nullptr;
256         uint64_t Addend = 0;
257 
258         switch (*Kind) {
259         case Branch32:
260         case PCRel32:
261         case PCRel32GOTLoad:
262         case PCRel32GOT:
263           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
264             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
265           else
266             return TargetSymbolOrErr.takeError();
267           Addend = *(const ulittle32_t *)FixupContent;
268           break;
269         case Pointer32:
270           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
271             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
272           else
273             return TargetSymbolOrErr.takeError();
274           Addend = *(const ulittle32_t *)FixupContent;
275           break;
276         case Pointer64:
277           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
278             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
279           else
280             return TargetSymbolOrErr.takeError();
281           Addend = *(const ulittle64_t *)FixupContent;
282           break;
283         case Pointer64Anon: {
284           JITTargetAddress TargetAddress = *(const ulittle64_t *)FixupContent;
285           if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
286             TargetSymbol = &*TargetSymbolOrErr;
287           else
288             return TargetSymbolOrErr.takeError();
289           Addend = TargetAddress - TargetSymbol->getAddress();
290           break;
291         }
292         case PCRel32Minus1:
293         case PCRel32Minus2:
294         case PCRel32Minus4:
295           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
296             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
297           else
298             return TargetSymbolOrErr.takeError();
299           Addend = *(const ulittle32_t *)FixupContent +
300                    (1 << (*Kind - PCRel32Minus1));
301           break;
302         case PCRel32Anon: {
303           JITTargetAddress TargetAddress =
304               FixupAddress + 4 + *(const ulittle32_t *)FixupContent;
305           if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
306             TargetSymbol = &*TargetSymbolOrErr;
307           else
308             return TargetSymbolOrErr.takeError();
309           Addend = TargetAddress - TargetSymbol->getAddress();
310           break;
311         }
312         case PCRel32Minus1Anon:
313         case PCRel32Minus2Anon:
314         case PCRel32Minus4Anon: {
315           JITTargetAddress Delta =
316               static_cast<JITTargetAddress>(1ULL << (*Kind - PCRel32Minus1Anon));
317           JITTargetAddress TargetAddress =
318               FixupAddress + 4 + Delta + *(const ulittle32_t *)FixupContent;
319           if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
320             TargetSymbol = &*TargetSymbolOrErr;
321           else
322             return TargetSymbolOrErr.takeError();
323           Addend = TargetAddress - TargetSymbol->getAddress();
324           break;
325         }
326         case Delta32:
327         case Delta64: {
328           // We use Delta32/Delta64 to represent SUBTRACTOR relocations.
329           // parsePairRelocation handles the paired reloc, and returns the
330           // edge kind to be used (either Delta32/Delta64, or
331           // NegDelta32/NegDelta64, depending on the direction of the
332           // subtraction) along with the addend.
333           auto PairInfo =
334               parsePairRelocation(*BlockToFix, *Kind, RI, FixupAddress,
335                                   FixupContent, ++RelItr, RelEnd);
336           if (!PairInfo)
337             return PairInfo.takeError();
338           std::tie(*Kind, TargetSymbol, Addend) = *PairInfo;
339           assert(TargetSymbol && "No target symbol from parsePairRelocation?");
340           break;
341         }
342         default:
343           llvm_unreachable("Special relocation kind should not appear in "
344                            "mach-o file");
345         }
346 
347         LLVM_DEBUG({
348           Edge GE(*Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
349                   Addend);
350           printEdge(dbgs(), *BlockToFix, GE,
351                     getMachOX86RelocationKindName(*Kind));
352           dbgs() << "\n";
353         });
354         BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(),
355                             *TargetSymbol, Addend);
356       }
357     }
358     return Error::success();
359   }
360 };
361 
362 class MachO_x86_64_GOTAndStubsBuilder
363     : public BasicGOTAndStubsBuilder<MachO_x86_64_GOTAndStubsBuilder> {
364 public:
365   MachO_x86_64_GOTAndStubsBuilder(LinkGraph &G)
366       : BasicGOTAndStubsBuilder<MachO_x86_64_GOTAndStubsBuilder>(G) {}
367 
368   bool isGOTEdge(Edge &E) const {
369     return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad;
370   }
371 
372   Symbol &createGOTEntry(Symbol &Target) {
373     auto &GOTEntryBlock = G.createContentBlock(
374         getGOTSection(), getGOTEntryBlockContent(), 0, 8, 0);
375     GOTEntryBlock.addEdge(Pointer64, 0, Target, 0);
376     return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
377   }
378 
379   void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
380     assert((E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad) &&
381            "Not a GOT edge?");
382     E.setKind(PCRel32);
383     E.setTarget(GOTEntry);
384     // Leave the edge addend as-is.
385   }
386 
387   bool isExternalBranchEdge(Edge &E) {
388     return E.getKind() == Branch32 && !E.getTarget().isDefined();
389   }
390 
391   Symbol &createStub(Symbol &Target) {
392     auto &StubContentBlock =
393         G.createContentBlock(getStubsSection(), getStubBlockContent(), 0, 1, 0);
394     // Re-use GOT entries for stub targets.
395     auto &GOTEntrySymbol = getGOTEntrySymbol(Target);
396     StubContentBlock.addEdge(PCRel32, 2, GOTEntrySymbol, 0);
397     return G.addAnonymousSymbol(StubContentBlock, 0, 6, true, false);
398   }
399 
400   void fixExternalBranchEdge(Edge &E, Symbol &Stub) {
401     assert(E.getKind() == Branch32 && "Not a Branch32 edge?");
402     assert(E.getAddend() == 0 && "Branch32 edge has non-zero addend?");
403     E.setTarget(Stub);
404   }
405 
406 private:
407   Section &getGOTSection() {
408     if (!GOTSection)
409       GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ);
410     return *GOTSection;
411   }
412 
413   Section &getStubsSection() {
414     if (!StubsSection) {
415       auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
416           sys::Memory::MF_READ | sys::Memory::MF_EXEC);
417       StubsSection = &G.createSection("$__STUBS", StubsProt);
418     }
419     return *StubsSection;
420   }
421 
422   StringRef getGOTEntryBlockContent() {
423     return StringRef(reinterpret_cast<const char *>(NullGOTEntryContent),
424                      sizeof(NullGOTEntryContent));
425   }
426 
427   StringRef getStubBlockContent() {
428     return StringRef(reinterpret_cast<const char *>(StubContent),
429                      sizeof(StubContent));
430   }
431 
432   static const uint8_t NullGOTEntryContent[8];
433   static const uint8_t StubContent[6];
434   Section *GOTSection = nullptr;
435   Section *StubsSection = nullptr;
436 };
437 
438 const uint8_t MachO_x86_64_GOTAndStubsBuilder::NullGOTEntryContent[8] = {
439     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
440 const uint8_t MachO_x86_64_GOTAndStubsBuilder::StubContent[6] = {
441     0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
442 } // namespace
443 
444 namespace llvm {
445 namespace jitlink {
446 
447 class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
448   friend class JITLinker<MachOJITLinker_x86_64>;
449 
450 public:
451   MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
452                         PassConfiguration PassConfig)
453       : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
454 
455 private:
456   StringRef getEdgeKindName(Edge::Kind R) const override {
457     return getMachOX86RelocationKindName(R);
458   }
459 
460   Expected<std::unique_ptr<LinkGraph>>
461   buildGraph(MemoryBufferRef ObjBuffer) override {
462     auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjBuffer);
463     if (!MachOObj)
464       return MachOObj.takeError();
465     return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
466   }
467 
468   static Error targetOutOfRangeError(const Block &B, const Edge &E) {
469     std::string ErrMsg;
470     {
471       raw_string_ostream ErrStream(ErrMsg);
472       ErrStream << "Relocation target out of range: ";
473       printEdge(ErrStream, B, E, getMachOX86RelocationKindName(E.getKind()));
474       ErrStream << "\n";
475     }
476     return make_error<JITLinkError>(std::move(ErrMsg));
477   }
478 
479   Error applyFixup(Block &B, const Edge &E, char *BlockWorkingMem) const {
480 
481     using namespace support;
482 
483     char *FixupPtr = BlockWorkingMem + E.getOffset();
484     JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
485 
486     switch (E.getKind()) {
487     case Branch32:
488     case PCRel32:
489     case PCRel32Anon: {
490       int64_t Value =
491           E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
492       if (Value < std::numeric_limits<int32_t>::min() ||
493           Value > std::numeric_limits<int32_t>::max())
494         return targetOutOfRangeError(B, E);
495       *(little32_t *)FixupPtr = Value;
496       break;
497     }
498     case Pointer64:
499     case Pointer64Anon: {
500       uint64_t Value = E.getTarget().getAddress() + E.getAddend();
501       *(ulittle64_t *)FixupPtr = Value;
502       break;
503     }
504     case PCRel32Minus1:
505     case PCRel32Minus2:
506     case PCRel32Minus4: {
507       int Delta = 4 + (1 << (E.getKind() - PCRel32Minus1));
508       int64_t Value =
509           E.getTarget().getAddress() - (FixupAddress + Delta) + E.getAddend();
510       if (Value < std::numeric_limits<int32_t>::min() ||
511           Value > std::numeric_limits<int32_t>::max())
512         return targetOutOfRangeError(B, E);
513       *(little32_t *)FixupPtr = Value;
514       break;
515     }
516     case PCRel32Minus1Anon:
517     case PCRel32Minus2Anon:
518     case PCRel32Minus4Anon: {
519       int Delta = 4 + (1 << (E.getKind() - PCRel32Minus1Anon));
520       int64_t Value =
521           E.getTarget().getAddress() - (FixupAddress + Delta) + E.getAddend();
522       if (Value < std::numeric_limits<int32_t>::min() ||
523           Value > std::numeric_limits<int32_t>::max())
524         return targetOutOfRangeError(B, E);
525       *(little32_t *)FixupPtr = Value;
526       break;
527     }
528     case Delta32:
529     case Delta64:
530     case NegDelta32:
531     case NegDelta64: {
532       int64_t Value;
533       if (E.getKind() == Delta32 || E.getKind() == Delta64)
534         Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
535       else
536         Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
537 
538       if (E.getKind() == Delta32 || E.getKind() == NegDelta32) {
539         if (Value < std::numeric_limits<int32_t>::min() ||
540             Value > std::numeric_limits<int32_t>::max())
541           return targetOutOfRangeError(B, E);
542         *(little32_t *)FixupPtr = Value;
543       } else
544         *(little64_t *)FixupPtr = Value;
545       break;
546     }
547     case Pointer32: {
548       uint64_t Value = E.getTarget().getAddress() + E.getAddend();
549       if (Value > std::numeric_limits<uint32_t>::max())
550         return targetOutOfRangeError(B, E);
551       *(ulittle32_t *)FixupPtr = Value;
552       break;
553     }
554     default:
555       llvm_unreachable("Unrecognized edge kind");
556     }
557 
558     return Error::success();
559   }
560 
561   uint64_t NullValue = 0;
562 };
563 
564 void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
565   PassConfiguration Config;
566   Triple TT("x86_64-apple-macosx");
567 
568   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
569     // Add a mark-live pass.
570     if (auto MarkLive = Ctx->getMarkLivePass(TT))
571       Config.PrePrunePasses.push_back(std::move(MarkLive));
572     else
573       Config.PrePrunePasses.push_back(markAllSymbolsLive);
574 
575     // Add an in-place GOT/Stubs pass.
576     Config.PostPrunePasses.push_back([](LinkGraph &G) -> Error {
577       MachO_x86_64_GOTAndStubsBuilder(G).run();
578       return Error::success();
579     });
580   }
581 
582   if (auto Err = Ctx->modifyPassConfig(TT, Config))
583     return Ctx->notifyFailed(std::move(Err));
584 
585   // Construct a JITLinker and run the link function.
586   MachOJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
587 }
588 
589 StringRef getMachOX86RelocationKindName(Edge::Kind R) {
590   switch (R) {
591   case Branch32:
592     return "Branch32";
593   case Pointer32:
594     return "Pointer32";
595   case Pointer64:
596     return "Pointer64";
597   case Pointer64Anon:
598     return "Pointer64Anon";
599   case PCRel32:
600     return "PCRel32";
601   case PCRel32Minus1:
602     return "PCRel32Minus1";
603   case PCRel32Minus2:
604     return "PCRel32Minus2";
605   case PCRel32Minus4:
606     return "PCRel32Minus4";
607   case PCRel32Anon:
608     return "PCRel32Anon";
609   case PCRel32Minus1Anon:
610     return "PCRel32Minus1Anon";
611   case PCRel32Minus2Anon:
612     return "PCRel32Minus2Anon";
613   case PCRel32Minus4Anon:
614     return "PCRel32Minus4Anon";
615   case PCRel32GOTLoad:
616     return "PCRel32GOTLoad";
617   case PCRel32GOT:
618     return "PCRel32GOT";
619   case PCRel32TLV:
620     return "PCRel32TLV";
621   case Delta32:
622     return "Delta32";
623   case Delta64:
624     return "Delta64";
625   case NegDelta32:
626     return "NegDelta32";
627   case NegDelta64:
628     return "NegDelta64";
629   default:
630     return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
631   }
632 }
633 
634 } // end namespace jitlink
635 } // end namespace llvm
636