Home | History | Annotate | Download | only in Instrumentation
      1 //===-- BlackList.cpp - blacklist for sanitizers --------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This is a utility class for instrumentation passes (like AddressSanitizer
     11 // or ThreadSanitizer) to avoid instrumenting some functions or global
     12 // variables based on a user-supplied blacklist.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #include "llvm/Transforms/Utils/BlackList.h"
     17 #include "llvm/ADT/OwningPtr.h"
     18 #include "llvm/ADT/SmallVector.h"
     19 #include "llvm/ADT/StringExtras.h"
     20 #include "llvm/IR/DerivedTypes.h"
     21 #include "llvm/IR/Function.h"
     22 #include "llvm/IR/GlobalVariable.h"
     23 #include "llvm/IR/Module.h"
     24 #include "llvm/Support/MemoryBuffer.h"
     25 #include "llvm/Support/Regex.h"
     26 #include "llvm/Support/raw_ostream.h"
     27 #include "llvm/Support/system_error.h"
     28 #include <string>
     29 #include <utility>
     30 
     31 namespace llvm {
     32 
     33 BlackList::BlackList(const StringRef Path) {
     34   // Validate and open blacklist file.
     35   if (Path.empty()) return;
     36   OwningPtr<MemoryBuffer> File;
     37   if (error_code EC = MemoryBuffer::getFile(Path, File)) {
     38     report_fatal_error("Can't open blacklist file: " + Path + ": " +
     39                        EC.message());
     40   }
     41 
     42   // Iterate through each line in the blacklist file.
     43   SmallVector<StringRef, 16> Lines;
     44   SplitString(File.take()->getBuffer(), Lines, "\n\r");
     45   StringMap<std::string> Regexps;
     46   for (SmallVector<StringRef, 16>::iterator I = Lines.begin(), E = Lines.end();
     47        I != E; ++I) {
     48     // Ignore empty lines and lines starting with "#"
     49     if (I->empty() || I->startswith("#"))
     50       continue;
     51     // Get our prefix and unparsed regexp.
     52     std::pair<StringRef, StringRef> SplitLine = I->split(":");
     53     StringRef Prefix = SplitLine.first;
     54     std::string Regexp = SplitLine.second;
     55     if (Regexp.empty()) {
     56       // Missing ':' in the line.
     57       report_fatal_error("malformed blacklist line: " + SplitLine.first);
     58     }
     59 
     60     // Replace * with .*
     61     for (size_t pos = 0; (pos = Regexp.find("*", pos)) != std::string::npos;
     62          pos += strlen(".*")) {
     63       Regexp.replace(pos, strlen("*"), ".*");
     64     }
     65 
     66     // Check that the regexp is valid.
     67     Regex CheckRE(Regexp);
     68     std::string Error;
     69     if (!CheckRE.isValid(Error)) {
     70       report_fatal_error("malformed blacklist regex: " + SplitLine.second +
     71           ": " + Error);
     72     }
     73 
     74     // Add this regexp into the proper group by its prefix.
     75     if (!Regexps[Prefix].empty())
     76       Regexps[Prefix] += "|";
     77     Regexps[Prefix] += Regexp;
     78   }
     79 
     80   // Iterate through each of the prefixes, and create Regexs for them.
     81   for (StringMap<std::string>::const_iterator I = Regexps.begin(),
     82        E = Regexps.end(); I != E; ++I) {
     83     Entries[I->getKey()] = new Regex(I->getValue());
     84   }
     85 }
     86 
     87 bool BlackList::isIn(const Function &F) const {
     88   return isIn(*F.getParent()) || inSection("fun", F.getName());
     89 }
     90 
     91 bool BlackList::isIn(const GlobalVariable &G) const {
     92   return isIn(*G.getParent()) || inSection("global", G.getName());
     93 }
     94 
     95 bool BlackList::isIn(const Module &M) const {
     96   return inSection("src", M.getModuleIdentifier());
     97 }
     98 
     99 static StringRef GetGVTypeString(const GlobalVariable &G) {
    100   // Types of GlobalVariables are always pointer types.
    101   Type *GType = G.getType()->getElementType();
    102   // For now we support blacklisting struct types only.
    103   if (StructType *SGType = dyn_cast<StructType>(GType)) {
    104     if (!SGType->isLiteral())
    105       return SGType->getName();
    106   }
    107   return "<unknown type>";
    108 }
    109 
    110 bool BlackList::isInInit(const GlobalVariable &G) const {
    111   return (isIn(*G.getParent()) ||
    112           inSection("global-init", G.getName()) ||
    113           inSection("global-init-type", GetGVTypeString(G)));
    114 }
    115 
    116 bool BlackList::inSection(const StringRef Section,
    117                           const StringRef Query) const {
    118   StringMap<Regex*>::const_iterator I = Entries.find(Section);
    119   if (I == Entries.end()) return false;
    120 
    121   Regex *FunctionRegex = I->getValue();
    122   return FunctionRegex->match(Query);
    123 }
    124 
    125 }  // namespace llvm
    126