[clang] a19da87 - [ARM] implement support for TLS register based stack protector
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
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