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 31namespace llvm { 32 33BlackList::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 87bool BlackList::isIn(const Function &F) const { 88 return isIn(*F.getParent()) || inSection("fun", F.getName()); 89} 90 91bool BlackList::isIn(const GlobalVariable &G) const { 92 return isIn(*G.getParent()) || inSection("global", G.getName()); 93} 94 95bool BlackList::isIn(const Module &M) const { 96 return inSection("src", M.getModuleIdentifier()); 97} 98 99static 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 110bool 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 inSection("global-init-src", G.getParent()->getModuleIdentifier())); 115} 116 117bool BlackList::inSection(const StringRef Section, 118 const StringRef Query) const { 119 StringMap<Regex*>::const_iterator I = Entries.find(Section); 120 if (I == Entries.end()) return false; 121 122 Regex *FunctionRegex = I->getValue(); 123 return FunctionRegex->match(Query); 124} 125 126} // namespace llvm 127