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