[llvm-branch-commits] [llvm] release/20.x: [AArch64] PAUTH_PROLOGUE should not be duplicated with PAuthLR (#124775) (PR #125230)
Tom Stellard via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Jan 31 15:52:43 PST 2025
https://github.com/tstellar updated https://github.com/llvm/llvm-project/pull/125230
>From 27f57290a8ba9323c8bda95a844880d7b9c450a9 Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Wed, 29 Jan 2025 10:42:47 +0000
Subject: [PATCH] [AArch64] PAUTH_PROLOGUE should not be duplicated with
PAuthLR (#124775)
When using PAuthLR, the PAUTH_PROLOGUE expands into a sequence of
instructions which takes the address of one of those instructions, and
uses that address to compute the return address signature. If this is
duplicated, there will be two different addresses used in calculating
the signature, so the epilogue will only be correct for (at most) one of
them.
This change also restricts code generation when using v8.3-A return
address signing, without PAuthLR. This isn't strictly needed, as
duplicating the prologue there would be valid. We could fix this by
having two copies of PAUTH_PROLOGUE, with and without isNotDuplicable,
but I don't think it's worth adding the extra complexity to a security
feature for that.
(cherry picked from commit 36b3c43524c8ca86a5050496b8773f07c5ccddff)
---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 7 +-
.../AArch64/pauthlr-prologue-duplication.mir | 88 +++++++++++++++++++
2 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/AArch64/pauthlr-prologue-duplication.mir
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index d112d4f10e47d99..b77246200db6456 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1773,7 +1773,12 @@ def : InstAlias<"xpaclri", (XPACLRI), 0>;
let Uses = [LR, SP], Defs = [LR] in {
// Insertion point of LR signing code.
-def PAUTH_PROLOGUE : Pseudo<(outs), (ins), []>, Sched<[]>;
+def PAUTH_PROLOGUE : Pseudo<(outs), (ins), []>, Sched<[]> {
+ // When using PAuthLR, the address of one of the instructions this expands
+ // into is used as an input to the signature calculation, so this must not be
+ // duplicated.
+ let isNotDuplicable = 1;
+}
// Insertion point of LR authentication code.
// The RET terminator of the containing machine basic block may be replaced
// with a combined RETA(A|B) instruction when rewriting this Pseudo.
diff --git a/llvm/test/CodeGen/AArch64/pauthlr-prologue-duplication.mir b/llvm/test/CodeGen/AArch64/pauthlr-prologue-duplication.mir
new file mode 100644
index 000000000000000..5e57604263793c6
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/pauthlr-prologue-duplication.mir
@@ -0,0 +1,88 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple aarch64-none-elf -run-pass=block-placement -O3 -o - %s | FileCheck %s
+
+## Check that block-placement does not perform tail duplication on the
+## PAUTH_EPILOGUE instruction. If that happened, the two prologues would use
+## different addresses while calculating the return address signature, so the
+## epilogue could only be correct for (at most) one of them.
+
+--- |
+ define void @test() "frame-pointer"="non-leaf" {
+ entry:
+ ret void
+ }
+
+ declare void @f()
+...
+---
+name: test
+body: |
+ ; CHECK-LABEL: name: test
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.1(0x30000000), %bb.2(0x50000000)
+ ; CHECK-NEXT: liveins: $w0, $w1, $lr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: CBZW renamable $w0, %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.3(0x80000000)
+ ; CHECK-NEXT: liveins: $w0, $w1, $lr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.3(0x80000000)
+ ; CHECK-NEXT: liveins: $w1, $lr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $w8 = MOVZWi 1, 0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: successors: %bb.5(0x30000000), %bb.4(0x50000000)
+ ; CHECK-NEXT: liveins: $w1, $w8, $lr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: frame-setup PAUTH_PROLOGUE implicit-def $lr, implicit killed $lr, implicit $sp
+ ; CHECK-NEXT: CBZW killed renamable $w1, %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.4:
+ ; CHECK-NEXT: successors: %bb.5(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: BL @f, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: BL @f, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp
+ ; CHECK-NEXT: frame-destroy PAUTH_EPILOGUE implicit-def $lr, implicit killed $lr, implicit $sp
+ ; CHECK-NEXT: TCRETURNdi @f, 0, csr_aarch64_aapcs, implicit $sp
+ bb.0.entry:
+ successors: %bb.1(0x30000000), %bb.2(0x50000000)
+ liveins: $w0, $w1, $lr
+
+ CBNZW renamable $w0, %bb.2
+
+ bb.1:
+ successors: %bb.3(0x80000000)
+ liveins: $w1, $lr
+
+ renamable $w8 = MOVZWi 1, 0
+ B %bb.3
+
+ bb.2:
+ successors: %bb.3(0x80000000)
+ liveins: $w0, $w1, $lr
+
+ bb.3:
+ successors: %bb.5(0x30000000), %bb.4(0x50000000)
+ liveins: $w1, $w8, $lr
+
+ frame-setup PAUTH_PROLOGUE implicit-def $lr, implicit killed $lr, implicit $sp
+ CBZW killed renamable $w1, %bb.5
+
+ bb.4:
+ successors: %bb.5(0x80000000)
+
+ BL @f, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp
+
+ bb.5:
+ BL @f, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp
+ frame-destroy PAUTH_EPILOGUE implicit-def $lr, implicit killed $lr, implicit $sp
+ TCRETURNdi @f, 0, csr_aarch64_aapcs, implicit $sp
+...
More information about the llvm-branch-commits
mailing list