[clang] a19da87 - [ARM] implement support for TLS register based stack protector

2021-11-09 Thread Ard Biesheuvel via cfe-commits

Author: Ard Biesheuvel
Date: 2021-11-09T18:19:47+01:00
New Revision: a19da876ab93d54ebc20aadd12820f74220d2f50

URL: 
https://github.com/llvm/llvm-project/commit/a19da876ab93d54ebc20aadd12820f74220d2f50
DIFF: 
https://github.com/llvm/llvm-project/commit/a19da876ab93d54ebc20aadd12820f74220d2f50.diff

LOG: [ARM] implement support for TLS register based stack protector

Implement support for loading the stack canary from a memory location held in
the TLS register, with an optional offset applied. This is used by the Linux
kernel to implement per-task stack canaries, which is impossible on SMP systems
when using a global variable for the stack canary.

Reviewed By: nickdesaulniers

Differential Revision: https://reviews.llvm.org/D112768

Added: 
llvm/test/CodeGen/ARM/stack-guard-tls.ll

Modified: 
clang/include/clang/Basic/DiagnosticCommonKinds.td
clang/include/clang/Basic/DiagnosticDriverKinds.td
clang/lib/Driver/ToolChains/Clang.cpp
clang/test/Driver/stack-protector-guard.c
llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
llvm/lib/Target/ARM/ARMInstrInfo.cpp
llvm/lib/Target/ARM/Thumb1InstrInfo.cpp
llvm/lib/Target/ARM/Thumb2InstrInfo.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td 
b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 1ed1c8cd9a19f..fe4ac5ed6cb03 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -298,6 +298,8 @@ def err_target_unsupported_unaligned : Error<
   "the %0 sub-architecture does not support unaligned accesses">;
 def err_target_unsupported_execute_only : Error<
   "execute only is not supported for the %0 sub-architecture">;
+def err_target_unsupported_tp_hard : Error<
+  "hardware TLS register is not supported for the %0 sub-architecture">;
 def err_target_unsupported_mcmse : Error<
   "-mcmse is not supported for %0">;
 def err_opt_not_valid_with_opt : Error<

diff  --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index fa464952189ba..8e7c14dc1549b 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -592,4 +592,7 @@ def err_cc1_round_trip_ok_then_fail : Error<
   "generated arguments parse failed in round-trip">;
 def err_cc1_round_trip_mismatch : Error<
   "generated arguments do not match in round-trip">;
+
+def err_drv_ssp_missing_offset_argument : Error<
+  "'%0' is used without '-mstack-protector-guard-offset', and there is no 
default">;
 }

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index dc20ae05ed419..e8ad105a78290 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3162,14 +3162,44 @@ static void RenderSSPOptions(const Driver &D, const 
ToolChain &TC,
   const std::string &TripleStr = EffectiveTriple.getTriple();
   if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) {
 StringRef Value = A->getValue();
-if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
+if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
+!EffectiveTriple.isARM() && !EffectiveTriple.isThumb())
   D.Diag(diag::err_drv_unsupported_opt_for_target)
   << A->getAsString(Args) << TripleStr;
-if (EffectiveTriple.isX86() && Value != "tls" && Value != "global") {
+if ((EffectiveTriple.isX86() || EffectiveTriple.isARM() ||
+ EffectiveTriple.isThumb()) &&
+Value != "tls" && Value != "global") {
   D.Diag(diag::err_drv_invalid_value_with_suggestion)
   << A->getOption().getName() << Value << "tls global";
   return;
 }
+if ((EffectiveTriple.isARM() || EffectiveTriple.isThumb()) &&
+Value == "tls") {
+  if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) {
+D.Diag(diag::err_drv_ssp_missing_offset_argument)
+<< A->getAsString(Args);
+return;
+  }
+  // Check whether the target subarch supports the hardware TLS register
+  if (arm::getARMSubArchVersionNumber(EffectiveTriple) < 7 &&
+  llvm::ARM::parseArch(EffectiveTriple.getArchName()) !=
+  llvm::ARM::ArchKind::ARMV6T2) {
+D.Diag(diag::err_target_unsupported_tp_hard)
+<< EffectiveTriple.getArchName();
+return;
+  }
+  // Check whether the user asked for something other than -mtp=cp15
+  if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
+StringRef Value = A->getValue();
+if (Value != "cp15") {
+  D.Diag(diag::err_drv_argument_not_allowed_with)
+  << A->getAsString(Args) << "-mstack-protector-guard=tls";
+  return;
+}
+  }
+  CmdArgs.push_back("-target-feature");
+  CmdArgs.push_back("+read-tp-hard");
+  

[clang] 2477272 - [ARM] reject -mtp=cp15 if target subarch does not support it

2021-11-09 Thread Ard Biesheuvel via cfe-commits

Author: Ard Biesheuvel
Date: 2021-11-09T18:29:30+01:00
New Revision: 24772720c54500714e2d48b9109bb62d5867ad95

