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:
MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile & Obj)28 MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj)
29 : MachOLinkGraphBuilder(Obj) {}
30
31 private:
32 static Expected<MachOX86RelocationKind>
getRelocationKind(const MachO::relocation_info & RI)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
getRelocationInfo(const object::relocation_iterator RelItr)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>
parsePairRelocation(Block & BlockToFix,Edge::Kind SubtractorKind,const MachO::relocation_info & SubRI,JITTargetAddress FixupAddress,const char * FixupContent,object::relocation_iterator & UnsignedRelItr,object::relocation_iterator & RelEnd)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
addRelocations()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:
MachO_x86_64_GOTAndStubsBuilder(LinkGraph & G)353 MachO_x86_64_GOTAndStubsBuilder(LinkGraph &G)
354 : BasicGOTAndStubsBuilder<MachO_x86_64_GOTAndStubsBuilder>(G) {}
355
isGOTEdge(Edge & E) const356 bool isGOTEdge(Edge &E) const {
357 return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad;
358 }
359
createGOTEntry(Symbol & Target)360 Symbol &createGOTEntry(Symbol &Target) {
361 auto &GOTEntryBlock = G.createContentBlock(
362 getGOTSection(), getGOTEntryBlockContent(), 0, 8, 0);
363 GOTEntryBlock.addEdge(Pointer64, 0, Target, 0);
364 return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
365 }
366
fixGOTEdge(Edge & E,Symbol & GOTEntry)367 void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
368 assert((E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad) &&
369 "Not a GOT edge?");
370 E.setKind(PCRel32);
371 E.setTarget(GOTEntry);
372 // Leave the edge addend as-is.
373 }
374
isExternalBranchEdge(Edge & E)375 bool isExternalBranchEdge(Edge &E) {
376 return E.getKind() == Branch32 && !E.getTarget().isDefined();
377 }
378
createStub(Symbol & Target)379 Symbol &createStub(Symbol &Target) {
380 auto &StubContentBlock =
381 G.createContentBlock(getStubsSection(), getStubBlockContent(), 0, 1, 0);
382 // Re-use GOT entries for stub targets.
383 auto &GOTEntrySymbol = getGOTEntrySymbol(Target);
384 StubContentBlock.addEdge(PCRel32, 2, GOTEntrySymbol, 0);
385 return G.addAnonymousSymbol(StubContentBlock, 0, 6, true, false);
386 }
387
fixExternalBranchEdge(Edge & E,Symbol & Stub)388 void fixExternalBranchEdge(Edge &E, Symbol &Stub) {
389 assert(E.getKind() == Branch32 && "Not a Branch32 edge?");
390 assert(E.getAddend() == 0 && "Branch32 edge has non-zero addend?");
391 E.setTarget(Stub);
392 }
393
394 private:
getGOTSection()395 Section &getGOTSection() {
396 if (!GOTSection)
397 GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ);
398 return *GOTSection;
399 }
400
getStubsSection()401 Section &getStubsSection() {
402 if (!StubsSection) {
403 auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
404 sys::Memory::MF_READ | sys::Memory::MF_EXEC);
405 StubsSection = &G.createSection("$__STUBS", StubsProt);
406 }
407 return *StubsSection;
408 }
409
getGOTEntryBlockContent()410 StringRef getGOTEntryBlockContent() {
411 return StringRef(reinterpret_cast<const char *>(NullGOTEntryContent),
412 sizeof(NullGOTEntryContent));
413 }
414
getStubBlockContent()415 StringRef getStubBlockContent() {
416 return StringRef(reinterpret_cast<const char *>(StubContent),
417 sizeof(StubContent));
418 }
419
420 static const uint8_t NullGOTEntryContent[8];
421 static const uint8_t StubContent[6];
422 Section *GOTSection = nullptr;
423 Section *StubsSection = nullptr;
424 };
425
426 const uint8_t MachO_x86_64_GOTAndStubsBuilder::NullGOTEntryContent[8] = {
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
428 const uint8_t MachO_x86_64_GOTAndStubsBuilder::StubContent[6] = {
429 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
430 } // namespace
431
432 namespace llvm {
433 namespace jitlink {
434
435 class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
436 friend class JITLinker<MachOJITLinker_x86_64>;
437
438 public:
MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,PassConfiguration PassConfig)439 MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
440 PassConfiguration PassConfig)
441 : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
442
443 private:
getEdgeKindName(Edge::Kind R) const444 StringRef getEdgeKindName(Edge::Kind R) const override {
445 return getMachOX86RelocationKindName(R);
446 }
447
448 Expected<std::unique_ptr<LinkGraph>>
buildGraph(MemoryBufferRef ObjBuffer)449 buildGraph(MemoryBufferRef ObjBuffer) override {
450 auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjBuffer);
451 if (!MachOObj)
452 return MachOObj.takeError();
453 return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
454 }
455
targetOutOfRangeError(const Block & B,const Edge & E)456 static Error targetOutOfRangeError(const Block &B, const Edge &E) {
457 std::string ErrMsg;
458 {
459 raw_string_ostream ErrStream(ErrMsg);
460 ErrStream << "Relocation target out of range: ";
461 printEdge(ErrStream, B, E, getMachOX86RelocationKindName(E.getKind()));
462 ErrStream << "\n";
463 }
464 return make_error<JITLinkError>(std::move(ErrMsg));
465 }
466
applyFixup(Block & B,const Edge & E,char * BlockWorkingMem) const467 Error applyFixup(Block &B, const Edge &E, char *BlockWorkingMem) const {
468
469 using namespace support;
470
471 char *FixupPtr = BlockWorkingMem + E.getOffset();
472 JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
473
474 switch (E.getKind()) {
475 case Branch32:
476 case PCRel32:
477 case PCRel32Anon: {
478 int64_t Value =
479 E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
480 if (Value < std::numeric_limits<int32_t>::min() ||
481 Value > std::numeric_limits<int32_t>::max())
482 return targetOutOfRangeError(B, E);
483 *(little32_t *)FixupPtr = Value;
484 break;
485 }
486 case Pointer64:
487 case Pointer64Anon: {
488 uint64_t Value = E.getTarget().getAddress() + E.getAddend();
489 *(ulittle64_t *)FixupPtr = Value;
490 break;
491 }
492 case PCRel32Minus1:
493 case PCRel32Minus2:
494 case PCRel32Minus4: {
495 int Delta = 4 + (1 << (E.getKind() - PCRel32Minus1));
496 int64_t Value =
497 E.getTarget().getAddress() - (FixupAddress + Delta) + E.getAddend();
498 if (Value < std::numeric_limits<int32_t>::min() ||
499 Value > std::numeric_limits<int32_t>::max())
500 return targetOutOfRangeError(B, E);
501 *(little32_t *)FixupPtr = Value;
502 break;
503 }
504 case PCRel32Minus1Anon:
505 case PCRel32Minus2Anon:
506 case PCRel32Minus4Anon: {
507 int Delta = 4 + (1 << (E.getKind() - PCRel32Minus1Anon));
508 int64_t Value =
509 E.getTarget().getAddress() - (FixupAddress + Delta) + E.getAddend();
510 if (Value < std::numeric_limits<int32_t>::min() ||
511 Value > std::numeric_limits<int32_t>::max())
512 return targetOutOfRangeError(B, E);
513 *(little32_t *)FixupPtr = Value;
514 break;
515 }
516 case Delta32:
517 case Delta64:
518 case NegDelta32:
519 case NegDelta64: {
520 int64_t Value;
521 if (E.getKind() == Delta32 || E.getKind() == Delta64)
522 Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
523 else
524 Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
525
526 if (E.getKind() == Delta32 || E.getKind() == NegDelta32) {
527 if (Value < std::numeric_limits<int32_t>::min() ||
528 Value > std::numeric_limits<int32_t>::max())
529 return targetOutOfRangeError(B, E);
530 *(little32_t *)FixupPtr = Value;
531 } else
532 *(little64_t *)FixupPtr = Value;
533 break;
534 }
535 case Pointer32: {
536 uint64_t Value = E.getTarget().getAddress() + E.getAddend();
537 if (Value > std::numeric_limits<uint32_t>::max())
538 return targetOutOfRangeError(B, E);
539 *(ulittle32_t *)FixupPtr = Value;
540 break;
541 }
542 default:
543 llvm_unreachable("Unrecognized edge kind");
544 }
545
546 return Error::success();
547 }
548
549 uint64_t NullValue = 0;
550 };
551
jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx)552 void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
553 PassConfiguration Config;
554 Triple TT("x86_64-apple-macosx");
555
556 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
557 // Add eh-frame passses.
558 Config.PrePrunePasses.push_back(EHFrameSplitter("__eh_frame"));
559 Config.PrePrunePasses.push_back(
560 EHFrameEdgeFixer("__eh_frame", NegDelta32, Delta64, Delta64));
561
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(markAllSymbolsLive);
567
568 // Add an in-place GOT/Stubs pass.
569 Config.PostPrunePasses.push_back([](LinkGraph &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
getMachOX86RelocationKindName(Edge::Kind R)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