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