https://github.com/ardbiesheuvel updated https://github.com/llvm/llvm-project/pull/188054
>From a9635ba735d3ae90bf2dd97b2af4652d79a769d9 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel <[email protected]> Date: Mon, 23 Mar 2026 15:38:52 +0100 Subject: [PATCH] [AARCH64] Support TPIDR_EL0 and TPIDRRO_EL0 as stack protector sysregs 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 <[email protected]> --- clang/lib/Driver/ToolChains/Clang.cpp | 11 +++++++-- clang/test/CodeGen/stack-protector-guard.c | 28 ++++++++++++++++++++-- clang/test/Driver/stack-protector-guard.c | 7 +++++- 3 files changed, 41 insertions(+), 5 deletions(-) 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
