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