r240179 - [Sanitizers] Provide better diagnostic for sanitizers unsupported for target triple.

Alexey Samsonov vonosmas at gmail.com
Fri Jun 19 14:36:47 PDT 2015


Author: samsonov
Date: Fri Jun 19 16:36:47 2015
New Revision: 240179

URL: http://llvm.org/viewvc/llvm-project?rev=240179&view=rev
Log:
[Sanitizers] Provide better diagnostic for sanitizers unsupported for target triple.

Introduce ToolChain::getSupportedSanitizers() that would return the set
of sanitizers available on given toolchain. By default, these are
sanitizers which don't necessarily require runtime support and are
not toolchain- or architecture-dependent.

Sanitizers (ASan, DFSan, TSan, MSan etc.) which cannot function
without runtime library are marked as supported only on platforms
for which we actually build these runtimes.

This would allow more fine-grained checks in the future: for instance,
we have to restrict availability of -fsanitize=vptr to Mac OS 10.9+
(PR23539).

Update test cases accrodingly: add tests for certain unsupported
configurations, remove test cases for -fsanitize=vptr + PS4
integration, as we don't build the runtime for PS4 at the moment.

This change was first submitted as r239953 and reverted in r239958.
The problem was and still is in Darwin toolchains, which get the
knowledge about target platform too late after initializaition, while
now we require this information when ToolChain::getSanitizerArgs() is
called. r240170 works around this issue.

Modified:
    cfe/trunk/include/clang/Driver/ToolChain.h
    cfe/trunk/lib/Driver/MSVCToolChain.cpp
    cfe/trunk/lib/Driver/SanitizerArgs.cpp
    cfe/trunk/lib/Driver/ToolChain.cpp
    cfe/trunk/lib/Driver/ToolChains.cpp
    cfe/trunk/lib/Driver/ToolChains.h
    cfe/trunk/test/Driver/fsanitize.c
    cfe/trunk/test/Driver/rtti-options.cpp

Modified: cfe/trunk/include/clang/Driver/ToolChain.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/ToolChain.h?rev=240179&r1=240178&r2=240179&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/ToolChain.h (original)
+++ cfe/trunk/include/clang/Driver/ToolChain.h Fri Jun 19 16:36:47 2015
@@ -10,6 +10,7 @@
 #ifndef LLVM_CLANG_DRIVER_TOOLCHAIN_H
 #define LLVM_CLANG_DRIVER_TOOLCHAIN_H
 
+#include "clang/Basic/Sanitizers.h"
 #include "clang/Driver/Action.h"
 #include "clang/Driver/Multilib.h"
 #include "clang/Driver/Types.h"
@@ -348,6 +349,9 @@ public:
   virtual bool
   AddFastMathRuntimeIfAvailable(const llvm::opt::ArgList &Args,
                                 llvm::opt::ArgStringList &CmdArgs) const;
+
+  /// \brief Return sanitizers which are available in this toolchain.
+  virtual SanitizerMask getSupportedSanitizers() const;
 };
 
 } // end namespace driver

Modified: cfe/trunk/lib/Driver/MSVCToolChain.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/MSVCToolChain.cpp?rev=240179&r1=240178&r2=240179&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/MSVCToolChain.cpp (original)
+++ cfe/trunk/lib/Driver/MSVCToolChain.cpp Fri Jun 19 16:36:47 2015
@@ -522,3 +522,12 @@ MSVCToolChain::ComputeEffectiveClangTrip
   }
   return Triple.getTriple();
 }
+
+SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers();
+  Res |= SanitizerKind::Address;
+  // CFI checks are not implemented for MSVC ABI for now.
+  Res &= ~SanitizerKind::CFI;
+  Res &= ~SanitizerKind::CFICastStrict;
+  return Res;
+}

