[clang] 9a1ebae - [AARCH64] Support TPIDR_EL0 and TPIDRRO_EL0 as stack protector sysregs (#188054)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 25 08:57:18 PDT 2026
Author: Ard Biesheuvel
Date: 2026-03-25T08:57:12-07:00
New Revision: 9a1ebae0296b544a3b5a5f2bbaee8e8803427de9
URL: https://github.com/llvm/llvm-project/commit/9a1ebae0296b544a3b5a5f2bbaee8e8803427de9
DIFF: https://github.com/llvm/llvm-project/commit/9a1ebae0296b544a3b5a5f2bbaee8e8803427de9.diff
LOG: [AARCH64] Support TPIDR_EL0 and TPIDRRO_EL0 as stack protector sysregs (#188054)
Even though the command line option suggests that arbitrary system
registers may be chosen, the sysreg option for the stack protector guard
currently only permits SP_EL0, as this is what the Linux kernel uses.
While it makes no sense to permit arbitrary system registers here (which
usually have side effects), there is a desire to switch to TPIDR_EL0 or
TPIDRRO_EL0 from the Linux side, both of which are part of the base v8.0
AArch64 ISA, and can hold arbitrary 64-bit values without side effects.
So add TPIDR_EL0 and TPIDRRO_EL0 to the set of accepted arguments for
the -mstack-protected-guard-reg= command line option. For good measure,
add TPIDR_EL1, TPIDR_EL2, FAR_EL1 and FAR_EL2 as well, all of which
could potentially be useful to privileged software such as the Linux
kernel to stash a per-thread pointer to the stack protector guard value.
Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
Added:
Modified:
clang/lib/Driver/ToolChains/Clang.cpp
clang/test/CodeGen/stack-protector-guard.c
clang/test/Driver/stack-protector-guard.c
llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
Removed:
################################################################################
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 6416baf9126ff..d2dcc8a800766 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3588,8 +3588,15 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
<< A->getOption().getName() << Value << "fs gs";
return;
}
- if (EffectiveTriple.isAArch64() && Value != "sp_el0") {
- D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
+ if (EffectiveTriple.isAArch64() &&
+ llvm::StringSwitch<bool>(Value)
+ .Cases({"sp_el0", "tpidrro_el0", "tpidr_el0", "tpidr_el1",
+ "tpidr_el2", "far_el1", "far_el2"},
+ false)
+ .Default(true)) {
+ D.Diag(diag::err_drv_invalid_value_with_suggestion)
+ << A->getOption().getName() << Value
+ << "{sp_el0, tpidrro_el0, tpidr_el[012], far_el[12]}";
return;
}
if (EffectiveTriple.isRISCV() && Value != "tp") {
diff --git a/clang/test/CodeGen/stack-protector-guard.c b/clang/test/CodeGen/stack-protector-guard.c
index 0a4da13eed95c..7bffa2a1107a4 100644
--- a/clang/test/CodeGen/stack-protector-guard.c
+++ b/clang/test/CodeGen/stack-protector-guard.c
@@ -8,7 +8,25 @@
// RUN: -mstack-protector-guard-offset=1024 -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -mstack-protector-guard=sysreg -triple aarch64-linux-gnu \
// RUN: -mstack-protector-guard-offset=1024 -mstack-protector-guard-reg=sp_el0 \
-// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64
+// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64 --check-prefix=AARCH64-SP
+// RUN: %clang_cc1 -mstack-protector-guard=sysreg -triple aarch64-linux-gnu \
+// RUN: -mstack-protector-guard-offset=1024 -mstack-protector-guard-reg=tpidrro_el0 \
+// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64 --check-prefix=AARCH64-TPIDRRO
+// RUN: %clang_cc1 -mstack-protector-guard=sysreg -triple aarch64-linux-gnu \
+// RUN: -mstack-protector-guard-offset=1024 -mstack-protector-guard-reg=tpidr_el0 \
+// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64 --check-prefix=AARCH64-TPIDR-EL0
+// RUN: %clang_cc1 -mstack-protector-guard=sysreg -triple aarch64-linux-gnu \
+// RUN: -mstack-protector-guard-offset=1024 -mstack-protector-guard-reg=tpidr_el1 \
+// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64 --check-prefix=AARCH64-TPIDR-EL1
+// RUN: %clang_cc1 -mstack-protector-guard=sysreg -triple aarch64-linux-gnu \
+// RUN: -mstack-protector-guard-offset=1024 -mstack-protector-guard-reg=tpidr_el2 \
+// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64 --check-prefix=AARCH64-TPIDR-EL2
+// RUN: %clang_cc1 -mstack-protector-guard=sysreg -triple aarch64-linux-gnu \
+// RUN: -mstack-protector-guard-offset=1024 -mstack-protector-guard-reg=far_el1 \
+// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64 --check-prefix=AARCH64-FAR-EL1
+// RUN: %clang_cc1 -mstack-protector-guard=sysreg -triple aarch64-linux-gnu \
+// RUN: -mstack-protector-guard-offset=1024 -mstack-protector-guard-reg=far_el2 \
+// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64 --check-prefix=AARCH64-FAR-EL2
// RUN: %clang_cc1 -mstack-protector-guard=tls -triple riscv64-unknown-elf \
// RUN: -mstack-protector-guard-offset=44 -mstack-protector-guard-reg=tp \
// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=RISCV
@@ -30,7 +48,13 @@ void bar(int x) {
// AARCH64: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]]}
// AARCH64: [[ATTR1]] = !{i32 1, !"stack-protector-guard", !"sysreg"}
-// AARCH64: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"sp_el0"}
+// AARCH64-SP: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"sp_el0"}
+// AARCH64-TPIDRRO: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"tpidrro_el0"}
+// AARCH64-TPIDR-EL0: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"tpidr_el0"}
+// AARCH64-TPIDR-EL1: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"tpidr_el1"}
+// AARCH64-TPIDR-EL2: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"tpidr_el2"}
+// AARCH64-FAR-EL1: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"far_el1"}
+// AARCH64-FAR-EL2: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"far_el2"}
// AARCH64: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 1024}
// RISCV: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]], [[ATTR4:![0-9]+]]}
diff --git a/clang/test/Driver/stack-protector-guard.c b/clang/test/Driver/stack-protector-guard.c
index 666c83079e519..a31eeefa36ddd 100644
--- a/clang/test/Driver/stack-protector-guard.c
+++ b/clang/test/Driver/stack-protector-guard.c
@@ -81,10 +81,15 @@
// RUN: -mstack-protector-guard-reg=foo \
// RUN: -mstack-protector-guard-offset=0 %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-REG-AARCH64 %s
+// RUN: %clang -### -target aarch64-linux-gnu -mstack-protector-guard=sysreg \
+// RUN: -mstack-protector-guard-reg=tpidr_el0 \
+// RUN: -mstack-protector-guard-offset=0 %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-AARCH64-TPIDR %s
// CHECK-AARCH64: "-cc1" {{.*}}"-mstack-protector-guard=sysreg" "-mstack-protector-guard-offset=0" "-mstack-protector-guard-reg=sp_el0"
// INVALID-VALUE-AARCH64: error: invalid value 'tls' in 'mstack-protector-guard=', expected one of: sysreg global
-// INVALID-REG-AARCH64: error: invalid value 'foo' in 'mstack-protector-guard-reg='
+// INVALID-REG-AARCH64: error: invalid value 'foo' in 'mstack-protector-guard-reg=', expected one of: {sp_el0, tpidrro_el0, tpidr_el[012], far_el[12]}
+// CHECK-AARCH64-TPIDR: "-cc1" {{.*}}"-mstack-protector-guard=sysreg" "-mstack-protector-guard-offset=0" "-mstack-protector-guard-reg=tpidr_el0"
// RUN: %clang -### -target riscv64-unknown-elf -mstack-protector-guard=tls -mstack-protector-guard-offset=24 -mstack-protector-guard-reg=tp %s 2>&1 | \
// RUN: FileCheck -v -check-prefix=CHECK-TLS-RISCV %s
diff --git a/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll b/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
index 60e8823934d15..44bd696640113 100644
--- a/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
+++ b/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
@@ -10,19 +10,19 @@
; RUN: cat %t/main.ll %t/i.ll > %t/i2.ll
; RUN: cat %t/main.ll %t/j.ll > %t/j2.ll
; RUN: llc %t/a2.ll -verify-machineinstrs -o - | \
-; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NO-OFFSET %s
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-SP --check-prefix=CHECK-NO-OFFSET %s
; RUN: llc %t/b2.ll -verify-machineinstrs -o - | \
-; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-POSITIVE-OFFSET %s
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-TPIDRRO --check-prefix=CHECK-POSITIVE-OFFSET %s
; RUN: llc %t/c2.ll -verify-machineinstrs -o - | \
-; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NEGATIVE-OFFSET %s
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-TPIDR0 --check-prefix=CHECK-NEGATIVE-OFFSET %s
; RUN: llc %t/d2.ll -verify-machineinstrs -o - | \
-; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NPOT-OFFSET %s
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-TPIDR1 --check-prefix=CHECK-NPOT-OFFSET %s
; RUN: llc %t/e2.ll -verify-machineinstrs -o - | \
-; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NPOT-NEG-OFFSET %s
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-TPIDR2 --check-prefix=CHECK-NPOT-NEG-OFFSET %s
; RUN: llc %t/f2.ll -verify-machineinstrs -o - | \
-; RUN: FileCheck --check-prefix=CHECK-ADD --check-prefix=CHECK-257-OFFSET %s
+; RUN: FileCheck --check-prefix=CHECK-ADD --check-prefix=CHECK-FAR1 --check-prefix=CHECK-257-OFFSET %s
; RUN: llc %t/g2.ll -verify-machineinstrs -o - | \
-; RUN: FileCheck --check-prefix=CHECK-ADD --check-prefix=CHECK-MINUS-257-OFFSET %s
+; RUN: FileCheck --check-prefix=CHECK-ADD --check-prefix=CHECK-FAR2 --check-prefix=CHECK-MINUS-257-OFFSET %s
; XFAIL
; RUN: not --crash llc %t/h2.ll -o - 2>&1 | \
@@ -50,7 +50,11 @@ define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: .cfi_remember_state
; CHECK-NEXT: sub sp, sp, #16
-; CHECK-NEXT: mrs x8, SP_EL0
+; CHECK-SP: mrs x8, SP_EL0
+; CHECK-TPIDRRO: mrs x8, TPIDRRO_EL0
+; CHECK-TPIDR0: mrs x8, TPIDR_EL0
+; CHECK-TPIDR1: mrs x8, TPIDR_EL1
+; CHECK-TPIDR2: mrs x8, TPIDR_EL2
; CHECK-NEXT: lsl x9, x0, #2
; CHECK-NO-OFFSET: ldr x8, [x8]
; CHECK-POSITIVE-OFFSET: ldr x8, [x8, #8]
@@ -64,7 +68,11 @@ define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
; CHECK-NEXT sub x0, x8, x9
; CHECK-NEXT mov sp, x0
; CHECK-NEXT bl baz
-; CHECK-NEXT mrs x8, SP_EL0
+; CHECK-SP: mrs x8, SP_EL0
+; CHECK-TPIDRRO: mrs x8, TPIDRRO_EL0
+; CHECK-TPIDR0: mrs x8, TPIDR_EL0
+; CHECK-TPIDR1: mrs x8, TPIDR_EL1
+; CHECK-TPIDR2: mrs x8, TPIDR_EL2
; CHECK-NO-OFFSET: ldr x8, [x8]
; CHECK-POSITIVE-OFFSET: ldr x8, [x8, #8]
; CHECK-NEGATIVE-OFFSET: ldur x8, [x8, #-8]
@@ -99,7 +107,8 @@ define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
; CHECK-ADD-NEXT: .cfi_offset w29, -16
; CHECK-ADD-NEXT: .cfi_remember_state
; CHECK-ADD-NEXT: sub sp, sp, #16
-; CHECK-ADD-NEXT: mrs x8, SP_EL0
+; CHECK-FAR1: mrs x8, FAR_EL1
+; CHECK-FAR2: mrs x8, FAR_EL2
; CHECK-ADD-NEXT: lsl x9, x0, #2
; CHECK-MINUS-257-OFFSET: sub x8, x8, #257
; CHECK-257-OFFSET: add x8, x8, #257
@@ -111,7 +120,8 @@ define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
; CHECK-ADD-NEXT: sub x0, x8, x9
; CHECK-ADD-NEXT: mov sp, x0
; CHECK-ADD-NEXT: bl baz
-; CHECK-ADD-NEXT: mrs x8, SP_EL0
+; CHECK-FAR1: mrs x8, FAR_EL1
+; CHECK-FAR2: mrs x8, FAR_EL2
; CHECK-257-OFFSET: add x8, x8, #257
; CHECK-MINUS-257-OFFSET: sub x8, x8, #257
; CHECK-ADD-NEXT: ldr x8, [x8]
@@ -148,25 +158,34 @@ attributes #0 = { sspstrong uwtable }
!llvm.module.flags = !{!1, !2, !3}
!1 = !{i32 2, !"stack-protector-guard", !"sysreg"}
-!2 = !{i32 2, !"stack-protector-guard-reg", !"sp_el0"}
;--- a.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"sp_el0"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 0}
;--- b.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"tpidrro_el0"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 8}
;--- c.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"tpidr_el0"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 -8}
;--- d.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"tpidr_el1"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 1}
;--- e.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"tpidr_el2"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 -1}
;--- f.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"far_el1"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 257}
;--- g.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"far_el2"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 -257}
;--- h.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"sp_el0"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 32761}
;--- i.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"sp_el0"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 -4096}
;--- j.ll
+!2 = !{i32 2, !"stack-protector-guard-reg", !"sp_el0"}
!3 = !{i32 2, !"stack-protector-guard-offset", i32 4097}
More information about the cfe-commits
mailing list