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