URL: 
https://github.com/llvm/llvm-project/commit/24772720c54500714e2d48b9109bb62d5867ad95
DIFF: 
https://github.com/llvm/llvm-project/commit/24772720c54500714e2d48b9109bb62d5867ad95.diff

LOG: [ARM] reject -mtp=cp15 if target subarch does not support it

Currently, we permit -mtp=cp15 even for targets that don't implement the
TLS register. When building for ARMv6 or earlier, this means we emit
instructions that will UNDEF at runtime. For Thumb1, passing -mtp=cp15
will trigger an assert in the backend.

So let's add some diagnostics to ensure that -mtp=cp15 is only accepted
for ARMv6T2 or newer.

Reviewed By: nickdesaulniers

Differential Revision: https://reviews.llvm.org/D113026

Added: 


Modified: 
clang/lib/Driver/ToolChains/Arch/ARM.cpp
clang/lib/Driver/ToolChains/Arch/ARM.h
clang/test/Driver/clang-translation.c

Removed: 




diff  --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp 
b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 05d83c91ba0ef..21c091e1a0ba4 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -148,13 +148,21 @@ bool arm::useAAPCSForMachO(const llvm::Triple &T) {
 }
 
 // Select mode for reading thread pointer (-mtp=soft/cp15).
-arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args) {
+arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args,
+   const llvm::Triple &Triple) {
   if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
 arm::ReadTPMode ThreadPointer =
 llvm::StringSwitch(A->getValue())
 .Case("cp15", ReadTPMode::Cp15)
 .Case("soft", ReadTPMode::Soft)
 .Default(ReadTPMode::Invalid);
+if (ThreadPointer == ReadTPMode::Cp15 &&
+getARMSubArchVersionNumber(Triple) < 7 &&
+llvm::ARM::parseArch(Triple.getArchName()) !=
+llvm::ARM::ArchKind::ARMV6T2) {
+  D.Diag(diag::err_target_unsupported_tp_hard) << Triple.getArchName();
+  return ReadTPMode::Invalid;
+}
 if (ThreadPointer != ReadTPMode::Invalid)
   return ThreadPointer;
 if (StringRef(A->getValue()).empty())
@@ -422,7 +430,7 @@ void arm::getARMTargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
   bool KernelOrKext =
   Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
   arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
-  arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args);
+  arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args, Triple);
   llvm::Optional> WaCPU, WaFPU, WaHDiv,
   WaArch;
 

diff  --git a/clang/lib/Driver/ToolChains/Arch/ARM.h 
b/clang/lib/Driver/ToolChains/Arch/ARM.h
index 0ab0d6c281f80..b6fd68fbb9c62 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -53,7 +53,8 @@ FloatABI getARMFloatABI(const Driver &D, const llvm::Triple 
&Triple,
 const llvm::opt::ArgList &Args);
 void setFloatABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
  llvm::Triple &triple);
-ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args);
+ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
 void setArchNameInTriple(const Driver &D, const llvm::opt::ArgList &Args,
  types::ID InputType, llvm::Triple &Triple);
 

diff  --git a/clang/test/Driver/clang-translation.c 
b/clang/test/Driver/clang-translation.c
index 9802ee3da239f..230ea8e302024 100644
--- a/clang/test/Driver/clang-translation.c
+++ b/clang/test/Driver/clang-translation.c
@@ -110,15 +110,27 @@
 // ARMV5E: "-cc1"
 // ARMV5E: "-target-cpu" "arm1022e"
 
-// RUN: %clang -target arm-linux -mtp=cp15 -### -S %s -arch armv7 2>&1 | \
+// RUN: %clang -target armv7-linux -mtp=cp15 -### -S %s 2>&1 | \
 // RUN: FileCheck -check-prefix=ARMv7_THREAD_POINTER-HARD %s
 // ARMv7_THREAD_POINTER-HARD: "-target-feature" "+read-tp-hard"
 
-// RUN: %clang -target arm-linux -mtp=soft -### -S %s -arch armv7 2>&1 | \
+// RUN: %clang -target armv6t2-linux -mtp=cp15 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv6T2_THREAD_POINTER-HARD %s
+// ARMv6T2_THREAD_POINTER-HARD: "-target-feature" "+read-tp-hard"
+
+// RUN: %clang -target armv5t-linux -mtp=cp15 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv5_THREAD_POINTER_UNSUPP %s
+// ARMv5_THREAD_POINTER_UNSUPP: hardware TLS register is not supported for the 
armv5 sub-architecture
+
+// RUN: %clang -target thumbv6-linux -mtp=cp15 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv6_THREAD_POINTER_UNSUPP %s
+// ARMv6_THREAD_POINTER_UNSUPP: hardware TLS register is not supported for the 
armv6 sub-architecture
+
+// RUN: %clang -tar