Modified: cfe/trunk/lib/Driver/SanitizerArgs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/SanitizerArgs.cpp?rev=240179&r1=240178&r2=240179&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/SanitizerArgs.cpp (original)
+++ cfe/trunk/lib/Driver/SanitizerArgs.cpp Fri Jun 19 16:36:47 2015
@@ -77,27 +77,6 @@ static std::string describeSanitizeArg(c
 /// Sanitizers set.
 static std::string toString(const clang::SanitizerSet &Sanitizers);
 
-static SanitizerMask getToolchainUnsupportedKinds(const ToolChain &TC) {
-  bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD;
-  bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux;
-  bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86;
-  bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64;
-  bool IsMIPS64 = TC.getTriple().getArch() == llvm::Triple::mips64 ||
-                  TC.getTriple().getArch() == llvm::Triple::mips64el;
-
-  SanitizerMask Unsupported = 0;
-  if (!(IsLinux && (IsX86_64 || IsMIPS64))) {
-    Unsupported |= Memory | DataFlow;
-  }
-  if (!((IsLinux || IsFreeBSD) && (IsX86_64 || IsMIPS64))) {
-    Unsupported |= Thread;
-  }
-  if (!(IsLinux && (IsX86 || IsX86_64))) {
-    Unsupported |= Function;
-  }
-  return Unsupported;
-}
-
 static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
                                 std::string &BLPath) {
   const char *BlacklistFile = nullptr;
@@ -215,12 +194,12 @@ SanitizerArgs::SanitizerArgs(const ToolC
   SanitizerMask DiagnosedKinds = 0;  // All Kinds we have diagnosed up to now.
                                      // Used to deduplicate diagnostics.
   SanitizerMask Kinds = 0;
-  SanitizerMask NotSupported = getToolchainUnsupportedKinds(TC);
+  SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
   ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
 
   const Driver &D = TC.getDriver();
   SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
-  NotSupported |= TrappingKinds & NotAllowedWithTrap;
+  SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
 
   for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
        I != E; ++I) {
@@ -236,21 +215,20 @@ SanitizerArgs::SanitizerArgs(const ToolC
       // sanitizers in Add are those which have been explicitly enabled.
       // Diagnose them.
       if (SanitizerMask KindsToDiagnose =
-              Add & TrappingKinds & NotAllowedWithTrap & ~DiagnosedKinds) {
+              Add & InvalidTrappingKinds & ~DiagnosedKinds) {
         std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
         D.Diag(diag::err_drv_argument_not_allowed_with)
             << Desc << "-fsanitize-trap=undefined";
         DiagnosedKinds |= KindsToDiagnose;
-        Add &= ~KindsToDiagnose;
       }
-      if (SanitizerMask KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) {
-        // Only diagnose the new kinds.
+      Add &= ~InvalidTrappingKinds;
+      if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
         std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
         D.Diag(diag::err_drv_unsupported_opt_for_target)
             << Desc << TC.getTriple().str();
         DiagnosedKinds |= KindsToDiagnose;
       }
-      Add &= ~NotSupported;
+      Add &= Supported;
 
       // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
       // so we don't error out if -fno-rtti and -fsanitize=undefined were
@@ -279,7 +257,8 @@ SanitizerArgs::SanitizerArgs(const ToolC
       Add &= ~AllRemove;
       // Silently discard any unsupported sanitizers implicitly enabled through
       // group expansion.
-      Add &= ~NotSupported;
+      Add &= ~InvalidTrappingKinds;
+      Add &= Supported;
 
       Kinds |= Add;
     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {

Modified: cfe/trunk/lib/Driver/ToolChain.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChain.cpp?rev=240179&r1=240178&r2=240179&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChain.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChain.cpp Fri Jun 19 16:36:47 2015
@@ -481,3 +481,12 @@ bool ToolChain::AddFastMathRuntimeIfAvai
   CmdArgs.push_back(Args.MakeArgString(Path));
   return true;
 }
+
+SanitizerMask ToolChain::getSupportedSanitizers() const {
+  // Return sanitizers which don't require runtime support and are not
+  // platform or architecture-dependent.
+  using namespace SanitizerKind;
+  return (Undefined & ~Vptr & ~Function) | CFI | CFICastStrict |
+         UnsignedIntegerOverflow | LocalBounds;
+}
+

Modified: cfe/trunk/lib/Driver/ToolChains.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.cpp?rev=240179&r1=240178&r2=240179&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains.cpp Fri Jun 19 16:36:47 2015
@@ -379,26 +379,10 @@ void DarwinClang::AddLinkRuntimeLibArgs(
 
 
   const SanitizerArgs &Sanitize = getSanitizerArgs();
-
-  if (Sanitize.needsAsanRt()) {
-    if (!isTargetMacOS() && !isTargetIOSSimulator()) {
-      // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
-      getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
-          << "-fsanitize=address";
-    } else {
-      AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
-    }
-  }
-
-  if (Sanitize.needsUbsanRt()) {
-    if (!isTargetMacOS() && !isTargetIOSSimulator()) {
-      // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
-      getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
-          << "-fsanitize=undefined";
-    } else {
-      AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
-    }
-  }
+  if (Sanitize.needsAsanRt())
+    AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
+  if (Sanitize.needsUbsanRt())
+    AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
 
   // Otherwise link libSystem, then the dynamic runtime library, and finally any
   // target specific static runtime library.
@@ -1084,6 +1068,18 @@ void Darwin::CheckObjCARC() const {
   getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
 }
 
+SanitizerMask Darwin::getSupportedSanitizers() const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers();
+  if (isTargetMacOS() || isTargetIOSSimulator()) {
+    // ASan and UBSan are available on Mac OS and on iOS simulator.
+    Res |= SanitizerKind::Address;
+    Res |= SanitizerKind::Vptr;
+  }
+  if (isTargetMacOS())
+    Res |= SanitizerKind::SafeStack;
+  return Res;
+}
+
 /// Generic_GCC - A tool chain using the 'gcc' command to perform
 /// all subcommands; this relies on gcc translating the majority of
 /// command line options.
@@ -2724,6 +2720,24 @@ bool FreeBSD::isPIEDefault() const {
   return getSanitizerArgs().requiresPIE();
 }
 
+SanitizerMask FreeBSD::getSupportedSanitizers() const {
+  const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
+  const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
+  const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
+                        getTriple().getArch() == llvm::Triple::mips64el;
+  SanitizerMask Res = ToolChain::getSupportedSanitizers();
+  Res |= SanitizerKind::Address;
+  Res |= SanitizerKind::Vptr;
+  if (IsX86_64 || IsMIPS64) {
+    Res |= SanitizerKind::Leak;
+    Res |= SanitizerKind::Thread;
+  }
+  if (IsX86 || IsX86_64) {
+    Res |= SanitizerKind::SafeStack;
+  }
+  return Res;
+}
+
 /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
 
 NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
@@ -3628,6 +3642,28 @@ bool Linux::isPIEDefault() const {
   return getSanitizerArgs().requiresPIE();
 }
 
+SanitizerMask Linux::getSupportedSanitizers() const {
+  const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
+  const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
+  const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
+                        getTriple().getArch() == llvm::Triple::mips64el;
+  SanitizerMask Res = ToolChain::getSupportedSanitizers();
+  Res |= SanitizerKind::Address;
+  Res |= SanitizerKind::KernelAddress;
+  Res |= SanitizerKind::Vptr;
+  if (IsX86_64 || IsMIPS64) {
+    Res |= SanitizerKind::DataFlow;
+    Res |= SanitizerKind::Leak;
+    Res |= SanitizerKind::Memory;
+    Res |= SanitizerKind::Thread;
+  }
+  if (IsX86 || IsX86_64) {
+    Res |= SanitizerKind::Function;
+    Res |= SanitizerKind::SafeStack;
+  }
+  return Res;
+}
+
 /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
 
 DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)

Modified: cfe/trunk/lib/Driver/ToolChains.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=240179&r1=240178&r2=240179&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.h (original)
+++ cfe/trunk/lib/Driver/ToolChains.h Fri Jun 19 16:36:47 2015
@@ -463,6 +463,8 @@ public:
   void CheckObjCARC() const override;
 
   bool UseSjLjExceptions() const override;
+
+  SanitizerMask getSupportedSanitizers() const override;
 };
 
 /// DarwinClang - The Darwin toolchain used by Clang.
@@ -605,6 +607,7 @@ public:
 
   bool UseSjLjExceptions() const override;
   bool isPIEDefault() const override;
+  SanitizerMask getSupportedSanitizers() const override;
 protected:
   Tool *buildAssembler() const override;
   Tool *buildLinker() const override;
@@ -668,6 +671,7 @@ public:
   AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                                llvm::opt::ArgStringList &CC1Args) const override;
   bool isPIEDefault() const override;
+  SanitizerMask getSupportedSanitizers() const override;
 
   std::string Linker;
   std::vector<std::string> ExtraOpts;
@@ -798,6 +802,7 @@ public:
 
   std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
                                           types::ID InputType) const override;
