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