1243789Sdim//===-- BlackList.cpp - blacklist for sanitizers --------------------------===// 2243789Sdim// 3243789Sdim// The LLVM Compiler Infrastructure 4243789Sdim// 5243789Sdim// This file is distributed under the University of Illinois Open Source 6243789Sdim// License. See LICENSE.TXT for details. 7243789Sdim// 8243789Sdim//===----------------------------------------------------------------------===// 9243789Sdim// 10243789Sdim// This is a utility class for instrumentation passes (like AddressSanitizer 11243789Sdim// or ThreadSanitizer) to avoid instrumenting some functions or global 12243789Sdim// variables based on a user-supplied blacklist. 13243789Sdim// 14243789Sdim//===----------------------------------------------------------------------===// 15243789Sdim 16249423Sdim#include "llvm/Transforms/Utils/BlackList.h" 17243789Sdim#include "llvm/ADT/OwningPtr.h" 18243789Sdim#include "llvm/ADT/SmallVector.h" 19243789Sdim#include "llvm/ADT/StringExtras.h" 20249423Sdim#include "llvm/IR/DerivedTypes.h" 21249423Sdim#include "llvm/IR/Function.h" 22249423Sdim#include "llvm/IR/GlobalVariable.h" 23249423Sdim#include "llvm/IR/Module.h" 24243789Sdim#include "llvm/Support/MemoryBuffer.h" 25243789Sdim#include "llvm/Support/Regex.h" 26243789Sdim#include "llvm/Support/raw_ostream.h" 27243789Sdim#include "llvm/Support/system_error.h" 28249423Sdim#include <string> 29249423Sdim#include <utility> 30243789Sdim 31243789Sdimnamespace llvm { 32243789Sdim 33243789SdimBlackList::BlackList(const StringRef Path) { 34243789Sdim // Validate and open blacklist file. 35249423Sdim if (Path.empty()) return; 36243789Sdim OwningPtr<MemoryBuffer> File; 37243789Sdim if (error_code EC = MemoryBuffer::getFile(Path, File)) { 38243789Sdim report_fatal_error("Can't open blacklist file: " + Path + ": " + 39243789Sdim EC.message()); 40243789Sdim } 41243789Sdim 42243789Sdim // Iterate through each line in the blacklist file. 43243789Sdim SmallVector<StringRef, 16> Lines; 44243789Sdim SplitString(File.take()->getBuffer(), Lines, "\n\r"); 45243789Sdim StringMap<std::string> Regexps; 46243789Sdim for (SmallVector<StringRef, 16>::iterator I = Lines.begin(), E = Lines.end(); 47243789Sdim I != E; ++I) { 48243789Sdim // Ignore empty lines and lines starting with "#" 49243789Sdim if (I->empty() || I->startswith("#")) 50243789Sdim continue; 51243789Sdim // Get our prefix and unparsed regexp. 52243789Sdim std::pair<StringRef, StringRef> SplitLine = I->split(":"); 53243789Sdim StringRef Prefix = SplitLine.first; 54243789Sdim std::string Regexp = SplitLine.second; 55249423Sdim if (Regexp.empty()) { 56249423Sdim // Missing ':' in the line. 57249423Sdim report_fatal_error("malformed blacklist line: " + SplitLine.first); 58249423Sdim } 59243789Sdim 60243789Sdim // Replace * with .* 61243789Sdim for (size_t pos = 0; (pos = Regexp.find("*", pos)) != std::string::npos; 62243789Sdim pos += strlen(".*")) { 63243789Sdim Regexp.replace(pos, strlen("*"), ".*"); 64243789Sdim } 65243789Sdim 66243789Sdim // Check that the regexp is valid. 67243789Sdim Regex CheckRE(Regexp); 68243789Sdim std::string Error; 69243789Sdim if (!CheckRE.isValid(Error)) { 70243789Sdim report_fatal_error("malformed blacklist regex: " + SplitLine.second + 71243789Sdim ": " + Error); 72243789Sdim } 73243789Sdim 74243789Sdim // Add this regexp into the proper group by its prefix. 75249423Sdim if (!Regexps[Prefix].empty()) 76243789Sdim Regexps[Prefix] += "|"; 77243789Sdim Regexps[Prefix] += Regexp; 78243789Sdim } 79243789Sdim 80243789Sdim // Iterate through each of the prefixes, and create Regexs for them. 81249423Sdim for (StringMap<std::string>::const_iterator I = Regexps.begin(), 82249423Sdim E = Regexps.end(); I != E; ++I) { 83243789Sdim Entries[I->getKey()] = new Regex(I->getValue()); 84243789Sdim } 85243789Sdim} 86243789Sdim 87249423Sdimbool BlackList::isIn(const Function &F) const { 88243789Sdim return isIn(*F.getParent()) || inSection("fun", F.getName()); 89243789Sdim} 90243789Sdim 91249423Sdimbool BlackList::isIn(const GlobalVariable &G) const { 92243789Sdim return isIn(*G.getParent()) || inSection("global", G.getName()); 93243789Sdim} 94243789Sdim 95249423Sdimbool BlackList::isIn(const Module &M) const { 96243789Sdim return inSection("src", M.getModuleIdentifier()); 97243789Sdim} 98243789Sdim 99249423Sdimstatic StringRef GetGVTypeString(const GlobalVariable &G) { 100249423Sdim // Types of GlobalVariables are always pointer types. 101249423Sdim Type *GType = G.getType()->getElementType(); 102249423Sdim // For now we support blacklisting struct types only. 103249423Sdim if (StructType *SGType = dyn_cast<StructType>(GType)) { 104249423Sdim if (!SGType->isLiteral()) 105249423Sdim return SGType->getName(); 106249423Sdim } 107249423Sdim return "<unknown type>"; 108243789Sdim} 109243789Sdim 110249423Sdimbool BlackList::isInInit(const GlobalVariable &G) const { 111249423Sdim return (isIn(*G.getParent()) || 112249423Sdim inSection("global-init", G.getName()) || 113251662Sdim inSection("global-init-type", GetGVTypeString(G)) || 114251662Sdim inSection("global-init-src", G.getParent()->getModuleIdentifier())); 115249423Sdim} 116249423Sdim 117243789Sdimbool BlackList::inSection(const StringRef Section, 118249423Sdim const StringRef Query) const { 119249423Sdim StringMap<Regex*>::const_iterator I = Entries.find(Section); 120249423Sdim if (I == Entries.end()) return false; 121249423Sdim 122249423Sdim Regex *FunctionRegex = I->getValue(); 123249423Sdim return FunctionRegex->match(Query); 124243789Sdim} 125243789Sdim 126243789Sdim} // namespace llvm 127