[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