726 lines · cpp
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-exception6//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#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 24using namespace llvm;25using namespace llvm::jitlink;26 27namespace {28 29class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder {30public:31 MachOLinkGraphBuilder_arm64(const object::MachOObjectFile &Obj,32 std::shared_ptr<orc::SymbolStringPool> SSP,33 SubtargetFeatures Features)34 : MachOLinkGraphBuilder(Obj, std::move(SSP), getObjectTriple(Obj),35 std::move(Features), aarch64::getEdgeKindName),36 NumSymbols(Obj.getSymtabLoadCommand().nsyms) {}37 38private:39 enum MachOARM64RelocationKind : Edge::Kind {40 MachOBranch26 = Edge::FirstRelocation,41 MachOPointer32,42 MachOPointer64,43 MachOPointer64Anon,44 MachOPointer64Authenticated,45 MachOPage21,46 MachOPageOffset12,47 MachOGOTPage21,48 MachOGOTPageOffset12,49 MachOTLVPage21,50 MachOTLVPageOffset12,51 MachOPointerToGOT,52 MachOPairedAddend,53 MachOLDRLiteral19,54 MachODelta32,55 MachODelta64,56 MachONegDelta32,57 MachONegDelta64,58 };59 60 static Triple getObjectTriple(const object::MachOObjectFile &Obj) {61 // Get the CPU sub-type from the header.62 // jitLink_MachO should already have validated that the buffer is big enough63 // to cover a mach_header64 so this is safe.64 uint32_t CPUSubType =65 *(const support::ulittle32_t *)(Obj.getData().data() + 8);66 CPUSubType &= ~MachO::CPU_SUBTYPE_MASK;67 if (CPUSubType == MachO::CPU_SUBTYPE_ARM64E)68 return Triple("arm64e-apple-darwin");69 return Triple("arm64-apple-darwin");70 }71 72 static Expected<MachOARM64RelocationKind>73 getRelocationKind(const MachO::relocation_info &RI) {74 switch (RI.r_type) {75 case MachO::ARM64_RELOC_UNSIGNED:76 if (!RI.r_pcrel) {77 if (RI.r_length == 3)78 return RI.r_extern ? MachOPointer64 : MachOPointer64Anon;79 else if (RI.r_length == 2)80 return MachOPointer32;81 }82 break;83 case MachO::ARM64_RELOC_SUBTRACTOR:84 // SUBTRACTOR must be non-pc-rel, extern, with length 2 or 3.85 // Initially represent SUBTRACTOR relocations with 'Delta<W>'.86 // They may be turned into NegDelta<W> by parsePairRelocation.87 if (!RI.r_pcrel && RI.r_extern) {88 if (RI.r_length == 2)89 return MachODelta32;90 else if (RI.r_length == 3)91 return MachODelta64;92 }93 break;94 case MachO::ARM64_RELOC_BRANCH26:95 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)96 return MachOBranch26;97 break;98 case MachO::ARM64_RELOC_PAGE21:99 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)100 return MachOPage21;101 break;102 case MachO::ARM64_RELOC_PAGEOFF12:103 if (!RI.r_pcrel && RI.r_extern && RI.r_length == 2)104 return MachOPageOffset12;105 break;106 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:107 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)108 return MachOGOTPage21;109 break;110 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:111 if (!RI.r_pcrel && RI.r_extern && RI.r_length == 2)112 return MachOGOTPageOffset12;113 break;114 case MachO::ARM64_RELOC_POINTER_TO_GOT:115 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)116 return MachOPointerToGOT;117 break;118 case MachO::ARM64_RELOC_ADDEND:119 if (!RI.r_pcrel && !RI.r_extern && RI.r_length == 2)120 return MachOPairedAddend;121 break;122 case MachO::ARM64_RELOC_AUTHENTICATED_POINTER:123 if (!RI.r_pcrel && RI.r_extern && RI.r_length == 3)124 return MachOPointer64Authenticated;125 break;126 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:127 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)128 return MachOTLVPage21;129 break;130 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:131 if (!RI.r_pcrel && RI.r_extern && RI.r_length == 2)132 return MachOTLVPageOffset12;133 break;134 }135 136 return make_error<JITLinkError>(137 "Unsupported arm64 relocation: address=" +138 formatv("{0:x8}", RI.r_address) +139 ", symbolnum=" + formatv("{0:x6}", RI.r_symbolnum) +140 ", kind=" + formatv("{0:x1}", RI.r_type) +141 ", pc_rel=" + (RI.r_pcrel ? "true" : "false") +142 ", extern=" + (RI.r_extern ? "true" : "false") +143 ", length=" + formatv("{0:d}", RI.r_length));144 }145 146 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;147 148 // Parses paired SUBTRACTOR/UNSIGNED relocations and, on success,149 // returns the edge kind and addend to be used.150 Expected<PairRelocInfo>151 parsePairRelocation(Block &BlockToFix, Edge::Kind SubtractorKind,152 const MachO::relocation_info &SubRI,153 orc::ExecutorAddr FixupAddress, const char *FixupContent,154 object::relocation_iterator &UnsignedRelItr,155 object::relocation_iterator &RelEnd) {156 using namespace support;157 158 assert(((SubtractorKind == MachODelta32 && SubRI.r_length == 2) ||159 (SubtractorKind == MachODelta64 && SubRI.r_length == 3)) &&160 "Subtractor kind should match length");161 assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern");162 assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel");163 164 if (UnsignedRelItr == RelEnd)165 return make_error<JITLinkError>("arm64 SUBTRACTOR without paired "166 "UNSIGNED relocation");167 168 auto UnsignedRI = getRelocationInfo(UnsignedRelItr);169 170 if (SubRI.r_address != UnsignedRI.r_address)171 return make_error<JITLinkError>("arm64 SUBTRACTOR and paired UNSIGNED "172 "point to different addresses");173 174 if (SubRI.r_length != UnsignedRI.r_length)175 return make_error<JITLinkError>("length of arm64 SUBTRACTOR and paired "176 "UNSIGNED reloc must match");177 178 Symbol *FromSymbol;179 if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum))180 FromSymbol = FromSymbolOrErr->GraphSymbol;181 else182 return FromSymbolOrErr.takeError();183 184 // Read the current fixup value.185 uint64_t FixupValue = 0;186 if (SubRI.r_length == 3)187 FixupValue = *(const little64_t *)FixupContent;188 else189 FixupValue = *(const little32_t *)FixupContent;190 191 // Find 'ToSymbol' using symbol number or address, depending on whether the192 // paired UNSIGNED relocation is extern.193 Symbol *ToSymbol = nullptr;194 if (UnsignedRI.r_extern) {195 // Find target symbol by symbol index.196 if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))197 ToSymbol = ToSymbolOrErr->GraphSymbol;198 else199 return ToSymbolOrErr.takeError();200 } else {201 auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);202 if (!ToSymbolSec)203 return ToSymbolSec.takeError();204 ToSymbol = getSymbolByAddress(*ToSymbolSec, ToSymbolSec->Address);205 assert(ToSymbol && "No symbol for section");206 FixupValue -= ToSymbol->getAddress().getValue();207 }208 209 Edge::Kind DeltaKind;210 Symbol *TargetSymbol;211 uint64_t Addend;212 213 bool FixingFromSymbol = true;214 if (&BlockToFix == &FromSymbol->getAddressable()) {215 if (LLVM_UNLIKELY(&BlockToFix == &ToSymbol->getAddressable())) {216 // From and To are symbols in the same block. Decide direction by offset217 // instead.218 if (ToSymbol->getAddress() > FixupAddress)219 FixingFromSymbol = true;220 else if (FromSymbol->getAddress() > FixupAddress)221 FixingFromSymbol = false;222 else223 FixingFromSymbol = FromSymbol->getAddress() >= ToSymbol->getAddress();224 } else225 FixingFromSymbol = true;226 } else {227 if (&BlockToFix == &ToSymbol->getAddressable())228 FixingFromSymbol = false;229 else {230 // BlockToFix was neither FromSymbol nor ToSymbol.231 return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "232 "either 'A' or 'B' (or a symbol in one "233 "of their alt-entry groups)");234 }235 }236 237 if (FixingFromSymbol) {238 TargetSymbol = ToSymbol;239 DeltaKind = (SubRI.r_length == 3) ? aarch64::Delta64 : aarch64::Delta32;240 Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());241 // FIXME: handle extern 'from'.242 } else {243 TargetSymbol = &*FromSymbol;244 DeltaKind =245 (SubRI.r_length == 3) ? aarch64::NegDelta64 : aarch64::NegDelta32;246 Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());247 }248 249 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);250 }251 252 Error addRelocations() override {253 using namespace support;254 auto &Obj = getObject();255 256 LLVM_DEBUG(dbgs() << "Processing relocations:\n");257 258 for (auto &S : Obj.sections()) {259 260 orc::ExecutorAddr SectionAddress(S.getAddress());261 262 // Skip relocations virtual sections.263 if (S.isVirtual()) {264 if (!S.relocations().empty())265 return make_error<JITLinkError>("Virtual section contains "266 "relocations");267 continue;268 }269 270 auto NSec =271 findSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));272 if (!NSec)273 return NSec.takeError();274 275 // Skip relocations for MachO sections without corresponding graph276 // sections.277 {278 if (!NSec->GraphSection) {279 LLVM_DEBUG({280 dbgs() << " Skipping relocations for MachO section "281 << NSec->SegName << "/" << NSec->SectName282 << " which has no associated graph section\n";283 });284 continue;285 }286 }287 288 for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();289 RelItr != RelEnd; ++RelItr) {290 291 MachO::relocation_info RI = getRelocationInfo(RelItr);292 293 // Validate the relocation kind.294 auto MachORelocKind = getRelocationKind(RI);295 if (!MachORelocKind)296 return MachORelocKind.takeError();297 298 // Find the address of the value to fix up.299 orc::ExecutorAddr FixupAddress =300 SectionAddress + (uint32_t)RI.r_address;301 LLVM_DEBUG({302 dbgs() << " " << NSec->SectName << " + "303 << formatv("{0:x8}", RI.r_address) << ":\n";304 });305 306 // Find the block that the fixup points to.307 Block *BlockToFix = nullptr;308 {309 auto SymbolToFixOrErr = findSymbolByAddress(*NSec, FixupAddress);310 if (!SymbolToFixOrErr)311 return SymbolToFixOrErr.takeError();312 BlockToFix = &SymbolToFixOrErr->getBlock();313 }314 315 if (FixupAddress + orc::ExecutorAddrDiff(1ULL << RI.r_length) >316 BlockToFix->getAddress() + BlockToFix->getContent().size())317 return make_error<JITLinkError>(318 "Relocation content extends past end of fixup block");319 320 Edge::Kind Kind = Edge::Invalid;321 322 // Get a pointer to the fixup content.323 const char *FixupContent = BlockToFix->getContent().data() +324 (FixupAddress - BlockToFix->getAddress());325 326 // The target symbol and addend will be populated by the switch below.327 Symbol *TargetSymbol = nullptr;328 uint64_t Addend = 0;329 330 if (*MachORelocKind == MachOPairedAddend) {331 // If this is an Addend relocation then process it and move to the332 // paired reloc.333 334 Addend = SignExtend64(RI.r_symbolnum, 24);335 336 ++RelItr;337 if (RelItr == RelEnd)338 return make_error<JITLinkError>("Unpaired Addend reloc at " +339 formatv("{0:x16}", FixupAddress));340 RI = getRelocationInfo(RelItr);341 342 MachORelocKind = getRelocationKind(RI);343 if (!MachORelocKind)344 return MachORelocKind.takeError();345 346 if (*MachORelocKind != MachOBranch26 &&347 *MachORelocKind != MachOPage21 &&348 *MachORelocKind != MachOPageOffset12)349 return make_error<JITLinkError>(350 "Invalid relocation pair: Addend + " +351 StringRef(getMachOARM64RelocationKindName(*MachORelocKind)));352 353 LLVM_DEBUG({354 dbgs() << " Addend: value = " << formatv("{0:x6}", Addend)355 << ", pair is "356 << getMachOARM64RelocationKindName(*MachORelocKind) << "\n";357 });358 359 // Find the address of the value to fix up.360 orc::ExecutorAddr PairedFixupAddress =361 SectionAddress + (uint32_t)RI.r_address;362 if (PairedFixupAddress != FixupAddress)363 return make_error<JITLinkError>("Paired relocation points at "364 "different target");365 }366 367 switch (*MachORelocKind) {368 case MachOBranch26: {369 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))370 TargetSymbol = TargetSymbolOrErr->GraphSymbol;371 else372 return TargetSymbolOrErr.takeError();373 uint32_t Instr = *(const ulittle32_t *)FixupContent;374 if ((Instr & 0x7fffffff) != 0x14000000)375 return make_error<JITLinkError>("BRANCH26 target is not a B or BL "376 "instruction with a zero addend");377 Kind = aarch64::Branch26PCRel;378 break;379 }380 case MachOPointer32:381 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))382 TargetSymbol = TargetSymbolOrErr->GraphSymbol;383 else384 return TargetSymbolOrErr.takeError();385 Addend = *(const ulittle32_t *)FixupContent;386 Kind = aarch64::Pointer32;387 break;388 case MachOPointer64:389 case MachOPointer64Authenticated:390 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))391 TargetSymbol = TargetSymbolOrErr->GraphSymbol;392 else393 return TargetSymbolOrErr.takeError();394 Addend = *(const ulittle64_t *)FixupContent;395 Kind = *MachORelocKind == MachOPointer64396 ? aarch64::Pointer64397 : aarch64::Pointer64Authenticated;398 break;399 case MachOPointer64Anon: {400 orc::ExecutorAddr TargetAddress(*(const ulittle64_t *)FixupContent);401 auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);402 if (!TargetNSec)403 return TargetNSec.takeError();404 if (auto TargetSymbolOrErr =405 findSymbolByAddress(*TargetNSec, TargetAddress))406 TargetSymbol = &*TargetSymbolOrErr;407 else408 return TargetSymbolOrErr.takeError();409 Addend = TargetAddress - TargetSymbol->getAddress();410 Kind = aarch64::Pointer64;411 break;412 }413 case MachOPage21:414 case MachOGOTPage21:415 case MachOTLVPage21: {416 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))417 TargetSymbol = TargetSymbolOrErr->GraphSymbol;418 else419 return TargetSymbolOrErr.takeError();420 uint32_t Instr = *(const ulittle32_t *)FixupContent;421 if ((Instr & 0xffffffe0) != 0x90000000)422 return make_error<JITLinkError>("PAGE21/GOTPAGE21 target is not an "423 "ADRP instruction with a zero "424 "addend");425 426 if (*MachORelocKind == MachOPage21) {427 Kind = aarch64::Page21;428 } else if (*MachORelocKind == MachOGOTPage21) {429 Kind = aarch64::RequestGOTAndTransformToPage21;430 } else if (*MachORelocKind == MachOTLVPage21) {431 Kind = aarch64::RequestTLVPAndTransformToPage21;432 }433 break;434 }435 case MachOPageOffset12: {436 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))437 TargetSymbol = TargetSymbolOrErr->GraphSymbol;438 else439 return TargetSymbolOrErr.takeError();440 uint32_t Instr = *(const ulittle32_t *)FixupContent;441 uint32_t EncodedAddend = (Instr & 0x003FFC00) >> 10;442 if (EncodedAddend != 0)443 return make_error<JITLinkError>("GOTPAGEOFF12 target has non-zero "444 "encoded addend");445 Kind = aarch64::PageOffset12;446 break;447 }448 case MachOGOTPageOffset12:449 case MachOTLVPageOffset12: {450 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))451 TargetSymbol = TargetSymbolOrErr->GraphSymbol;452 else453 return TargetSymbolOrErr.takeError();454 uint32_t Instr = *(const ulittle32_t *)FixupContent;455 if ((Instr & 0xfffffc00) != 0xf9400000)456 return make_error<JITLinkError>("GOTPAGEOFF12 target is not an LDR "457 "immediate instruction with a zero "458 "addend");459 460 if (*MachORelocKind == MachOGOTPageOffset12) {461 Kind = aarch64::RequestGOTAndTransformToPageOffset12;462 } else if (*MachORelocKind == MachOTLVPageOffset12) {463 Kind = aarch64::RequestTLVPAndTransformToPageOffset12;464 }465 break;466 }467 case MachOPointerToGOT:468 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))469 TargetSymbol = TargetSymbolOrErr->GraphSymbol;470 else471 return TargetSymbolOrErr.takeError();472 473 Kind = aarch64::RequestGOTAndTransformToDelta32;474 break;475 case MachODelta32:476 case MachODelta64: {477 // We use Delta32/Delta64 to represent SUBTRACTOR relocations.478 // parsePairRelocation handles the paired reloc, and returns the479 // edge kind to be used (either Delta32/Delta64, or480 // NegDelta32/NegDelta64, depending on the direction of the481 // subtraction) along with the addend.482 auto PairInfo =483 parsePairRelocation(*BlockToFix, *MachORelocKind, RI,484 FixupAddress, FixupContent, ++RelItr, RelEnd);485 if (!PairInfo)486 return PairInfo.takeError();487 std::tie(Kind, TargetSymbol, Addend) = *PairInfo;488 assert(TargetSymbol && "No target symbol from parsePairRelocation?");489 break;490 }491 default:492 llvm_unreachable("Special relocation kind should not appear in "493 "mach-o file");494 }495 496 LLVM_DEBUG({497 dbgs() << " ";498 Edge GE(Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,499 Addend);500 printEdge(dbgs(), *BlockToFix, GE, aarch64::getEdgeKindName(Kind));501 dbgs() << "\n";502 });503 BlockToFix->addEdge(Kind, FixupAddress - BlockToFix->getAddress(),504 *TargetSymbol, Addend);505 }506 }507 return Error::success();508 }509 510 /// Return the string name of the given MachO arm64 edge kind.511 const char *getMachOARM64RelocationKindName(Edge::Kind R) {512 switch (R) {513 case MachOBranch26:514 return "MachOBranch26";515 case MachOPointer64:516 return "MachOPointer64";517 case MachOPointer64Anon:518 return "MachOPointer64Anon";519 case MachOPointer64Authenticated:520 return "MachOPointer64Authenticated";521 case MachOPage21:522 return "MachOPage21";523 case MachOPageOffset12:524 return "MachOPageOffset12";525 case MachOGOTPage21:526 return "MachOGOTPage21";527 case MachOGOTPageOffset12:528 return "MachOGOTPageOffset12";529 case MachOTLVPage21:530 return "MachOTLVPage21";531 case MachOTLVPageOffset12:532 return "MachOTLVPageOffset12";533 case MachOPointerToGOT:534 return "MachOPointerToGOT";535 case MachOPairedAddend:536 return "MachOPairedAddend";537 case MachOLDRLiteral19:538 return "MachOLDRLiteral19";539 case MachODelta32:540 return "MachODelta32";541 case MachODelta64:542 return "MachODelta64";543 case MachONegDelta32:544 return "MachONegDelta32";545 case MachONegDelta64:546 return "MachONegDelta64";547 default:548 return getGenericEdgeKindName(R);549 }550 }551 552 unsigned NumSymbols = 0;553};554 555} // namespace556 557namespace llvm {558namespace jitlink {559 560Error buildTables_MachO_arm64(LinkGraph &G) {561 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");562 563 aarch64::GOTTableManager GOT(G);564 aarch64::PLTTableManager PLT(G, GOT);565 visitExistingEdges(G, GOT, PLT);566 return Error::success();567}568 569class MachOJITLinker_arm64 : public JITLinker<MachOJITLinker_arm64> {570 friend class JITLinker<MachOJITLinker_arm64>;571 572public:573 MachOJITLinker_arm64(std::unique_ptr<JITLinkContext> Ctx,574 std::unique_ptr<LinkGraph> G,575 PassConfiguration PassConfig)576 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}577 578private:579 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {580 return aarch64::applyFixup(G, B, E, nullptr);581 }582 583 uint64_t NullValue = 0;584};585 586Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromMachOObject_arm64(587 MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {588 auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);589 if (!MachOObj)590 return MachOObj.takeError();591 592 auto Features = (*MachOObj)->getFeatures();593 if (!Features)594 return Features.takeError();595 596 return MachOLinkGraphBuilder_arm64(**MachOObj, std::move(SSP),597 std::move(*Features))598 .buildGraph();599}600 601static Error applyPACSigningToModInitPointers(LinkGraph &G) {602 assert(G.getTargetTriple().isArm64e() && "PAC signing only valid for arm64e");603 604 if (auto *ModInitSec = G.findSectionByName("__DATA,__mod_init_func")) {605 for (auto *B : ModInitSec->blocks()) {606 for (auto &E : B->edges()) {607 if (E.getKind() == aarch64::Pointer64) {608 609 // Check that we have room to encode pointer signing bits.610 if (E.getAddend() >> 32)611 return make_error<JITLinkError>(612 "In " + G.getName() + ", __mod_init_func pointer at " +613 formatv("{0:x}", B->getFixupAddress(E).getValue()) +614 " has data in high bits of addend (addend >= 2^32)");615 616 // Change edge to Pointer64Authenticated, encode signing:617 // key = asia, discriminator = 0, diversity = 0.618 Edge::AddendT SigningBits = 0x1ULL << 63;619 E.setKind(aarch64::Pointer64Authenticated);620 E.setAddend(E.getAddend() | SigningBits);621 }622 }623 }624 }625 626 return Error::success();627}628 629struct CompactUnwindTraits_MachO_arm64630 : public CompactUnwindTraits<CompactUnwindTraits_MachO_arm64,631 /* PointerSize = */ 8> {632 // FIXME: Reinstate once we no longer need the MSVC workaround. See633 // FIXME for CompactUnwindTraits in CompactUnwindSupport.h.634 // constexpr static size_t PointerSize = 8;635 636 constexpr static endianness Endianness = endianness::little;637 638 constexpr static uint32_t EncodingModeMask = 0x0f000000;639 constexpr static uint32_t DWARFSectionOffsetMask = 0x00ffffff;640 641 using GOTManager = aarch64::GOTTableManager;642 643 static bool encodingSpecifiesDWARF(uint32_t Encoding) {644 constexpr uint32_t DWARFMode = 0x03000000;645 return (Encoding & EncodingModeMask) == DWARFMode;646 }647 648 static bool encodingCannotBeMerged(uint32_t Encoding) { return false; }649};650 651void link_MachO_arm64(std::unique_ptr<LinkGraph> G,652 std::unique_ptr<JITLinkContext> Ctx) {653 654 PassConfiguration Config;655 656 if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {657 // Add a mark-live pass.658 if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))659 Config.PrePrunePasses.push_back(std::move(MarkLive));660 else661 Config.PrePrunePasses.push_back(markAllSymbolsLive);662 663 // Add eh-frame passes.664 Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_arm64());665 Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_arm64());666 667 // Create a compact-unwind manager for use in passes below.668 auto CompactUnwindMgr =669 std::make_shared<CompactUnwindManager<CompactUnwindTraits_MachO_arm64>>(670 orc::MachOCompactUnwindSectionName, orc::MachOUnwindInfoSectionName,671 orc::MachOEHFrameSectionName);672 673 // Add compact unwind prepare pass.674 Config.PrePrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) {675 return CompactUnwindMgr->prepareForPrune(G);676 });677 678 // Resolve any external section start / end symbols.679 Config.PostAllocationPasses.push_back(680 createDefineExternalSectionStartAndEndSymbolsPass(681 identifyMachOSectionStartAndEndSymbols));682 683 // Add an in-place GOT/Stubs pass.684 Config.PostPrunePasses.push_back(buildTables_MachO_arm64);685 686 // If this is an arm64e graph then add pointer signing passes.687 if (G->getTargetTriple().isArm64e()) {688 Config.PostPrunePasses.push_back(applyPACSigningToModInitPointers);689 Config.PostPrunePasses.push_back(690 aarch64::createEmptyPointerSigningFunction);691 Config.PreFixupPasses.push_back(692 aarch64::lowerPointer64AuthEdgesToSigningFunction);693 }694 695 // Reserve unwind-info space.696 Config.PostPrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) {697 return CompactUnwindMgr->processAndReserveUnwindInfo(G);698 });699 700 // Translate compact-unwind to unwind-info.701 Config.PreFixupPasses.push_back([CompactUnwindMgr](LinkGraph &G) {702 return CompactUnwindMgr->writeUnwindInfo(G);703 });704 }705 706 if (auto Err = Ctx->modifyPassConfig(*G, Config))707 return Ctx->notifyFailed(std::move(Err));708 709 // Construct a JITLinker and run the link function.710 MachOJITLinker_arm64::link(std::move(Ctx), std::move(G), std::move(Config));711}712 713LinkGraphPassFunction createEHFrameSplitterPass_MachO_arm64() {714 return DWARFRecordSectionSplitter(orc::MachOEHFrameSectionName);715}716 717LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_arm64() {718 return EHFrameEdgeFixer(orc::MachOEHFrameSectionName, aarch64::PointerSize,719 aarch64::Pointer32, aarch64::Pointer64,720 aarch64::Delta32, aarch64::Delta64,721 aarch64::NegDelta32);722}723 724} // end namespace jitlink725} // end namespace llvm726