Hi rsmith,

This patch adds flags -fsanitize-blacklist=<path> and
-fno-sanitize-blacklist to Clang and makes this flag usable for
ASan. Blacklisting can be used to disable
sanitizer checks for particular source file/function/object.
It is implemented in backend instrumentation passes for
ASan/TSan/MSan, so for these passes we may just "implement"
this flag by properly configuring passes in frontend.
This patch depends on refactoring of ASan pass options that
will be sent for review shortly.

http://llvm-reviews.chandlerc.com/D152

Files:
  test/Driver/fsanitize-blacklist.c
  include/clang/Frontend/CodeGenOptions.h
  include/clang/Driver/Options.td
  lib/Frontend/CompilerInvocation.cpp
  lib/Driver/Tools.cpp
  lib/Driver/SanitizerArgs.h
  lib/CodeGen/BackendUtil.cpp

Index: test/Driver/fsanitize-blacklist.c
===================================================================
--- /dev/null
+++ test/Driver/fsanitize-blacklist.c
@@ -0,0 +1,15 @@
+// General blacklist usage.
+// RUN: %clang -fsanitize=address -fsanitize-blacklist=%s %s -### 2>&1 | 
FileCheck %s --check-prefix=CHECK-BLACKLIST
+// CHECK-BLACKLIST: -fsanitize-blacklist
+
+// Ignore -fsanitize-blacklist flag if there is no -fsanitize flag.
+// RUN: %clang -fsanitize-blacklist=%s %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-NO-SANITIZE
+// CHECK-NO-SANITIZE-NOT: -fsanitize-blacklist
+
+// Flag -fno-sanitize-blacklist wins if it is specified later.
+// RUN: %clang -fsanitize=address -fsanitize-blacklist=%s 
-fno-sanitize-blacklist %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-NO-BLACKLIST
+// CHECK-NO-BLACKLIST-NOT: -fsanitize-blacklist
+
+// Driver barks on unexisting blacklist files.
+// RUN: %clang -fno-sanitize-blacklist -fsanitize-blacklist=unexisting.txt %s 
-### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SUCH-FILE
+// CHECK-NO-SUCH-FILE: error: no such file or directory: 'unexisting.txt'
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -105,6 +105,9 @@
   /// The name of the relocation model to use.
   std::string RelocationModel;
 
+  /// Path to blacklist file for sanitizers.
+  std::string SanitizerBlacklistFile;
+
   /// If not an empty string, trap intrinsics are lowered to calls to this
   /// function instead of to trap instructions.
   std::string TrapFuncName;
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -391,6 +391,12 @@
                             "address (memory errors) | thread (race detection) 
| "
                             "undefined (miscellaneous undefined behavior)">;
 def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, 
Group<f_clang_Group>;
+def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
+                          Group<f_clang_Group>, Flags<[CC1Option]>,
+                          HelpText<"Path to blacklist file for sanitizers">;
+def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">,
+                             Group<f_clang_Group>, Flags<[CC1Option]>,
+                             HelpText<"Don't use blacklist file for 
sanitizers">;
 def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">,
   Group<f_Group>;
 def fno_unsafe_math_optimizations : Flag<["-"], 
"fno-unsafe-math-optimizations">,
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -402,6 +402,7 @@
   Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
   Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
   Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
+  Opts.SanitizerBlacklistFile = Args.getLastArgValue(OPT_fsanitize_blacklist);
   Opts.SSPBufferSize =
     Args.getLastArgIntValue(OPT_stack_protector_buffer_size, 8, Diags);
   Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1481,6 +1481,19 @@
     D.Diag(diag::err_drv_argument_only_allowed_with)
       << lastArgumentForKind(D, Args, NeedsAsanRt)
       << "-fsanitize=address";
+
+  // Parse -f(no)sanitize-blacklist options.
+  if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist,
+                                   options::OPT_fno_sanitize_blacklist)) {
+    if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) {
+      std::string BLPath = BLArg->getValue();
+      bool BLExists = false;
+      if (!llvm::sys::fs::exists(BLPath, BLExists) && BLExists)
+        BlacklistFile = BLPath;
+      else
+        D.Diag(diag::err_drv_no_such_file) << BLPath;
+    }
+  }
 }
 
 /// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
Index: lib/Driver/SanitizerArgs.h
===================================================================
--- lib/Driver/SanitizerArgs.h
+++ lib/Driver/SanitizerArgs.h
@@ -33,9 +33,10 @@
     NeedsUbsanRt = (Undefined & ~Bounds) | Integer
   };
   unsigned Kind;
+  std::string BlacklistFile;
 
  public:
