1 //===---- MachO_arm64.cpp - JIT linker implementation for MachO/arm64 -----===// 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/arm64 jit-link implementation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ExecutionEngine/JITLink/MachO_arm64.h" 14 #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 15 #include "llvm/ExecutionEngine/JITLink/aarch64.h" 16 17 #include "MachOLinkGraphBuilder.h" 18 19 #define DEBUG_TYPE "jitlink" 20 21 using namespace llvm; 22 using namespace llvm::jitlink; 23 24 namespace { 25 26 class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder { 27 public: 28 MachOLinkGraphBuilder_arm64(const object::MachOObjectFile &Obj) 29 : MachOLinkGraphBuilder(Obj, Triple("arm64-apple-darwin"), 30 aarch64::getEdgeKindName), 31 NumSymbols(Obj.getSymtabLoadCommand().nsyms) {} 32 33 private: 34 enum MachOARM64RelocationKind : Edge::Kind { 35 MachOBranch26 = Edge::FirstRelocation, 36 MachOPointer32, 37 MachOPointer64, 38 MachOPointer64Anon, 39 MachOPage21, 40 MachOPageOffset12, 41 MachOGOTPage21, 42 MachOGOTPageOffset12, 43 MachOTLVPage21, 44 MachOTLVPageOffset12, 45 MachOPointerToGOT, 46 MachOPairedAddend, 47 MachOLDRLiteral19, 48 MachODelta32, 49 MachODelta64, 50 MachONegDelta32, 51 MachONegDelta64, 52 }; 53 54 static Expected<MachOARM64RelocationKind> 55 getRelocationKind(const MachO::relocation_info &RI) { 56 switch (RI.r_type) { 57 case MachO::ARM64_RELOC_UNSIGNED: 58 if (!RI.r_pcrel) { 59 if (RI.r_length == 3) 60 return RI.r_extern ? MachOPointer64 : MachOPointer64Anon; 61 else if (RI.r_length == 2) 62 return MachOPointer32; 63 } 64 break; 65 case MachO::ARM64_RELOC_SUBTRACTOR: 66 // SUBTRACTOR must be non-pc-rel, extern, with length 2 or 3. 67 // Initially represent SUBTRACTOR relocations with 'Delta<W>'. 68 // They may be turned into NegDelta<W> by parsePairRelocation. 69 if (!RI.r_pcrel && RI.r_extern) { 70 if (RI.r_length == 2) 71 return MachODelta32; 72 else if (RI.r_length == 3) 73 return MachODelta64; 74 } 75 break; 76 case MachO::ARM64_RELOC_BRANCH26: 77 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2) 78 return MachOBranch26; 79 break; 80 case MachO::ARM64_RELOC_PAGE21: 81 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2) 82 return MachOPage21; 83 break; 84 case MachO::ARM64_RELOC_PAGEOFF12: 85 if (!RI.r_pcrel && RI.r_extern && RI.r_length == 2) 86 return MachOPageOffset12; 87 break; 88 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 89 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2) 90 return MachOGOTPage21; 91 break; 92 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 93 if (!RI.r_pcrel && RI.r_extern && RI.r_length == 2) 94 return MachOGOTPageOffset12; 95 break; 96 case MachO::ARM64_RELOC_POINTER_TO_GOT: 97 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2) 98 return MachOPointerToGOT; 99 break; 100 case MachO::ARM64_RELOC_ADDEND: 101 if (!RI.r_pcrel && !RI.r_extern && RI.r_length == 2) 102 return MachOPairedAddend; 103 break; 104 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 105 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2) 106 return MachOTLVPage21; 107 break; 108 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 109 if (!RI.r_pcrel && RI.r_extern && RI.r_length == 2) 110 return MachOTLVPageOffset12; 111 break; 112 } 113 114 return make_error<JITLinkError>( 115 "Unsupported arm64 relocation: address=" + 116 formatv("{0:x8}", RI.r_address) + 117 ", symbolnum=" + formatv("{0:x6}", RI.r_symbolnum) + 118 ", kind=" + formatv("{0:x1}", RI.r_type) + 119 ", pc_rel=" + (RI.r_pcrel ? "true" : "false") + 120 ", extern=" + (RI.r_extern ? "true" : "false") + 121 ", length=" + formatv("{0:d}", RI.r_length)); 122 } 123 124 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>; 125 126 // Parses paired SUBTRACTOR/UNSIGNED relocations and, on success, 127 // returns the edge kind and addend to be used. 128 Expected<PairRelocInfo> 129 parsePairRelocation(Block &BlockToFix, Edge::Kind SubtractorKind, 130 const MachO::relocation_info &SubRI, 131 orc::ExecutorAddr FixupAddress, const char *FixupContent, 132 object::relocation_iterator &UnsignedRelItr, 133 object::relocation_iterator &RelEnd) { 134 using namespace support; 135 136 assert(((SubtractorKind == MachODelta32 && SubRI.r_length == 2) || 137 (SubtractorKind == MachODelta64 && SubRI.r_length == 3)) && 138 "Subtractor kind should match length"); 139 assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern"); 140 assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel"); 141 142 if (UnsignedRelItr == RelEnd) 143 return make_error<JITLinkError>("arm64 SUBTRACTOR without paired " 144 "UNSIGNED relocation"); 145 146 auto UnsignedRI = getRelocationInfo(UnsignedRelItr); 147 148 if (SubRI.r_address != UnsignedRI.r_address) 149 return make_error<JITLinkError>("arm64 SUBTRACTOR and paired UNSIGNED " 150 "point to different addresses"); 151 152 if (SubRI.r_length != UnsignedRI.r_length) 153 return make_error<JITLinkError>("length of arm64 SUBTRACTOR and paired " 154 "UNSIGNED reloc must match"); 155 156 Symbol *FromSymbol; 157 if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum)) 158 FromSymbol = FromSymbolOrErr->GraphSymbol; 159 else 160 return FromSymbolOrErr.takeError(); 161 162 // Read the current fixup value. 163 uint64_t FixupValue = 0; 164 if (SubRI.r_length == 3) 165 FixupValue = *(const little64_t *)FixupContent; 166 else 167 FixupValue = *(const little32_t *)FixupContent; 168 169 // Find 'ToSymbol' using symbol number or address, depending on whether the 170 // paired UNSIGNED relocation is extern. 171 Symbol *ToSymbol = nullptr; 172 if (UnsignedRI.r_extern) { 173 // Find target symbol by symbol index. 174 if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum)) 175 ToSymbol = ToSymbolOrErr->GraphSymbol; 176 else 177 return ToSymbolOrErr.takeError(); 178 } else { 179 auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1); 180 if (!ToSymbolSec) 181 return ToSymbolSec.takeError(); 182 ToSymbol = getSymbolByAddress(*ToSymbolSec, ToSymbolSec->Address); 183 assert(ToSymbol && "No symbol for section"); 184 FixupValue -= ToSymbol->getAddress().getValue(); 185 } 186 187 Edge::Kind DeltaKind; 188 Symbol *TargetSymbol; 189 uint64_t Addend; 190 if (&BlockToFix == &FromSymbol->getAddressable()) { 191 TargetSymbol = ToSymbol; 192 DeltaKind = (SubRI.r_length == 3) ? aarch64::Delta64 : aarch64::Delta32; 193 Addend = FixupValue + (FixupAddress - FromSymbol->getAddress()); 194 // FIXME: handle extern 'from'. 195 } else if (&BlockToFix == &ToSymbol->getAddressable()) { 196 TargetSymbol = &*FromSymbol; 197 DeltaKind = 198 (SubRI.r_length == 3) ? aarch64::NegDelta64 : aarch64::NegDelta32; 199 Addend = FixupValue - (FixupAddress - ToSymbol->getAddress()); 200 } else { 201 // BlockToFix was neither FromSymbol nor ToSymbol. 202 return make_error<JITLinkError>("SUBTRACTOR relocation must fix up " 203 "either 'A' or 'B' (or a symbol in one " 204 "of their alt-entry groups)"); 205 } 206 207 return PairRelocInfo(DeltaKind, TargetSymbol, Addend); 208 } 209 210 Error addRelocations() override { 211 using namespace support; 212 auto &Obj = getObject(); 213 214 LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 215 216 for (auto &S : Obj.sections()) { 217 218 orc::ExecutorAddr SectionAddress(S.getAddress()); 219 220 // Skip relocations virtual sections. 221 if (S.isVirtual()) { 222 if (S.relocation_begin() != S.relocation_end()) 223 return make_error<JITLinkError>("Virtual section contains " 224 "relocations"); 225 continue; 226 } 227 228 auto NSec = 229 findSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl())); 230 if (!NSec) 231 return NSec.takeError(); 232 233 // Skip relocations for MachO sections without corresponding graph 234 // sections. 235 { 236 if (!NSec->GraphSection) { 237 LLVM_DEBUG({ 238 dbgs() << " Skipping relocations for MachO section " 239 << NSec->SegName << "/" << NSec->SectName 240 << " which has no associated graph section\n"; 241 }); 242 continue; 243 } 244 } 245 246 for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end(); 247 RelItr != RelEnd; ++RelItr) { 248 249 MachO::relocation_info RI = getRelocationInfo(RelItr); 250 251 // Validate the relocation kind. 252 auto MachORelocKind = getRelocationKind(RI); 253 if (!MachORelocKind) 254 return MachORelocKind.takeError(); 255 256 // Find the address of the value to fix up. 257 orc::ExecutorAddr FixupAddress = 258 SectionAddress + (uint32_t)RI.r_address; 259 LLVM_DEBUG({ 260 dbgs() << " " << NSec->SectName << " + " 261 << formatv("{0:x8}", RI.r_address) << ":\n"; 262 }); 263 264 // Find the block that the fixup points to. 265 Block *BlockToFix = nullptr; 266 { 267 auto SymbolToFixOrErr = findSymbolByAddress(*NSec, FixupAddress); 268 if (!SymbolToFixOrErr) 269 return SymbolToFixOrErr.takeError(); 270 BlockToFix = &SymbolToFixOrErr->getBlock(); 271 } 272 273 if (FixupAddress + orc::ExecutorAddrDiff(1ULL << RI.r_length) > 274 BlockToFix->getAddress() + BlockToFix->getContent().size()) 275 return make_error<JITLinkError>( 276 "Relocation content extends past end of fixup block"); 277 278 Edge::Kind Kind = Edge::Invalid; 279 280 // Get a pointer to the fixup content. 281 const char *FixupContent = BlockToFix->getContent().data() + 282 (FixupAddress - BlockToFix->getAddress()); 283 284 // The target symbol and addend will be populated by the switch below. 285 Symbol *TargetSymbol = nullptr; 286 uint64_t Addend = 0; 287 288 if (*MachORelocKind == MachOPairedAddend) { 289 // If this is an Addend relocation then process it and move to the 290 // paired reloc. 291 292 Addend = SignExtend64(RI.r_symbolnum, 24); 293 294 if (RelItr == RelEnd) 295 return make_error<JITLinkError>("Unpaired Addend reloc at " + 296 formatv("{0:x16}", FixupAddress)); 297 ++RelItr; 298 RI = getRelocationInfo(RelItr); 299 300 MachORelocKind = getRelocationKind(RI); 301 if (!MachORelocKind) 302 return MachORelocKind.takeError(); 303 304 if (*MachORelocKind != MachOBranch26 && 305 *MachORelocKind != MachOPage21 && 306 *MachORelocKind != MachOPageOffset12) 307 return make_error<JITLinkError>( 308 "Invalid relocation pair: Addend + " + 309 StringRef(getMachOARM64RelocationKindName(*MachORelocKind))); 310 311 LLVM_DEBUG({ 312 dbgs() << " Addend: value = " << formatv("{0:x6}", Addend) 313 << ", pair is " 314 << getMachOARM64RelocationKindName(*MachORelocKind) << "\n"; 315 }); 316 317 // Find the address of the value to fix up. 318 orc::ExecutorAddr PairedFixupAddress = 319 SectionAddress + (uint32_t)RI.r_address; 320 if (PairedFixupAddress != FixupAddress) 321 return make_error<JITLinkError>("Paired relocation points at " 322 "different target"); 323 } 324 325 switch (*MachORelocKind) { 326 case MachOBranch26: { 327 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum)) 328 TargetSymbol = TargetSymbolOrErr->GraphSymbol; 329 else 330 return TargetSymbolOrErr.takeError(); 331 uint32_t Instr = *(const ulittle32_t *)FixupContent; 332 if ((Instr & 0x7fffffff) != 0x14000000) 333 return make_error<JITLinkError>("BRANCH26 target is not a B or BL " 334 "instruction with a zero addend"); 335 Kind = aarch64::Branch26PCRel; 336 break; 337 } 338 case MachOPointer32: 339 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum)) 340 TargetSymbol = TargetSymbolOrErr->GraphSymbol; 341 else 342 return TargetSymbolOrErr.takeError(); 343 Addend = *(const ulittle32_t *)FixupContent; 344 Kind = aarch64::Pointer32; 345 break; 346 case MachOPointer64: 347 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum)) 348 TargetSymbol = TargetSymbolOrErr->GraphSymbol; 349 else 350 return TargetSymbolOrErr.takeError(); 351 Addend = *(const ulittle64_t *)FixupContent; 352 Kind = aarch64::Pointer64; 353 break; 354 case MachOPointer64Anon: { 355 orc::ExecutorAddr TargetAddress(*(const ulittle64_t *)FixupContent); 356 auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1); 357 if (!TargetNSec) 358 return TargetNSec.takeError(); 359 if (auto TargetSymbolOrErr = 360 findSymbolByAddress(*TargetNSec, TargetAddress)) 361 TargetSymbol = &*TargetSymbolOrErr; 362 else 363 return TargetSymbolOrErr.takeError(); 364 Addend = TargetAddress - TargetSymbol->getAddress(); 365 Kind = aarch64::Pointer64; 366 break; 367 } 368 case MachOPage21: 369 case MachOGOTPage21: 370 case MachOTLVPage21: { 371 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum)) 372 TargetSymbol = TargetSymbolOrErr->GraphSymbol; 373 else 374 return TargetSymbolOrErr.takeError(); 375 uint32_t Instr = *(const ulittle32_t *)FixupContent; 376 if ((Instr & 0xffffffe0) != 0x90000000) 377 return make_error<JITLinkError>("PAGE21/GOTPAGE21 target is not an " 378 "ADRP instruction with a zero " 379 "addend"); 380 381 if (*MachORelocKind == MachOPage21) { 382 Kind = aarch64::Page21; 383 } else if (*MachORelocKind == MachOGOTPage21) { 384 Kind = aarch64::RequestGOTAndTransformToPage21; 385 } else if (*MachORelocKind == MachOTLVPage21) { 386 Kind = aarch64::RequestTLVPAndTransformToPage21; 387 } 388 break; 389 } 390 case MachOPageOffset12: { 391 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum)) 392 TargetSymbol = TargetSymbolOrErr->GraphSymbol; 393 else 394 return TargetSymbolOrErr.takeError(); 395 uint32_t Instr = *(const ulittle32_t *)FixupContent; 396 uint32_t EncodedAddend = (Instr & 0x003FFC00) >> 10; 397 if (EncodedAddend != 0) 398 return make_error<JITLinkError>("GOTPAGEOFF12 target has non-zero " 399 "encoded addend"); 400 Kind = aarch64::PageOffset12; 401 break; 402 } 403 case MachOGOTPageOffset12: 404 case MachOTLVPageOffset12: { 405 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum)) 406 TargetSymbol = TargetSymbolOrErr->GraphSymbol; 407 else 408 return TargetSymbolOrErr.takeError(); 409 uint32_t Instr = *(const ulittle32_t *)FixupContent; 410 if ((Instr & 0xfffffc00) != 0xf9400000) 411 return make_error<JITLinkError>("GOTPAGEOFF12 target is not an LDR " 412 "immediate instruction with a zero " 413 "addend"); 414 415 if (*MachORelocKind == MachOGOTPageOffset12) { 416 Kind = aarch64::RequestGOTAndTransformToPageOffset12; 417 } else if (*MachORelocKind == MachOTLVPageOffset12) { 418 Kind = aarch64::RequestTLVPAndTransformToPageOffset12; 419 } 420 break; 421 } 422 case MachOPointerToGOT: 423 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum)) 424 TargetSymbol = TargetSymbolOrErr->GraphSymbol; 425 else 426 return TargetSymbolOrErr.takeError(); 427 428 Kind = aarch64::RequestGOTAndTransformToDelta32; 429 break; 430 case MachODelta32: 431 case MachODelta64: { 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 default: 447 llvm_unreachable("Special relocation kind should not appear in " 448 "mach-o file"); 449 } 450 451 LLVM_DEBUG({ 452 dbgs() << " "; 453 Edge GE(Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol, 454 Addend); 455 printEdge(dbgs(), *BlockToFix, GE, aarch64::getEdgeKindName(Kind)); 456 dbgs() << "\n"; 457 }); 458 BlockToFix->addEdge(Kind, FixupAddress - BlockToFix->getAddress(), 459 *TargetSymbol, Addend); 460 } 461 } 462 return Error::success(); 463 } 464 465 /// Return the string name of the given MachO arm64 edge kind. 466 const char *getMachOARM64RelocationKindName(Edge::Kind R) { 467 switch (R) { 468 case MachOBranch26: 469 return "MachOBranch26"; 470 case MachOPointer64: 471 return "MachOPointer64"; 472 case MachOPointer64Anon: 473 return "MachOPointer64Anon"; 474 case MachOPage21: 475 return "MachOPage21"; 476 case MachOPageOffset12: 477 return "MachOPageOffset12"; 478 case MachOGOTPage21: 479 return "MachOGOTPage21"; 480 case MachOGOTPageOffset12: 481 return "MachOGOTPageOffset12"; 482 case MachOTLVPage21: 483 return "MachOTLVPage21"; 484 case MachOTLVPageOffset12: 485 return "MachOTLVPageOffset12"; 486 case MachOPointerToGOT: 487 return "MachOPointerToGOT"; 488 case MachOPairedAddend: 489 return "MachOPairedAddend"; 490 case MachOLDRLiteral19: 491 return "MachOLDRLiteral19"; 492 case MachODelta32: 493 return "MachODelta32"; 494 case MachODelta64: 495 return "MachODelta64"; 496 case MachONegDelta32: 497 return "MachONegDelta32"; 498 case MachONegDelta64: 499 return "MachONegDelta64"; 500 default: 501 return getGenericEdgeKindName(static_cast<Edge::Kind>(R)); 502 } 503 } 504 505 unsigned NumSymbols = 0; 506 }; 507 508 } // namespace 509 510 namespace llvm { 511 namespace jitlink { 512 513 Error buildTables_MachO_arm64(LinkGraph &G) { 514 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 515 516 aarch64::GOTTableManager GOT; 517 aarch64::PLTTableManager PLT(GOT); 518 visitExistingEdges(G, GOT, PLT); 519 return Error::success(); 520 } 521 522 class MachOJITLinker_arm64 : public JITLinker<MachOJITLinker_arm64> { 523 friend class JITLinker<MachOJITLinker_arm64>; 524 525 public: 526 MachOJITLinker_arm64(std::unique_ptr<JITLinkContext> Ctx, 527 std::unique_ptr<LinkGraph> G, 528 PassConfiguration PassConfig) 529 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {} 530 531 private: 532 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 533 return aarch64::applyFixup(G, B, E); 534 } 535 536 uint64_t NullValue = 0; 537 }; 538 539 Expected<std::unique_ptr<LinkGraph>> 540 createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer) { 541 auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer); 542 if (!MachOObj) 543 return MachOObj.takeError(); 544 return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph(); 545 } 546 547 void link_MachO_arm64(std::unique_ptr<LinkGraph> G, 548 std::unique_ptr<JITLinkContext> Ctx) { 549 550 PassConfiguration Config; 551 552 if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { 553 // Add a mark-live pass. 554 if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) 555 Config.PrePrunePasses.push_back(std::move(MarkLive)); 556 else 557 Config.PrePrunePasses.push_back(markAllSymbolsLive); 558 559 // Add compact unwind splitter pass. 560 Config.PrePrunePasses.push_back( 561 CompactUnwindSplitter("__LD,__compact_unwind")); 562 563 // Add eh-frame passses. 564 // FIXME: Prune eh-frames for which compact-unwind is available once 565 // we support compact-unwind registration with libunwind. 566 Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_arm64()); 567 Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_arm64()); 568 569 // Add an in-place GOT/Stubs pass. 570 Config.PostPrunePasses.push_back(buildTables_MachO_arm64); 571 } 572 573 if (auto Err = Ctx->modifyPassConfig(*G, Config)) 574 return Ctx->notifyFailed(std::move(Err)); 575 576 // Construct a JITLinker and run the link function. 577 MachOJITLinker_arm64::link(std::move(Ctx), std::move(G), std::move(Config)); 578 } 579 580 LinkGraphPassFunction createEHFrameSplitterPass_MachO_arm64() { 581 return DWARFRecordSectionSplitter("__TEXT,__eh_frame"); 582 } 583 584 LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_arm64() { 585 return EHFrameEdgeFixer("__TEXT,__eh_frame", aarch64::PointerSize, 586 aarch64::Pointer32, aarch64::Pointer64, 587 aarch64::Delta32, aarch64::Delta64, 588 aarch64::NegDelta32); 589 } 590 591 } // end namespace jitlink 592 } // end namespace llvm 593