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: 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> 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. 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 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 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: 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: 485 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 486 return x86_64::applyFixup(G, B, E, nullptr); 487 } 488 }; 489 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 519 static bool encodingSpecifiesDWARF(uint32_t Encoding) { 520 constexpr uint32_t DWARFMode = 0x04000000; 521 return (Encoding & EncodingModeMask) == DWARFMode; 522 } 523 524 static bool encodingCannotBeMerged(uint32_t Encoding) { 525 constexpr uint32_t StackIndirectMode = 0x03000000; 526 return (Encoding & EncodingModeMask) == StackIndirectMode; 527 } 528 }; 529 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 586 LinkGraphPassFunction createEHFrameSplitterPass_MachO_x86_64() { 587 return DWARFRecordSectionSplitter(orc::MachOEHFrameSectionName); 588 } 589 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