[AArch64] Make width of stack protector guard value load configurable. (#195379) Certain embedded targets store the value of the stack protector global in an MMIO register, which requires a load of a specific width. Allow changing the backend to emit a 4-byte load for the value of the stack protector, instead of an 8-byte load. (Or vice versa for an ilp32 target.) The current version of the patch has a limitation: it still allocates a pointer-sized stack slot for the guard. This could be fixed in the future, if it becomes relevant. GitOrigin-RevId: 57fcde7df138c64793cf349bb97303e921f9c5f6
diff --git a/include/clang/Basic/CodeGenOptions.def b/include/clang/Basic/CodeGenOptions.def index fd0b6d9..aa36de6 100644 --- a/include/clang/Basic/CodeGenOptions.def +++ b/include/clang/Basic/CodeGenOptions.def
@@ -433,6 +433,9 @@ /// The default stack protector guard offset to use. VALUE_CODEGENOPT(StackProtectorGuardOffset, 32, INT_MAX, Benign) +/// The width to use for the stack protector guard value. +VALUE_CODEGENOPT(StackProtectorGuardValueWidth, 32, UINT_MAX, Benign) + /// Number of path components to strip when emitting checks. (0 == full /// filename) VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0, Benign)
diff --git a/include/clang/Options/Options.td b/include/clang/Options/Options.td index 0dc74ea..71ad4b7 100644 --- a/include/clang/Options/Options.td +++ b/include/clang/Options/Options.td
@@ -6082,6 +6082,15 @@ Visibility<[ClangOption, CC1Option]>, HelpText<"Use the given offset for addressing the stack-protector guard">, MarshallingInfoInt<CodeGenOpts<"StackProtectorGuardOffset">, "INT_MAX", "int">; +def mstack_protector_guard_value_width_EQ : Joined<["-"], "mstack-protector-guard-value-width=">, Group<m_Group>, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Use the given width for the value of the the stack-protector guard (AArch64-only)">, + MarshallingInfoInt<CodeGenOpts<"StackProtectorGuardValueWidth">, "UINT_MAX", "unsigned">, + DocBrief<[{Set the width of the stack-protector guard variable. By default, +the width is the same as the pointer width. Currently only supported on AArch64 +targets. Only the values "4" and "8" are currently supported. This currently +only modifies the size of accesses to the global variable, not the value +stored on the stack.}]>; def mstack_protector_guard_symbol_EQ : Joined<["-"], "mstack-protector-guard-symbol=">, Group<m_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Use the given symbol for addressing the stack-protector guard">,
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 416a5be..9ed67d9 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1716,6 +1716,9 @@ if (getCodeGenOpts().StackProtectorGuardOffset != INT_MAX) getModule().setStackProtectorGuardOffset( getCodeGenOpts().StackProtectorGuardOffset); + if (getCodeGenOpts().StackProtectorGuardValueWidth != UINT_MAX) + getModule().setStackProtectorGuardValueWidth( + getCodeGenOpts().StackProtectorGuardValueWidth); if (getCodeGenOpts().StackAlignment) getModule().setOverrideStackAlignment(getCodeGenOpts().StackAlignment); if (getCodeGenOpts().SkipRaxSetup)
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 92b3045..e411775 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp
@@ -3634,6 +3634,25 @@ } A->render(Args, CmdArgs); } + + if (Arg *A = + Args.getLastArg(options::OPT_mstack_protector_guard_value_width_EQ)) { + if (!EffectiveTriple.isAArch64()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getAsString(Args) << TripleStr; + StringRef Value = A->getValue(); + unsigned Width; + if (Value.getAsInteger(10, Width)) { + D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value; + return; + } + if (Width != 4 && Width != 8) { + D.Diag(diag::err_drv_invalid_int_value) + << A->getOption().getName() << Value; + return; + } + A->render(Args, CmdArgs); + } } static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args,
diff --git a/test/CodeGen/stack-protector-guard.c b/test/CodeGen/stack-protector-guard.c index 7bffa2a..5438671 100644 --- a/test/CodeGen/stack-protector-guard.c +++ b/test/CodeGen/stack-protector-guard.c
@@ -27,6 +27,8 @@ // 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-value-width=4 -triple aarch64-linux-gnu \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64-WIDTH-4 // 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 @@ -57,6 +59,9 @@ // AARCH64-FAR-EL2: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"far_el2"} // AARCH64: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 1024} +// AARCH64-WIDTH-4: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]]} +// AARCH64-WIDTH-4: [[ATTR1]] = !{i32 1, !"stack-protector-guard-value-width", i32 4} + // RISCV: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]], [[ATTR4:![0-9]+]]} // RISCV: [[ATTR1]] = !{i32 1, !"stack-protector-guard", !"tls"} // RISCV: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"tp"}