+  SanitizerMask getSupportedSanitizers() const override;
 
 protected:
   void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,

Modified: cfe/trunk/test/Driver/fsanitize.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=240179&r1=240178&r2=240179&view=diff
==============================================================================
--- cfe/trunk/test/Driver/fsanitize.c (original)
+++ cfe/trunk/test/Driver/fsanitize.c Fri Jun 19 16:36:47 2015
@@ -13,6 +13,9 @@
 // RUN: %clang -target x86_64-apple-darwin10 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-DARWIN
 // CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}}
 
+// RUN: %clang -target i386-unknown-openbsd -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-OPENBSD
+// CHECK-UNDEFINED-OPENBSD: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}}
+
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER
 // CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent),?){5}"}}
 
@@ -202,6 +205,12 @@
 // RUN: %clang -target x86_64-apple-darwin10 -fsanitize=function -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSAN-UBSAN-DARWIN
 // CHECK-FSAN-UBSAN-DARWIN: unsupported option '-fsanitize=function' for target 'x86_64-apple-darwin10'
 
+// RUN: %clang -target armv7-apple-ios7 -miphoneos-version-min=7.0 -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-IOS
+// CHECK-ASAN-IOS: unsupported option '-fsanitize=address' for target 'arm-apple-ios7'
+
+// RUN: %clang -target i386-pc-openbsd -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-OPENBSD
+// CHECK-ASAN-OPENBSD: unsupported option '-fsanitize=address' for target 'i386-pc-openbsd'
+
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-derived-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-DCAST
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-unrelated-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-UCAST

