Skip to content

Commit

Permalink
[AArch64][PAC] Emit auth call for Darwin tlv access thunk. (llvm#97658)
Browse files Browse the repository at this point in the history
With ptrauth-calls, function pointers are supposed to be signed.
On Darwin that includes the TLS indirection accessor (`_tlv_get_addr`).
We simply sign it with the plain function-pointer schema (IA,0), which
lets us do a `blraaz` when calling it.

Note that this doesn't have any kind of diversity, even when function
pointer diversity is enabled in the frontend.  On arm64e this accessor
is never signed that way, but the obvious alternative where this (or
another backend-generated) function pointer needs to be diversified
would need more than the "ptrauth-calls" attribute as it exists today.
  • Loading branch information
ahmedbougacha authored and aaryanshukla committed Jul 14, 2024
1 parent d0ca712 commit ee5d1ed
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 5 deletions.
22 changes: 18 additions & 4 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9227,10 +9227,24 @@ AArch64TargetLowering::LowerDarwinGlobalTLSAddress(SDValue Op,
// normal AArch64 call node: x0 takes the address of the descriptor, and
// returns the address of the variable in this thread.
Chain = DAG.getCopyToReg(Chain, DL, AArch64::X0, DescAddr, SDValue());
Chain =
DAG.getNode(AArch64ISD::CALL, DL, DAG.getVTList(MVT::Other, MVT::Glue),
Chain, FuncTLVGet, DAG.getRegister(AArch64::X0, MVT::i64),
DAG.getRegisterMask(Mask), Chain.getValue(1));

unsigned Opcode = AArch64ISD::CALL;
SmallVector<SDValue, 8> Ops;
Ops.push_back(Chain);
Ops.push_back(FuncTLVGet);

// With ptrauth-calls, the tlv access thunk pointer is authenticated (IA, 0).
if (DAG.getMachineFunction().getFunction().hasFnAttribute("ptrauth-calls")) {
Opcode = AArch64ISD::AUTH_CALL;
Ops.push_back(DAG.getTargetConstant(AArch64PACKey::IA, DL, MVT::i32));
Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64)); // Integer Disc.
Ops.push_back(DAG.getRegister(AArch64::NoRegister, MVT::i64)); // Addr Disc.
}

Ops.push_back(DAG.getRegister(AArch64::X0, MVT::i64));
Ops.push_back(DAG.getRegisterMask(Mask));
Ops.push_back(Chain.getValue(1));
Chain = DAG.getNode(Opcode, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Chain.getValue(1));
}

Expand Down
10 changes: 9 additions & 1 deletion llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3653,7 +3653,15 @@ bool AArch64InstructionSelector::selectTLSGlobalValue(
// TLS calls preserve all registers except those that absolutely must be
// trashed: X0 (it takes an argument), LR (it's a call) and NZCV (let's not be
// silly).
MIB.buildInstr(getBLRCallOpcode(MF), {}, {Load})
unsigned Opcode = getBLRCallOpcode(MF);

// With ptrauth-calls, the tlv access thunk pointer is authenticated (IA, 0).
if (MF.getFunction().hasFnAttribute("ptrauth-calls")) {
assert(Opcode == AArch64::BLR);
Opcode = AArch64::BLRAAZ;
}

MIB.buildInstr(Opcode, {}, {Load})
.addUse(AArch64::X0, RegState::Implicit)
.addDef(AArch64::X0, RegState::Implicit)
.addRegMask(TRI.getTLSCallPreservedMask());
Expand Down
27 changes: 27 additions & 0 deletions llvm/test/CodeGen/AArch64/ptrauth-tls-darwin.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=arm64e-apple-darwin %s -o - \
; RUN: -aarch64-enable-collect-loh=0 | FileCheck %s

; RUN: llc -mtriple=arm64e-apple-darwin %s -o - \
; RUN: -global-isel -global-isel-abort=1 -verify-machineinstrs \
; RUN: -aarch64-enable-collect-loh=0 | FileCheck %s

@var = thread_local global i8 0

define i8 @get_var() #0 {
; CHECK-LABEL: get_var:
; CHECK: ; %bb.0:
; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
; CHECK-NEXT: adrp x0, _var@TLVPPAGE
; CHECK-NEXT: ldr x0, [x0, _var@TLVPPAGEOFF]
; CHECK-NEXT: ldr x8, [x0]
; CHECK-NEXT: blraaz x8
; CHECK-NEXT: ldrb w0, [x0]
; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
; CHECK-NEXT: ret

%val = load i8, ptr @var, align 1
ret i8 %val
}

attributes #0 = { nounwind "ptrauth-calls" }

0 comments on commit ee5d1ed

Please sign in to comment.