-  SanitizerArgs() : Kind(0) {}
+  SanitizerArgs() : Kind(0), BlacklistFile("") {}
   /// Parses the sanitizer arguments from an argument list.
   SanitizerArgs(const Driver &D, const ArgList &Args);
 
@@ -55,6 +56,11 @@
 #include "clang/Basic/Sanitizers.def"
     SanitizeOpt.pop_back();
     CmdArgs.push_back(Args.MakeArgString(SanitizeOpt));
+    if (!BlacklistFile.empty()) {
+      llvm::SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
+      BlacklistOpt += BlacklistFile;
+      CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
+    }
   }
 
  private:
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -139,10 +139,13 @@
 // we add to the PassManagerBuilder.
 class PassManagerBuilderWrapper : public PassManagerBuilder {
 public:
-  PassManagerBuilderWrapper(const LangOptions &LangOpts)
-      : PassManagerBuilder(), LangOpts(LangOpts) {}
+  PassManagerBuilderWrapper(const CodeGenOptions &CGOpts,
+                            const LangOptions &LangOpts)
+      : PassManagerBuilder(), CGOpts(CGOpts), LangOpts(LangOpts) {}
+  const CodeGenOptions &getCGOpts() const { return CGOpts; }
   const LangOptions &getLangOpts() const { return LangOpts; }
 private:
+  const CodeGenOptions &CGOpts;
   const LangOptions &LangOpts;
 };
 
@@ -172,11 +175,14 @@
                                       PassManagerBase &PM) {
   const PassManagerBuilderWrapper &BuilderWrapper =
       static_cast<const PassManagerBuilderWrapper&>(Builder);
+  const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
   const LangOptions &LangOpts = BuilderWrapper.getLangOpts();
-  PM.add(createAddressSanitizerFunctionPass(LangOpts.SanitizeInitOrder,
-                                            LangOpts.SanitizeUseAfterReturn,
-                                            LangOpts.SanitizeUseAfterScope));
-  PM.add(createAddressSanitizerModulePass(LangOpts.SanitizeInitOrder));
+  AddressSanitizerOptions AsanOpts(LangOpts.SanitizeInitOrder,
+                                   LangOpts.SanitizeUseAfterReturn,
+                                   LangOpts.SanitizeUseAfterScope,
+                                   CGOpts.SanitizerBlacklistFile);
+  PM.add(createAddressSanitizerFunctionPass(AsanOpts));
+  PM.add(createAddressSanitizerModulePass(AsanOpts));
 }
 
 static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
@@ -195,7 +201,7 @@
     Inlining = CodeGenOpts.NoInlining;
   }
 
-  PassManagerBuilderWrapper PMBuilder(LangOpts);
+  PassManagerBuilderWrapper PMBuilder(CodeGenOpts, LangOpts);
   PMBuilder.OptLevel = OptLevel;
   PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
Index: test/Driver/fsanitize-blacklist.c
===================================================================
--- /dev/null
+++ test/Driver/fsanitize-blacklist.c
@@ -0,0 +1,15 @@
+// General blacklist usage.
+// RUN: %clang -fsanitize=address -fsanitize-blacklist=%s %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-BLACKLIST
+// CHECK-BLACKLIST: -fsanitize-blacklist
+
+// Ignore -fsanitize-blacklist flag if there is no -fsanitize flag.
+// RUN: %clang -fsanitize-blacklist=%s %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SANITIZE
+// CHECK-NO-SANITIZE-NOT: -fsanitize-blacklist
+
+// Flag -fno-sanitize-blacklist wins if it is specified later.
+// RUN: %clang -fsanitize=address -fsanitize-blacklist=%s -fno-sanitize-blacklist %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-BLACKLIST
+// CHECK-NO-BLACKLIST-NOT: -fsanitize-blacklist
+
+// Driver barks on unexisting blacklist files.
+// RUN: %clang -fno-sanitize-blacklist -fsanitize-blacklist=unexisting.txt %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SUCH-FILE
+// CHECK-NO-SUCH-FILE: error: no such file or directory: 'unexisting.txt'
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -105,6 +105,9 @@
   /// The name of the relocation model to use.
   std::string RelocationModel;
 
+  /// Path to blacklist file for sanitizers.
+  std::string SanitizerBlacklistFile;
+
   /// If not an empty string, trap intrinsics are lowered to calls to this
   /// function instead of to trap instructions.
   std::string TrapFuncName;
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -391,6 +391,12 @@
                             "address (memory errors) | thread (race detection) | "
                             "undefined (miscellaneous undefined behavior)">;
 def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>;