Modified: cfe/trunk/test/Driver/rtti-options.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/rtti-options.cpp?rev=240179&r1=240178&r2=240179&view=diff
==============================================================================
--- cfe/trunk/test/Driver/rtti-options.cpp (original)
+++ cfe/trunk/test/Driver/rtti-options.cpp Fri Jun 19 16:36:47 2015
@@ -15,17 +15,12 @@
 // -fsanitize=vptr
 // Make sure we only error/warn once, when trying to enable vptr and
 // undefined and have -fno-rtti
-// RUN: %clang -### -c -fsanitize=undefined -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR -check-prefix=CHECK-OK %s
-
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-WARN %s
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
-// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=undefined %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
+// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
 
 // Exceptions + no/default rtti
 // RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-ERROR-CXX %s
@@ -51,7 +46,6 @@
 // RUN: %clang -### -c -target x86_64-unknown-unknown %s 2>&1 | FileCheck -check-prefix=CHECK-RTTI %s
 
 // CHECK-UNUSED: warning: argument unused during compilation: '-fcxx-exceptions'
-// CHECK-SAN-WARN: implicitly disabling vptr sanitizer because rtti wasn't enabled
 // CHECK-SAN-ERROR: invalid argument '-fsanitize=vptr' not allowed with '-fno-rtti'
 // CHECK-EXC-WARN: implicitly enabling rtti for exception handling
 // CHECK-EXC-ERROR: invalid argument '-fno-rtti' not allowed with '-fexceptions'





More information about the cfe-commits mailing list