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