+def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
+                          Group<f_clang_Group>, Flags<[CC1Option]>,
+                          HelpText<"Path to blacklist file for sanitizers">;
+def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">,
+                             Group<f_clang_Group>, Flags<[CC1Option]>,
+                             HelpText<"Don't use blacklist file for sanitizers">;
 def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">,
   Group<f_Group>;
 def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">,
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -402,6 +402,7 @@
   Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
   Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
   Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
+  Opts.SanitizerBlacklistFile = Args.getLastArgValue(OPT_fsanitize_blacklist);
   Opts.SSPBufferSize =
     Args.getLastArgIntValue(OPT_stack_protector_buffer_size, 8, Diags);
   Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1481,6 +1481,19 @@
     D.Diag(diag::err_drv_argument_only_allowed_with)
       << lastArgumentForKind(D, Args, NeedsAsanRt)
       << "-fsanitize=address";
+
+  // Parse -f(no)sanitize-blacklist options.
+  if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist,
+                                   options::OPT_fno_sanitize_blacklist)) {
+    if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) {
+      std::string BLPath = BLArg->getValue();
+      bool BLExists = false;
+      if (!llvm::sys::fs::exists(BLPath, BLExists) && BLExists)
+        BlacklistFile = BLPath;
+      else
+        D.Diag(diag::err_drv_no_such_file) << BLPath;
+    }
+  }
 }
 
 /// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
Index: lib/Driver/SanitizerArgs.h
===================================================================
--- lib/Driver/SanitizerArgs.h
+++ lib/Driver/SanitizerArgs.h
@@ -33,9 +33,10 @@
     NeedsUbsanRt = (Undefined & ~Bounds) | Integer
   };
   unsigned Kind;
+  std::string BlacklistFile;
 
  public:
-  SanitizerArgs() : Kind(0) {}
+  SanitizerArgs() : Kind(0), BlacklistFile("") {}
   /// Parses the sanitizer arguments from an argument list.
   SanitizerArgs(const Driver &D, const ArgList &Args);
 
@@ -55,6 +56,11 @@
 #include "clang/Basic/Sanitizers.def"
     SanitizeOpt.pop_back();
     CmdArgs.push_back(Args.MakeArgString(SanitizeOpt));
+    if (!BlacklistFile.empty()) {
+      llvm::SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
+      BlacklistOpt += BlacklistFile;
+      CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
+    }
   }
 
  private:
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -139,10 +139,13 @@
 // we add to the PassManagerBuilder.
 class PassManagerBuilderWrapper : public PassManagerBuilder {
 public:
-  PassManagerBuilderWrapper(const LangOptions &LangOpts)
-      : PassManagerBuilder(), LangOpts(LangOpts) {}
+  PassManagerBuilderWrapper(const CodeGenOptions &CGOpts,
+                            const LangOptions &LangOpts)
+      : PassManagerBuilder(), CGOpts(CGOpts), LangOpts(LangOpts) {}
+  const CodeGenOptions &getCGOpts() const { return CGOpts; }
   const LangOptions &getLangOpts() const { return LangOpts; }
 private:
+  const CodeGenOptions &CGOpts;
   const LangOptions &LangOpts;
 };
 
@@ -172,11 +175,14 @@
                                       PassManagerBase &PM) {
   const PassManagerBuilderWrapper &BuilderWrapper =
       static_cast<const PassManagerBuilderWrapper&>(Builder);
+  const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
   const LangOptions &LangOpts = BuilderWrapper.getLangOpts();
-  PM.add(createAddressSanitizerFunctionPass(LangOpts.SanitizeInitOrder,
-                                            LangOpts.SanitizeUseAfterReturn,
-                                            LangOpts.SanitizeUseAfterScope));
-  PM.add(createAddressSanitizerModulePass(LangOpts.SanitizeInitOrder));
+  AddressSanitizerOptions AsanOpts(LangOpts.SanitizeInitOrder,
+                                   LangOpts.SanitizeUseAfterReturn,
+                                   LangOpts.SanitizeUseAfterScope,
+                                   CGOpts.SanitizerBlacklistFile);
+  PM.add(createAddressSanitizerFunctionPass(AsanOpts));
+  PM.add(createAddressSanitizerModulePass(AsanOpts));
 }
 
 static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
@@ -195,7 +201,7 @@
     Inlining = CodeGenOpts.NoInlining;
   }
 
-  PassManagerBuilderWrapper PMBuilder(LangOpts);
+  PassManagerBuilderWrapper PMBuilder(CodeGenOpts, LangOpts);
   PMBuilder.OptLevel = OptLevel;
   PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to