-
Notifications
You must be signed in to change notification settings - Fork 11k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[AArch64][PAC] Emit auth call for Darwin tlv access thunk. #97658
[AArch64][PAC] Emit auth call for Darwin tlv access thunk. #97658
Conversation
@llvm/pr-subscribers-backend-aarch64 Author: Ahmed Bougacha (ahmedbougacha) ChangesWith ptrauth-calls, function pointers are supposed to be signed. 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:
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
+
+@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" }
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
You are right, it's handled differently. JFYI: see |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/51/builds/1258 Here is the relevant piece of the build log for the reference:
|
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.
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 ;)