xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
15 #include "llvm/ExecutionEngine/JITLink/x86_64.h"
16 
17 #include "DefineExternalSectionStartAndEndSymbols.h"
18 #include "MachOLinkGraphBuilder.h"
19 
20 #define DEBUG_TYPE "jitlink"
21 
22 using namespace llvm;
23 using namespace llvm::jitlink;
24 
25 namespace {
26 
27 class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
28 public:
MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile & Obj,SubtargetFeatures Features)29   MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj,
30                                SubtargetFeatures Features)
31       : MachOLinkGraphBuilder(Obj, Triple("x86_64-apple-darwin"),
32                               std::move(Features), x86_64::getEdgeKindName) {}
33 
34 private:
35   enum MachONormalizedRelocationType : unsigned {
36     MachOBranch32,
37     MachOPointer32,
38     MachOPointer64,
39     MachOPointer64Anon,
40     MachOPCRel32,
41     MachOPCRel32Minus1,
42     MachOPCRel32Minus2,
43     MachOPCRel32Minus4,
44     MachOPCRel32Anon,
45     MachOPCRel32Minus1Anon,
46     MachOPCRel32Minus2Anon,
47     MachOPCRel32Minus4Anon,
48     MachOPCRel32GOTLoad,
49     MachOPCRel32GOT,
50     MachOPCRel32TLV,
51     MachOSubtractor32,
52     MachOSubtractor64,
53   };
54 
55   static Expected<MachONormalizedRelocationType>
getRelocKind(const MachO::relocation_info & RI)56   getRelocKind(const MachO::relocation_info &RI) {
57     switch (RI.r_type) {
58     case MachO::X86_64_RELOC_UNSIGNED:
59       if (!RI.r_pcrel) {
60         if (RI.r_length == 3)
61           return RI.r_extern ? MachOPointer64 : MachOPointer64Anon;
62         else if (RI.r_extern && RI.r_length == 2)
63           return MachOPointer32;
64       }
65       break;
66     case MachO::X86_64_RELOC_SIGNED:
67       if (RI.r_pcrel && RI.r_length == 2)
68         return RI.r_extern ? MachOPCRel32 : MachOPCRel32Anon;
69       break;
70     case MachO::X86_64_RELOC_BRANCH:
71       if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
72         return MachOBranch32;
73       break;
74     case MachO::X86_64_RELOC_GOT_LOAD:
75       if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
76         return MachOPCRel32GOTLoad;
77       break;
78     case MachO::X86_64_RELOC_GOT:
79       if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
80         return MachOPCRel32GOT;
81       break;
82     case MachO::X86_64_RELOC_SUBTRACTOR:
83       if (!RI.r_pcrel && RI.r_extern) {
84         if (RI.r_length == 2)
85           return MachOSubtractor32;
86         else if (RI.r_length == 3)
87           return MachOSubtractor64;
88       }
89       break;
90     case MachO::X86_64_RELOC_SIGNED_1:
91       if (RI.r_pcrel && RI.r_length == 2)
92         return RI.r_extern ? MachOPCRel32Minus1 : MachOPCRel32Minus1Anon;
93       break;
94     case MachO::X86_64_RELOC_SIGNED_2:
95       if (RI.r_pcrel && RI.r_length == 2)
96         return RI.r_extern ? MachOPCRel32Minus2 : MachOPCRel32Minus2Anon;
97       break;
98     case MachO::X86_64_RELOC_SIGNED_4:
99       if (RI.r_pcrel && RI.r_length == 2)
100         return RI.r_extern ? MachOPCRel32Minus4 : MachOPCRel32Minus4Anon;
101       break;
102     case MachO::X86_64_RELOC_TLV:
103       if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
104         return MachOPCRel32TLV;
105       break;
106     }
107 
108     return make_error<JITLinkError>(
109         "Unsupported x86-64 relocation: address=" +
110         formatv("{0:x8}", RI.r_address) +
111         ", symbolnum=" + formatv("{0:x6}", RI.r_symbolnum) +
112         ", kind=" + formatv("{0:x1}", RI.r_type) +
113         ", pc_rel=" + (RI.r_pcrel ? "true" : "false") +
114         ", extern=" + (RI.r_extern ? "true" : "false") +
115         ", length=" + formatv("{0:d}", RI.r_length));
116   }
117 
118   using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;
119 
120   // Parses paired SUBTRACTOR/UNSIGNED relocations and, on success,
121   // returns the edge kind and addend to be used.
parsePairRelocation(Block & BlockToFix,MachONormalizedRelocationType SubtractorKind,const MachO::relocation_info & SubRI,orc::ExecutorAddr FixupAddress,const char * FixupContent,object::relocation_iterator & UnsignedRelItr,object::relocation_iterator & RelEnd)122   Expected<PairRelocInfo> parsePairRelocation(
123       Block &BlockToFix, MachONormalizedRelocationType SubtractorKind,
124       const MachO::relocation_info &SubRI, orc::ExecutorAddr FixupAddress,
125       const char *FixupContent, object::relocation_iterator &UnsignedRelItr,
126       object::relocation_iterator &RelEnd) {
127     using namespace support;
128 
129     assert(((SubtractorKind == MachOSubtractor32 && SubRI.r_length == 2) ||
130             (SubtractorKind == MachOSubtractor64 && SubRI.r_length == 3)) &&
131            "Subtractor kind should match length");
132     assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern");
133     assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel");
134 
135     if (UnsignedRelItr == RelEnd)
136       return make_error<JITLinkError>("x86_64 SUBTRACTOR without paired "
137                                       "UNSIGNED relocation");
138 
139     auto UnsignedRI = getRelocationInfo(UnsignedRelItr);
140 
141     if (SubRI.r_address != UnsignedRI.r_address)
142       return make_error<JITLinkError>("x86_64 SUBTRACTOR and paired UNSIGNED "
143                                       "point to different addresses");
144 
145     if (SubRI.r_length != UnsignedRI.r_length)
146       return make_error<JITLinkError>("length of x86_64 SUBTRACTOR and paired "
147                                       "UNSIGNED reloc must match");
148 
149     Symbol *FromSymbol;
150     if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum))
151       FromSymbol = FromSymbolOrErr->GraphSymbol;
152     else
153       return FromSymbolOrErr.takeError();
154 
155     // Read the current fixup value.
156     uint64_t FixupValue = 0;
157     if (SubRI.r_length == 3)
158       FixupValue = *(const little64_t *)FixupContent;
159     else
160       FixupValue = *(const little32_t *)FixupContent;
161 
162     // Find 'ToSymbol' using symbol number or address, depending on whether the
163     // paired UNSIGNED relocation is extern.
164     Symbol *ToSymbol = nullptr;
165     if (UnsignedRI.r_extern) {
166       // Find target symbol by symbol index.
167       if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))
168         ToSymbol = ToSymbolOrErr->GraphSymbol;
169       else
170         return ToSymbolOrErr.takeError();
171     } else {
172       auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);
173       if (!ToSymbolSec)
174         return ToSymbolSec.takeError();
175       ToSymbol = getSymbolByAddress(*ToSymbolSec, ToSymbolSec->Address);
176       assert(ToSymbol && "No symbol for section");
177       FixupValue -= ToSymbol->getAddress().getValue();
178     }
179 
180     Edge::Kind DeltaKind;
181     Symbol *TargetSymbol;
182     uint64_t Addend;
183 
184     bool FixingFromSymbol = true;
185     if (&BlockToFix == &FromSymbol->getAddressable()) {
186       if (LLVM_UNLIKELY(&BlockToFix == &ToSymbol->getAddressable())) {
187         // From and To are symbols in the same block. Decide direction by offset
188         // instead.
189         if (ToSymbol->getAddress() > FixupAddress)
190           FixingFromSymbol = true;
191         else if (FromSymbol->getAddress() > FixupAddress)
192           FixingFromSymbol = false;
193         else
194           FixingFromSymbol = FromSymbol->getAddress() >= ToSymbol->getAddress();
195       } else
196         FixingFromSymbol = true;
197     } else {
198       if (&BlockToFix == &ToSymbol->getAddressable())
199         FixingFromSymbol = false;
200       else {
201         // BlockToFix was neither FromSymbol nor ToSymbol.
202         return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
203                                         "either 'A' or 'B' (or a symbol in one "
204                                         "of their alt-entry groups)");
205       }
206     }
207 
208     if (FixingFromSymbol) {
209       TargetSymbol = ToSymbol;
210       DeltaKind = (SubRI.r_length == 3) ? x86_64::Delta64 : x86_64::Delta32;
211       Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());
212       // FIXME: handle extern 'from'.
213     } else {
214       TargetSymbol = FromSymbol;
215       DeltaKind =
216           (SubRI.r_length == 3) ? x86_64::NegDelta64 : x86_64::NegDelta32;
217       Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());
218     }
219 
220     return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
221   }
222 
addRelocations()223   Error addRelocations() override {
224     using namespace support;
225     auto &Obj = getObject();
226 
227     LLVM_DEBUG(dbgs() << "Processing relocations:\n");
228 
229     for (const auto &S : Obj.sections()) {
230 
231       orc::ExecutorAddr SectionAddress(S.getAddress());
232 
233       // Skip relocations virtual sections.
234       if (S.isVirtual()) {
235         if (S.relocation_begin() != S.relocation_end())
236           return make_error<JITLinkError>("Virtual section contains "
237                                           "relocations");
238         continue;
239       }
240 
241       auto NSec =
242           findSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
243       if (!NSec)
244         return NSec.takeError();
245 
246       // Skip relocations for MachO sections without corresponding graph
247       // sections.
248       {
249         if (!NSec->GraphSection) {
250           LLVM_DEBUG({
251             dbgs() << "  Skipping relocations for MachO section "
252                    << NSec->SegName << "/" << NSec->SectName
253                    << " which has no associated graph section\n";
254           });
255           continue;
256         }
257       }
258 
259       // Add relocations for section.
260       for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
261            RelItr != RelEnd; ++RelItr) {
262 
263         MachO::relocation_info RI = getRelocationInfo(RelItr);
264 
265         // Find the address of the value to fix up.
266         auto FixupAddress = SectionAddress + (uint32_t)RI.r_address;
267 
268         LLVM_DEBUG({
269           dbgs() << "  " << NSec->SectName << " + "
270                  << formatv("{0:x8}", RI.r_address) << ":\n";
271         });
272 
273         // Find the block that the fixup points to.
274         Block *BlockToFix = nullptr;
275         {
276           auto SymbolToFixOrErr = findSymbolByAddress(*NSec, FixupAddress);
277           if (!SymbolToFixOrErr)
278             return SymbolToFixOrErr.takeError();
279           BlockToFix = &SymbolToFixOrErr->getBlock();
280         }
281 
282         if (FixupAddress + orc::ExecutorAddrDiff(1ULL << RI.r_length) >
283             BlockToFix->getAddress() + BlockToFix->getContent().size())
284           return make_error<JITLinkError>(
285               "Relocation extends past end of fixup block");
286 
287         // Get a pointer to the fixup content.
288         const char *FixupContent = BlockToFix->getContent().data() +
289                                    (FixupAddress - BlockToFix->getAddress());
290 
291         size_t FixupOffset = FixupAddress - BlockToFix->getAddress();
292 
293         // The target symbol and addend will be populated by the switch below.
294         Symbol *TargetSymbol = nullptr;
295         uint64_t Addend = 0;
296 
297         // Validate the relocation kind.
298         auto MachORelocKind = getRelocKind(RI);
299         if (!MachORelocKind)
300           return MachORelocKind.takeError();
301 
302         Edge::Kind Kind = Edge::Invalid;
303 
304         switch (*MachORelocKind) {
305         case MachOBranch32:
306           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
307             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
308           else
309             return TargetSymbolOrErr.takeError();
310           Addend = *(const little32_t *)FixupContent;
311           Kind = x86_64::BranchPCRel32;
312           break;
313         case MachOPCRel32:
314           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
315             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
316           else
317             return TargetSymbolOrErr.takeError();
318           Addend = *(const little32_t *)FixupContent - 4;
319           Kind = x86_64::Delta32;
320           break;
321         case MachOPCRel32GOTLoad:
322           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
323             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
324           else
325             return TargetSymbolOrErr.takeError();
326           Addend = *(const little32_t *)FixupContent;
327           Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable;
328           if (FixupOffset < 3)
329             return make_error<JITLinkError>("GOTLD at invalid offset " +
330                                             formatv("{0}", FixupOffset));
331           break;
332         case MachOPCRel32GOT:
333           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
334             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
335           else
336             return TargetSymbolOrErr.takeError();
337           Addend = *(const little32_t *)FixupContent - 4;
338           Kind = x86_64::RequestGOTAndTransformToDelta32;
339           break;
340         case MachOPCRel32TLV:
341           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
342             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
343           else
344             return TargetSymbolOrErr.takeError();
345           Addend = *(const little32_t *)FixupContent;
346           Kind = x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable;
347           if (FixupOffset < 3)
348             return make_error<JITLinkError>("TLV at invalid offset " +
349                                             formatv("{0}", FixupOffset));
350           break;
351         case MachOPointer32:
352           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
353             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
354           else
355             return TargetSymbolOrErr.takeError();
356           Addend = *(const ulittle32_t *)FixupContent;
357           Kind = x86_64::Pointer32;
358           break;
359         case MachOPointer64:
360           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
361             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
362           else
363             return TargetSymbolOrErr.takeError();
364           Addend = *(const ulittle64_t *)FixupContent;
365           Kind = x86_64::Pointer64;
366           break;
367         case MachOPointer64Anon: {
368           orc::ExecutorAddr TargetAddress(*(const ulittle64_t *)FixupContent);
369           auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);
370           if (!TargetNSec)
371             return TargetNSec.takeError();
372           if (auto TargetSymbolOrErr =
373                   findSymbolByAddress(*TargetNSec, TargetAddress))
374             TargetSymbol = &*TargetSymbolOrErr;
375           else
376             return TargetSymbolOrErr.takeError();
377           Addend = TargetAddress - TargetSymbol->getAddress();
378           Kind = x86_64::Pointer64;
379           break;
380         }
381         case MachOPCRel32Minus1:
382         case MachOPCRel32Minus2:
383         case MachOPCRel32Minus4:
384           if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
385             TargetSymbol = TargetSymbolOrErr->GraphSymbol;
386           else
387             return TargetSymbolOrErr.takeError();
388           Addend = *(const little32_t *)FixupContent - 4;
389           Kind = x86_64::Delta32;
390           break;
391         case MachOPCRel32Anon: {
392           orc::ExecutorAddr TargetAddress(FixupAddress + 4 +
393                                           *(const little32_t *)FixupContent);
394           auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);
395           if (!TargetNSec)
396             return TargetNSec.takeError();
397           if (auto TargetSymbolOrErr =
398                   findSymbolByAddress(*TargetNSec, TargetAddress))
399             TargetSymbol = &*TargetSymbolOrErr;
400           else
401             return TargetSymbolOrErr.takeError();
402           Addend = TargetAddress - TargetSymbol->getAddress() - 4;
403           Kind = x86_64::Delta32;
404           break;
405         }
406         case MachOPCRel32Minus1Anon:
407         case MachOPCRel32Minus2Anon:
408         case MachOPCRel32Minus4Anon: {
409           orc::ExecutorAddrDiff Delta =
410               4 + orc::ExecutorAddrDiff(
411                       1ULL << (*MachORelocKind - MachOPCRel32Minus1Anon));
412           orc::ExecutorAddr TargetAddress =
413               FixupAddress + Delta + *(const little32_t *)FixupContent;
414           auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);
415           if (!TargetNSec)
416             return TargetNSec.takeError();
417           if (auto TargetSymbolOrErr =
418                   findSymbolByAddress(*TargetNSec, TargetAddress))
419             TargetSymbol = &*TargetSymbolOrErr;
420           else
421             return TargetSymbolOrErr.takeError();
422           Addend = TargetAddress - TargetSymbol->getAddress() - Delta;
423           Kind = x86_64::Delta32;
424           break;
425         }
426         case MachOSubtractor32:
427         case MachOSubtractor64: {
428           // We use Delta32/Delta64 to represent SUBTRACTOR relocations.
429           // parsePairRelocation handles the paired reloc, and returns the
430           // edge kind to be used (either Delta32/Delta64, or
431           // NegDelta32/NegDelta64, depending on the direction of the
432           // subtraction) along with the addend.
433           auto PairInfo =
434               parsePairRelocation(*BlockToFix, *MachORelocKind, RI,
435                                   FixupAddress, FixupContent, ++RelItr, RelEnd);
436           if (!PairInfo)
437             return PairInfo.takeError();
438           std::tie(Kind, TargetSymbol, Addend) = *PairInfo;
439           assert(TargetSymbol && "No target symbol from parsePairRelocation?");
440           break;
441         }
442         }
443 
444         LLVM_DEBUG({
445           dbgs() << "    ";
446           Edge GE(Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
447                   Addend);
448           printEdge(dbgs(), *BlockToFix, GE, x86_64::getEdgeKindName(Kind));
449           dbgs() << "\n";
450         });
451         BlockToFix->addEdge(Kind, FixupAddress - BlockToFix->getAddress(),
452                             *TargetSymbol, Addend);
453       }
454     }
455     return Error::success();
456   }
457 };
458 
buildGOTAndStubs_MachO_x86_64(LinkGraph & G)459 Error buildGOTAndStubs_MachO_x86_64(LinkGraph &G) {
460   x86_64::GOTTableManager GOT;
461   x86_64::PLTTableManager PLT(GOT);
462   visitExistingEdges(G, GOT, PLT);
463   return Error::success();
464 }
465 
466 } // namespace
467 
468 namespace llvm {
469 namespace jitlink {
470 
471 class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
472   friend class JITLinker<MachOJITLinker_x86_64>;
473 
474 public:
MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,std::unique_ptr<LinkGraph> G,PassConfiguration PassConfig)475   MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
476                         std::unique_ptr<LinkGraph> G,
477                         PassConfiguration PassConfig)
478       : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
479 
480 private:
applyFixup(LinkGraph & G,Block & B,const Edge & E) const481   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
482     return x86_64::applyFixup(G, B, E, nullptr);
483   }
484 };
485 
486 Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer)487 createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer) {
488   auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
489   if (!MachOObj)
490     return MachOObj.takeError();
491 
492   auto Features = (*MachOObj)->getFeatures();
493   if (!Features)
494     return Features.takeError();
495 
496   return MachOLinkGraphBuilder_x86_64(**MachOObj, std::move(*Features))
497       .buildGraph();
498 }
499 
link_MachO_x86_64(std::unique_ptr<LinkGraph> G,std::unique_ptr<JITLinkContext> Ctx)500 void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
501                        std::unique_ptr<JITLinkContext> Ctx) {
502 
503   PassConfiguration Config;
504 
505   if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
506     // Add eh-frame passes.
507     Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_x86_64());
508     Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_x86_64());
509 
510     // Add compact unwind splitter pass.
511     Config.PrePrunePasses.push_back(
512         CompactUnwindSplitter("__LD,__compact_unwind"));
513 
514     // Add a mark-live pass.
515     if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
516       Config.PrePrunePasses.push_back(std::move(MarkLive));
517     else
518       Config.PrePrunePasses.push_back(markAllSymbolsLive);
519 
520     // Resolve any external section start / end symbols.
521     Config.PostAllocationPasses.push_back(
522         createDefineExternalSectionStartAndEndSymbolsPass(
523             identifyMachOSectionStartAndEndSymbols));
524 
525     // Add an in-place GOT/Stubs pass.
526     Config.PostPrunePasses.push_back(buildGOTAndStubs_MachO_x86_64);
527 
528     // Add GOT/Stubs optimizer pass.
529     Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses);
530   }
531 
532   if (auto Err = Ctx->modifyPassConfig(*G, Config))
533     return Ctx->notifyFailed(std::move(Err));
534 
535   // Construct a JITLinker and run the link function.
536   MachOJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
537 }
538 
createEHFrameSplitterPass_MachO_x86_64()539 LinkGraphPassFunction createEHFrameSplitterPass_MachO_x86_64() {
540   return DWARFRecordSectionSplitter("__TEXT,__eh_frame");
541 }
542 
createEHFrameEdgeFixerPass_MachO_x86_64()543 LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_x86_64() {
544   return EHFrameEdgeFixer("__TEXT,__eh_frame", x86_64::PointerSize,
545                           x86_64::Pointer32, x86_64::Pointer64, x86_64::Delta32,
546                           x86_64::Delta64, x86_64::NegDelta32);
547 }
548 
549 } // end namespace jitlink
550 } // end namespace llvm
551