1 //===-- SpecialCaseList.cpp - special case list for sanitizers ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This is a utility class for instrumentation passes (like AddressSanitizer
11 // or ThreadSanitizer) to avoid instrumenting some functions or global
12 // variables, or to instrument some functions or global variables in a specific
13 // way, based on a user-supplied list.
15 //===----------------------------------------------------------------------===//
17 #include "llvm/Transforms/Utils/SpecialCaseList.h"
18 #include "llvm/ADT/OwningPtr.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/IR/DerivedTypes.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/GlobalVariable.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/Support/MemoryBuffer.h"
27 #include "llvm/Support/Regex.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include "llvm/Support/system_error.h"
35 SpecialCaseList::SpecialCaseList(const StringRef Path) {
36 // Validate and open blacklist file.
37 if (Path.empty()) return;
38 OwningPtr<MemoryBuffer> File;
39 if (error_code EC = MemoryBuffer::getFile(Path, File)) {
40 report_fatal_error("Can't open blacklist file: " + Path + ": " +
47 SpecialCaseList::SpecialCaseList(const MemoryBuffer *MB) {
51 void SpecialCaseList::init(const MemoryBuffer *MB) {
52 // Iterate through each line in the blacklist file.
53 SmallVector<StringRef, 16> Lines;
54 SplitString(MB->getBuffer(), Lines, "\n\r");
55 StringMap<StringMap<std::string> > Regexps;
56 for (SmallVectorImpl<StringRef>::iterator I = Lines.begin(), E = Lines.end();
58 // Ignore empty lines and lines starting with "#"
59 if (I->empty() || I->startswith("#"))
61 // Get our prefix and unparsed regexp.
62 std::pair<StringRef, StringRef> SplitLine = I->split(":");
63 StringRef Prefix = SplitLine.first;
64 if (SplitLine.second.empty()) {
65 // Missing ':' in the line.
66 report_fatal_error("malformed blacklist line: " + SplitLine.first);
69 std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
70 std::string Regexp = SplitRegexp.first;
71 StringRef Category = SplitRegexp.second;
73 // Backwards compatibility.
74 if (Prefix == "global-init") {
77 } else if (Prefix == "global-init-type") {
80 } else if (Prefix == "global-init-src") {
86 for (size_t pos = 0; (pos = Regexp.find("*", pos)) != std::string::npos;
87 pos += strlen(".*")) {
88 Regexp.replace(pos, strlen("*"), ".*");
91 // Check that the regexp is valid.
92 Regex CheckRE(Regexp);
94 if (!CheckRE.isValid(Error)) {
95 report_fatal_error("malformed blacklist regex: " + SplitLine.second +
99 // Add this regexp into the proper group by its prefix.
100 if (!Regexps[Prefix][Category].empty())
101 Regexps[Prefix][Category] += "|";
102 Regexps[Prefix][Category] += "^" + Regexp + "$";
105 // Iterate through each of the prefixes, and create Regexs for them.
106 for (StringMap<StringMap<std::string> >::const_iterator I = Regexps.begin(),
109 for (StringMap<std::string>::const_iterator II = I->second.begin(),
110 IE = I->second.end();
112 Entries[I->getKey()][II->getKey()] = new Regex(II->getValue());
117 SpecialCaseList::~SpecialCaseList() {
118 for (StringMap<StringMap<Regex*> >::iterator I = Entries.begin(),
121 DeleteContainerSeconds(I->second);
125 bool SpecialCaseList::findCategory(const Function &F,
126 StringRef &Category) const {
127 return findCategory(*F.getParent(), Category) ||
128 findCategory("fun", F.getName(), Category);
131 bool SpecialCaseList::isIn(const Function& F, const StringRef Category) const {
132 return isIn(*F.getParent(), Category) ||
133 inSectionCategory("fun", F.getName(), Category);
136 static StringRef GetGVTypeString(const GlobalVariable &G) {
137 // Types of GlobalVariables are always pointer types.
138 Type *GType = G.getType()->getElementType();
139 // For now we support blacklisting struct types only.
140 if (StructType *SGType = dyn_cast<StructType>(GType)) {
141 if (!SGType->isLiteral())
142 return SGType->getName();
144 return "<unknown type>";
147 bool SpecialCaseList::findCategory(const GlobalVariable &G,
148 StringRef &Category) const {
149 return findCategory(*G.getParent(), Category) ||
150 findCategory("global", G.getName(), Category) ||
151 findCategory("type", GetGVTypeString(G), Category);
154 bool SpecialCaseList::isIn(const GlobalVariable &G,
155 const StringRef Category) const {
156 return isIn(*G.getParent(), Category) ||
157 inSectionCategory("global", G.getName(), Category) ||
158 inSectionCategory("type", GetGVTypeString(G), Category);
161 bool SpecialCaseList::findCategory(const Module &M, StringRef &Category) const {
162 return findCategory("src", M.getModuleIdentifier(), Category);
165 bool SpecialCaseList::isIn(const Module &M, const StringRef Category) const {
166 return inSectionCategory("src", M.getModuleIdentifier(), Category);
169 bool SpecialCaseList::findCategory(const StringRef Section,
170 const StringRef Query,
171 StringRef &Category) const {
172 StringMap<StringMap<Regex *> >::const_iterator I = Entries.find(Section);
173 if (I == Entries.end()) return false;
175 for (StringMap<Regex *>::const_iterator II = I->second.begin(),
176 IE = I->second.end();
178 Regex *FunctionRegex = II->getValue();
179 if (FunctionRegex->match(Query)) {
180 Category = II->first();
188 bool SpecialCaseList::inSectionCategory(const StringRef Section,
189 const StringRef Query,
190 const StringRef Category) const {
191 StringMap<StringMap<Regex *> >::const_iterator I = Entries.find(Section);
192 if (I == Entries.end()) return false;
193 StringMap<Regex *>::const_iterator II = I->second.find(Category);
194 if (II == I->second.end()) return false;
196 Regex *FunctionRegex = II->getValue();
197 return FunctionRegex->match(Query);