Skip to content

Commit ee4661e

Browse files
[AArch64][PAC] Emit auth call for Darwin tlv access thunk. (#97658)
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.
1 parent 7b135f7 commit ee4661e

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9227,10 +9227,24 @@ AArch64TargetLowering::LowerDarwinGlobalTLSAddress(SDValue Op,
92279227
// normal AArch64 call node: x0 takes the address of the descriptor, and
92289228
// returns the address of the variable in this thread.
92299229
Chain = DAG.getCopyToReg(Chain, DL, AArch64::X0, DescAddr, SDValue());
9230-
Chain =
9231-
DAG.getNode(AArch64ISD::CALL, DL, DAG.getVTList(MVT::Other, MVT::Glue),
9232-
Chain, FuncTLVGet, DAG.getRegister(AArch64::X0, MVT::i64),
9233-
DAG.getRegisterMask(Mask), Chain.getValue(1));
9230+
9231+
unsigned Opcode = AArch64ISD::CALL;
9232+
SmallVector<SDValue, 8> Ops;
9233+
Ops.push_back(Chain);
9234+
Ops.push_back(FuncTLVGet);
9235+
9236+
// With ptrauth-calls, the tlv access thunk pointer is authenticated (IA, 0).
9237+
if (DAG.getMachineFunction().getFunction().hasFnAttribute("ptrauth-calls")) {
9238+
Opcode = AArch64ISD::AUTH_CALL;
9239+
Ops.push_back(DAG.getTargetConstant(AArch64PACKey::IA, DL, MVT::i32));
9240+
Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64)); // Integer Disc.
9241+
Ops.push_back(DAG.getRegister(AArch64::NoRegister, MVT::i64)); // Addr Disc.
9242+
}
9243+
9244+
Ops.push_back(DAG.getRegister(AArch64::X0, MVT::i64));
9245+
Ops.push_back(DAG.getRegisterMask(Mask));
9246+
Ops.push_back(Chain.getValue(1));
9247+
Chain = DAG.getNode(Opcode, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
92349248
return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Chain.getValue(1));
92359249
}
92369250

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3653,7 +3653,15 @@ bool AArch64InstructionSelector::selectTLSGlobalValue(
36533653
// TLS calls preserve all registers except those that absolutely must be
36543654
// trashed: X0 (it takes an argument), LR (it's a call) and NZCV (let's not be
36553655
// silly).
3656-
MIB.buildInstr(getBLRCallOpcode(MF), {}, {Load})
3656+
unsigned Opcode = getBLRCallOpcode(MF);
3657+
3658+
// With ptrauth-calls, the tlv access thunk pointer is authenticated (IA, 0).
3659+
if (MF.getFunction().hasFnAttribute("ptrauth-calls")) {
3660+
assert(Opcode == AArch64::BLR);
3661+
Opcode = AArch64::BLRAAZ;
3662+
}
3663+
3664+
MIB.buildInstr(Opcode, {}, {Load})
36573665
.addUse(AArch64::X0, RegState::Implicit)
36583666
.addDef(AArch64::X0, RegState::Implicit)
36593667
.addRegMask(TRI.getTLSCallPreservedMask());
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=arm64e-apple-darwin %s -o - \
3+
; RUN: -aarch64-enable-collect-loh=0 | FileCheck %s
4+
5+
; RUN: llc -mtriple=arm64e-apple-darwin %s -o - \
6+
; RUN: -global-isel -global-isel-abort=1 -verify-machineinstrs \
7+
; RUN: -aarch64-enable-collect-loh=0 | FileCheck %s
8+
9+
@var = thread_local global i8 0
10+
11+
define i8 @get_var() #0 {
12+
; CHECK-LABEL: get_var:
13+
; CHECK: ; %bb.0:
14+
; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
15+
; CHECK-NEXT: adrp x0, _var@TLVPPAGE
16+
; CHECK-NEXT: ldr x0, [x0, _var@TLVPPAGEOFF]
17+
; CHECK-NEXT: ldr x8, [x0]
18+
; CHECK-NEXT: blraaz x8
19+
; CHECK-NEXT: ldrb w0, [x0]
20+
; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
21+
; CHECK-NEXT: ret
22+
23+
%val = load i8, ptr @var, align 1
24+
ret i8 %val
25+
}
26+
27+
attributes #0 = { nounwind "ptrauth-calls" }

0 commit comments

Comments
 (0)