[llvm] [AArch64][PAC] Emit auth call for tlv access thunk function pointer. (PR #97658)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 3 20:40:09 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Ahmed Bougacha (ahmedbougacha)
<details>
<summary>Changes</summary>
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.
I'm only vaguely familiar with the ELF equivalents, but IIRC there's more variety, so this doesn't even try to handle that ;)
---
Full diff: https://github.com/llvm/llvm-project/pull/97658.diff
3 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+18-4)
- (modified) llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp (+9-1)
- (added) llvm/test/CodeGen/AArch64/ptrauth-darwin-tls.ll (+27)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e0c3cc5eddb82..115a26a76bf34 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -9233,10 +9233,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));
}
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 9e0860934f777..be02f92ec71f9 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -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());
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-darwin-tls.ll b/llvm/test/CodeGen/AArch64/ptrauth-darwin-tls.ll
new file mode 100644
index 0000000000000..e3cb0e818d16d
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-darwin-tls.ll
@@ -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
+
+ at 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 at TLVPPAGE
+; CHECK-NEXT: ldr x0, [x0, _var at 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" }
``````````
</details>
https://github.com/llvm/llvm-project/pull/97658
More information about the llvm-commits
mailing list