From fb57f4e0e0b302ec1b3181e952a4bd4b3c57a286 Mon Sep 17 00:00:00 2001 From: Evgenii Stepanov Date: Tue, 21 Nov 2023 13:11:12 -0800 Subject: [PATCH] Allow multiple sanitizers on baremetal targets. (#72933) Baremetal targets tend to implement their own runtime support for sanitizers. Clang driver gatekeeping of allowed sanitizer types is counter productive. This change allows anything that does not crash and burn in compilation, and leaves any potential runtime issues for the user to figure out. --- clang/lib/Driver/ToolChains/BareMetal.cpp | 26 ++++++++++++ clang/lib/Driver/ToolChains/BareMetal.h | 1 + clang/test/Driver/fsanitize.c | 51 ++++++++++++++++++++++- 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index 842061c1e1488b..42c8336e626c7b 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -491,3 +491,29 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs, Output)); } + +// BareMetal toolchain allows all sanitizers where the compiler generates valid +// code, ignoring all runtime library support issues on the assumption that +// baremetal targets typically implement their own runtime support. +SanitizerMask BareMetal::getSupportedSanitizers() const { + const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; + const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 || + getTriple().getArch() == llvm::Triple::aarch64_be; + const bool IsRISCV64 = getTriple().getArch() == llvm::Triple::riscv64; + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + Res |= SanitizerKind::Address; + Res |= SanitizerKind::KernelAddress; + Res |= SanitizerKind::PointerCompare; + Res |= SanitizerKind::PointerSubtract; + Res |= SanitizerKind::Fuzzer; + Res |= SanitizerKind::FuzzerNoLink; + Res |= SanitizerKind::Vptr; + Res |= SanitizerKind::SafeStack; + Res |= SanitizerKind::Thread; + Res |= SanitizerKind::Scudo; + if (IsX86_64 || IsAArch64 || IsRISCV64) { + Res |= SanitizerKind::HWAddress; + Res |= SanitizerKind::KernelHWAddress; + } + return Res; +} diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h index f602ef2be3542f..67b5aa5998fc3d 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.h +++ b/clang/lib/Driver/ToolChains/BareMetal.h @@ -72,6 +72,7 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain { void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; std::string computeSysRoot() const override; + SanitizerMask getSupportedSanitizers() const override; private: using OrderedMultilibs = diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 9eb800b0d9e2c7..84a8e2b6b203dd 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -973,11 +973,58 @@ // RUN: not %clang --target=x86_64-sie-ps5 -fsanitize=kcfi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-KCFI // RUN: not %clang --target=x86_64-sie-ps5 -fsanitize=function -fsanitize=kcfi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-KCFI --check-prefix=CHECK-UBSAN-FUNCTION // RUN: %clang --target=x86_64-sie-ps5 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-UNDEFINED +// CHECK-UBSAN-UNDEFINED: "-fsanitize={{((alignment|array-bounds|bool|builtin|enum|float-cast-overflow|integer-divide-by-zero|nonnull-attribute|null|pointer-overflow|return|returns-nonnull-attribute|shift-base|shift-exponent|signed-integer-overflow|unreachable|vla-bound),?){17}"}} // RUN: not %clang --target=armv6t2-eabi -mexecute-only -fsanitize=function %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-FUNCTION // RUN: not %clang --target=armv6t2-eabi -mexecute-only -fsanitize=kcfi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-KCFI -// RUN: %clang --target=armv6t2-eabi -mexecute-only -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-UNDEFINED +// RUN: %clang --target=armv6t2-eabi -mexecute-only -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-UNDEFINED-VPTR // CHECK-UBSAN-KCFI-DAG: error: invalid argument '-fsanitize=kcfi' not allowed with {{('x86_64-sie-ps5'|'armv6t2-unknown-unknown-eabi')}} // CHECK-UBSAN-FUNCTION-DAG: error: invalid argument '-fsanitize=function' not allowed with {{('x86_64-sie-ps5'|'armv6t2-unknown-unknown-eabi')}} -// CHECK-UBSAN-UNDEFINED: "-fsanitize={{((alignment|array-bounds|bool|builtin|enum|float-cast-overflow|integer-divide-by-zero|nonnull-attribute|null|pointer-overflow|return|returns-nonnull-attribute|shift-base|shift-exponent|signed-integer-overflow|unreachable|vla-bound),?){17}"}} +// CHECK-UBSAN-UNDEFINED-VPTR: "-fsanitize={{((alignment|array-bounds|bool|builtin|enum|float-cast-overflow|integer-divide-by-zero|nonnull-attribute|null|pointer-overflow|return|returns-nonnull-attribute|shift-base|shift-exponent|signed-integer-overflow|unreachable|vla-bound|vptr),?){18}"}} + +// * Test BareMetal toolchain sanitizer support * + +// RUN: %clang --target=arm-arm-non-eabi -fsanitize=address %s -### 2>&1 | FileCheck %s -check-prefix=ADDRESS-BAREMETAL +// RUN: %clang --target=aarch64-none-elf -fsanitize=address %s -### 2>&1 | FileCheck %s -check-prefix=ADDRESS-BAREMETAL +// ADDRESS-BAREMETAL: "-fsanitize=address" + +// RUN: %clang --target=arm-arm-none-eabi -fsanitize=kernel-address %s -### 2>&1 | FileCheck %s -check-prefix=KERNEL-ADDRESS-BAREMETAL +// RUN: %clang --target=aarch64-none-elf -fsanitize=kernel-address %s -### 2>&1 | FileCheck %s -check-prefix=KERNEL-ADDRESS-BAREMETAL +// KERNEL-ADDRESS-BAREMETAL: "-fsanitize=kernel-address" + +// RUN: %clang --target=aarch64-none-elf -fsanitize=hwaddress %s -### 2>&1 | FileCheck %s -check-prefix=HWADDRESS-BAREMETAL +// HWADDRESS-BAREMETAL: "-fsanitize=hwaddress" + +// RUN: %clang --target=aarch64-none-elf -fsanitize=kernel-hwaddress %s -### 2>&1 | FileCheck %s -check-prefix=KERNEL-HWADDRESS-BAREMETAL +// KERNEL-HWADDRESS-BAREMETAL: "-fsanitize=kernel-hwaddress" + +// RUN: %clang --target=aarch64-none-elf -fsanitize=thread %s -### 2>&1 | FileCheck %s -check-prefix=THREAD-BAREMETAL +// THREAD-BAREMETAL: "-fsanitize=thread" + +// RUN: %clang --target=arm-arm-none-eabi -fsanitize=vptr %s -### 2>&1 | FileCheck %s -check-prefix=VPTR-BAREMETAL +// RUN: %clang --target=aarch64-none-elf -fsanitize=vptr %s -### 2>&1 | FileCheck %s -check-prefix=VPTR-BAREMETAL +// VPTR-BAREMETAL: "-fsanitize=vptr" + +// RUN: %clang --target=arm-arm-none-eabi -fsanitize=safe-stack %s -### 2>&1 | FileCheck %s -check-prefix=SAFESTACK-BAREMETAL +// RUN: %clang --target=aarch64-none-elf -fsanitize=safe-stack %s -### 2>&1 | FileCheck %s -check-prefix=SAFESTACK-BAREMETAL +// SAFESTACK-BAREMETAL: "-fsanitize=safe-stack" + +// RUN: %clang --target=arm-arm-none-eabi -fsanitize=undefined %s -### 2>&1 | FileCheck %s -check-prefix=UNDEFINED-BAREMETAL +// RUN: %clang --target=aarch64-none-elf -fsanitize=undefined %s -### 2>&1 | FileCheck %s -check-prefix=UNDEFINED-BAREMETAL +// UNDEFINED-BAREMETAL: "-fsanitize={{.*}} + +// RUN: %clang --target=arm-arm-none-eabi -fsanitize=scudo %s -### 2>&1 | FileCheck %s -check-prefix=SCUDO-BAREMETAL +// RUN: %clang --target=aarch64-none-elf -fsanitize=scudo %s -### 2>&1 | FileCheck %s -check-prefix=SCUDO-BAREMETAL +// SCUDO-BAREMETAL: "-fsanitize=scudo" + +// RUN: %clang --target=arm-arm-none-eabi -fsanitize=function %s -### 2>&1 | FileCheck %s -check-prefix=FUNCTION-BAREMETAL +// RUN: %clang --target=aarch64-none-elf -fsanitize=function %s -### 2>&1 | FileCheck %s -check-prefix=FUNCTION-BAREMETAL +// FUNCTION-BAREMETAL: "-fsanitize=function" + +// RUN: not %clang --target=aarch64-none-elf -fsanitize=memory %s -### 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-BAREMETAL +// RUN: not %clang --target=aarch64-none-elf -fsanitize=kernel-memory %s -### 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-BAREMETAL +// RUN: not %clang --target=aarch64-none-elf -fsanitize=leak %s -### 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-BAREMETAL +// RUN: not %clang --target=aarch64-none-elf -fsanitize=dataflow %s -### 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-BAREMETAL +// RUN: not %clang --target=arm-arm-none-eabi -fsanitize=shadow-call-stack %s -### 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-BAREMETAL +// UNSUPPORTED-BAREMETAL: unsupported option '-fsanitize={{.*}}' for target