Skip to content

Commit 0cfd20e

Browse files
committed
[JITLink][arm64][MachO] Apply PAC signing to __mod_init_func pointers.
The __mod_init_func section contains pointers to static initializer functions. In the static compilation model for MachO/arm64e these are unsigned pointers that are signed by dyld before being called. This patch teaches JITLink's MachO/arm64 backend to sign __mod_init_func pointers using the PAC signing function introduced in a432f11 (signing is triggered by rewriting all Pointer64 edges in the section to Pointer64Authenticated edges). This means that unlike the static compilation model the linked __mod_init_func section will contain signed pointers. Note: Signing of init pointers could instead have been handled by the ORC runtime in a manner similar to dyld, but this would have come at the cost of adding an extra signing oracle. Using the signing function avoids this. Testing this change requires execution. It is covered by the trivial-cxx-constructor.cpp testcase that was added to the ORC runtime in 7c07863.
1 parent 9894cd5 commit 0cfd20e

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,35 @@ createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer) {
594594
.buildGraph();
595595
}
596596

597+
static Error applyPACSigningToModInitPointers(LinkGraph &G) {
598+
assert(G.getTargetTriple().getSubArch() == Triple::AArch64SubArch_arm64e &&
599+
"PAC signing only valid for arm64e");
600+
601+
if (auto *ModInitSec = G.findSectionByName("__DATA,__mod_init_func")) {
602+
for (auto *B : ModInitSec->blocks()) {
603+
for (auto &E : B->edges()) {
604+
if (E.getKind() == aarch64::Pointer64) {
605+
606+
// Check that we have room to encode pointer signing bits.
607+
if (E.getAddend() >> 32)
608+
return make_error<JITLinkError>(
609+
"In " + G.getName() + ", __mod_init_func pointer at " +
610+
formatv("{0:x}", B->getFixupAddress(E).getValue()) +
611+
" has data in high bits of addend (addend >= 2^32)");
612+
613+
// Change edge to Pointer64Authenticated, encode signing:
614+
// key = asia, discriminator = 0, diversity = 0.
615+
Edge::AddendT SigningBits = 0x1ULL << 63;
616+
E.setKind(aarch64::Pointer64Authenticated);
617+
E.setAddend(E.getAddend() | SigningBits);
618+
}
619+
}
620+
}
621+
}
622+
623+
return Error::success();
624+
}
625+
597626
void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
598627
std::unique_ptr<JITLinkContext> Ctx) {
599628

@@ -626,6 +655,7 @@ void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
626655

627656
// If this is an arm64e graph then add pointer signing passes.
628657
if (G->getTargetTriple().isArm64e()) {
658+
Config.PostPrunePasses.push_back(applyPACSigningToModInitPointers);
629659
Config.PostPrunePasses.push_back(
630660
aarch64::createEmptyPointerSigningFunction);
631661
Config.PreFixupPasses.push_back(

0 commit comments

Comments
 (0)