[asan/tsan] extend the functionality of FunctionBlackList to globals and modules...
authorKostya Serebryany <kcc@google.com>
Fri, 24 Aug 2012 16:40:11 +0000 (16:40 +0000)
committerKostya Serebryany <kcc@google.com>
Fri, 24 Aug 2012 16:40:11 +0000 (16:40 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162565 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Instrumentation/FunctionBlackList.cpp
lib/Transforms/Instrumentation/FunctionBlackList.h

index 188ea4d9b3cbf5e04b6703f82de6d0bea82f69d9..b6f6060f39903658b69002af41efd4e7db117b88 100644 (file)
@@ -1,4 +1,4 @@
-//===-- FunctionBlackList.cpp - blacklist of functions --------------------===//
+//===-- FunctionBlackList.cpp - blacklist for sanitizers -----------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,17 +7,22 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This is a utility class for instrumentation passes (like AddressSanitizer 
-// or ThreadSanitizer) to avoid instrumenting some functions based on
-// user-supplied blacklist.
+// This is a utility class for instrumentation passes (like AddressSanitizer
+// or ThreadSanitizer) to avoid instrumenting some functions or global
+// variables based on a user-supplied blacklist.
 //
 //===----------------------------------------------------------------------===//
 
+#include <utility>
+#include <string>
+
 #include "FunctionBlackList.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Module.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace llvm {
 
-FunctionBlackList::FunctionBlackList(const std::string &Path) {
-  Functions = NULL;
-  const char *kFunPrefix = "fun:";
+FunctionBlackList::FunctionBlackList(const StringRef Path) {
+  // Validate and open blacklist file.
   if (!Path.size()) return;
-  std::string Fun;
-
   OwningPtr<MemoryBuffer> File;
-  if (error_code EC = MemoryBuffer::getFile(Path.c_str(), File)) {
-    report_fatal_error("Can't open blacklist file " + Path + ": " +
+  if (error_code EC = MemoryBuffer::getFile(Path, File)) {
+    report_fatal_error("Can't open blacklist file: " + Path + ": " +
                        EC.message());
   }
-  MemoryBuffer *Buff = File.take();
-  const char *Data = Buff->getBufferStart();
-  size_t DataLen = Buff->getBufferSize();
+
+  // Iterate through each line in the blacklist file.
   SmallVector<StringRef, 16> Lines;
-  SplitString(StringRef(Data, DataLen), Lines, "\n\r");
-  for (size_t i = 0, numLines = Lines.size(); i < numLines; i++) {
-    if (Lines[i].startswith(kFunPrefix)) {
-      std::string ThisFunc = Lines[i].substr(strlen(kFunPrefix));
-      std::string ThisFuncRE;
-      // add ThisFunc replacing * with .*
-      for (size_t j = 0, n = ThisFunc.size(); j < n; j++) {
-        if (ThisFunc[j] == '*')
-          ThisFuncRE += '.';
-        ThisFuncRE += ThisFunc[j];
-      }
-      // Check that the regexp is valid.
-      Regex CheckRE(ThisFuncRE);
-      std::string Error;
-      if (!CheckRE.isValid(Error))
-        report_fatal_error("malformed blacklist regex: " + ThisFunc +
-                           ": " + Error);
-      // Append to the final regexp.
-      if (Fun.size())
-        Fun += "|";
-      Fun += ThisFuncRE;
+  SplitString(File.take()->getBuffer(), Lines, "\n\r");
+  StringMap<std::string> Regexps;
+  for (SmallVector<StringRef, 16>::iterator I = Lines.begin(), E = Lines.end();
+       I != E; ++I) {
+    // Get our prefix and unparsed regexp.
+    std::pair<StringRef, StringRef> SplitLine = I->split(":");
+    StringRef Prefix = SplitLine.first;
+    std::string Regexp = SplitLine.second;
+
+    // Replace * with .*
+    for (size_t pos = 0; (pos = Regexp.find("*", pos)) != std::string::npos;
+         pos += strlen(".*")) {
+      Regexp.replace(pos, strlen("*"), ".*");
     }
+
+    // Check that the regexp is valid.
+    Regex CheckRE(Regexp);
+    std::string Error;
+    if (!CheckRE.isValid(Error)) {
+      report_fatal_error("malformed blacklist regex: " + SplitLine.second +
+          ": " + Error);
+    }
+
+    // Add this regexp into the proper group by its prefix.
+    if (Regexps[Prefix].size())
+      Regexps[Prefix] += "|";
+    Regexps[Prefix] += Regexp;
   }
-  if (Fun.size()) {
-    Functions = new Regex(Fun);
+
+  // Iterate through each of the prefixes, and create Regexs for them.
+  for (StringMap<std::string>::iterator I = Regexps.begin(), E = Regexps.end();
+       I != E; ++I) {
+    Entries[I->getKey()] = new Regex(I->getValue());
   }
 }
 
 bool FunctionBlackList::isIn(const Function &F) {
-  if (Functions) {
-    bool Res = Functions->match(F.getName());
-    return Res;
-  }
-  return false;
+  return isIn(*F.getParent()) || inSection("fun", F.getName());
+}
+
+bool FunctionBlackList::isIn(const GlobalVariable &G) {
+  return isIn(*G.getParent()) || inSection("global", G.getName());
+}
+
+bool FunctionBlackList::isIn(const Module &M) {
+  return inSection("src", M.getModuleIdentifier());
+}
+
+bool FunctionBlackList::inSection(const StringRef Section,
+                                  const StringRef Query) {
+  Regex *FunctionRegex = Entries[Section];
+  return FunctionRegex ? FunctionRegex->match(Query) : false;
 }
 
 }  // namespace llvm
index c1239b9b7e0dc7c60d1fba0b1b096f036155b483..52f2dbd4f61040c6c85877fb23db22ab538154c6 100644 (file)
@@ -1,4 +1,4 @@
-//===-- FunctionBlackList.cpp - blacklist of functions ----------*- C++ -*-===//
+//===-- FunctionBlackList.h - blacklist for sanitizers ----------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,31 +7,46 @@
 //===----------------------------------------------------------------------===//
 //
 // This is a utility class for instrumentation passes (like AddressSanitizer
-// or ThreadSanitizer) to avoid instrumenting some functions based on
-// user-supplied blacklist.
+// or ThreadSanitizer) to avoid instrumenting some functions or global
+// variables based on a user-supplied blacklist.
+//
+// The blacklist disables instrumentation of various functions and global
+// variables.  Each line contains a prefix, followed by a wild card expression.
+// ---
+// fun:*_ZN4base6subtle*
+// global:*global_with_initialization_problems*
+// src:file_with_tricky_code.cc
+// ---
+// Note that the wild card is in fact an llvm::Regex, but * is automatically
+// replaced with .*
+// This is similar to the "ignore" feature of ThreadSanitizer.
+// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores
 //
 //===----------------------------------------------------------------------===//
 //
 
-#include <string>
+#include "llvm/ADT/StringMap.h"
 
 namespace llvm {
 class Function;
+class GlobalVariable;
+class Module;
 class Regex;
+class StringRef;
 
-// Blacklisted functions are not instrumented.
-// The blacklist file contains one or more lines like this:
-// ---
-// fun:FunctionWildCard
-// ---
-// This is similar to the "ignore" feature of ThreadSanitizer.
-// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores
 class FunctionBlackList {
  public:
-  FunctionBlackList(const std::string &Path);
+  FunctionBlackList(const StringRef Path);
+  // Returns whether either this function or it's source file are blacklisted.
   bool isIn(const Function &F);
+  // Returns whether either this global or it's source file are blacklisted.
+  bool isIn(const GlobalVariable &G);
+  // Returns whether this module is blacklisted by filename.
+  bool isIn(const Module &M);
  private:
-  Regex *Functions;
+  StringMap<Regex*> Entries;
+
+  bool inSection(const StringRef Section, const StringRef Query);
 };
 
 }  // namespace llvm