LLVM  4.0.0
SpecialCaseList.cpp
Go to the documentation of this file.
1 //===-- SpecialCaseList.cpp - special case list 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, or to instrument some functions or global variables in a specific
13 // way, based on a user-supplied list.
14 //
15 //===----------------------------------------------------------------------===//
16 
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/StringSet.h"
23 #include "llvm/Support/Regex.h"
24 #include <string>
25 #include <system_error>
26 #include <utility>
27 
28 namespace llvm {
29 
30 /// Represents a set of regular expressions. Regular expressions which are
31 /// "literal" (i.e. no regex metacharacters) are stored in Strings, while all
32 /// others are represented as a single pipe-separated regex in RegEx. The
33 /// reason for doing so is efficiency; StringSet is much faster at matching
34 /// literal strings than Regex.
38  std::unique_ptr<Regex> RegEx;
39 
40  bool match(StringRef Query) const {
41  if (Strings.count(Query))
42  return true;
43  if (Trigrams.isDefinitelyOut(Query))
44  return false;
45  return RegEx && RegEx->match(Query);
46  }
47 };
48 
49 SpecialCaseList::SpecialCaseList() : Entries(), Regexps(), IsCompiled(false) {}
50 
51 std::unique_ptr<SpecialCaseList>
52 SpecialCaseList::create(const std::vector<std::string> &Paths,
53  std::string &Error) {
54  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
55  for (const auto &Path : Paths) {
58  if (std::error_code EC = FileOrErr.getError()) {
59  Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
60  return nullptr;
61  }
62  std::string ParseError;
63  if (!SCL->parse(FileOrErr.get().get(), ParseError)) {
64  Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
65  return nullptr;
66  }
67  }
68  SCL->compile();
69  return SCL;
70 }
71 
72 std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
73  std::string &Error) {
74  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
75  if (!SCL->parse(MB, Error))
76  return nullptr;
77  SCL->compile();
78  return SCL;
79 }
80 
81 std::unique_ptr<SpecialCaseList>
82 SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
83  std::string Error;
84  if (auto SCL = create(Paths, Error))
85  return SCL;
86  report_fatal_error(Error);
87 }
88 
89 bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
90  // Iterate through each line in the blacklist file.
92  SplitString(MB->getBuffer(), Lines, "\n\r");
93  int LineNo = 1;
94  for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
95  // Ignore empty lines and lines starting with "#"
96  if (I->empty() || I->startswith("#"))
97  continue;
98  // Get our prefix and unparsed regexp.
99  std::pair<StringRef, StringRef> SplitLine = I->split(":");
100  StringRef Prefix = SplitLine.first;
101  if (SplitLine.second.empty()) {
102  // Missing ':' in the line.
103  Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
104  SplitLine.first + "'").str();
105  return false;
106  }
107 
108  std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
109  std::string Regexp = SplitRegexp.first;
110  StringRef Category = SplitRegexp.second;
111 
112  // See if we can store Regexp in Strings.
113  auto &Entry = Entries[Prefix][Category];
114  if (Regex::isLiteralERE(Regexp)) {
115  Entry.Strings.insert(Regexp);
116  continue;
117  }
118  Entry.Trigrams.insert(Regexp);
119 
120  // Replace * with .*
121  for (size_t pos = 0; (pos = Regexp.find('*', pos)) != std::string::npos;
122  pos += strlen(".*")) {
123  Regexp.replace(pos, strlen("*"), ".*");
124  }
125 
126  // Check that the regexp is valid.
127  Regex CheckRE(Regexp);
128  std::string REError;
129  if (!CheckRE.isValid(REError)) {
130  Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
131  SplitLine.second + "': " + REError).str();
132  return false;
133  }
134 
135  // Add this regexp into the proper group by its prefix.
136  if (!Regexps[Prefix][Category].empty())
137  Regexps[Prefix][Category] += "|";
138  Regexps[Prefix][Category] += "^" + Regexp + "$";
139  }
140  return true;
141 }
142 
143 void SpecialCaseList::compile() {
144  assert(!IsCompiled && "compile() should only be called once");
145  // Iterate through each of the prefixes, and create Regexs for them.
146  for (StringMap<StringMap<std::string>>::const_iterator I = Regexps.begin(),
147  E = Regexps.end();
148  I != E; ++I) {
149  for (StringMap<std::string>::const_iterator II = I->second.begin(),
150  IE = I->second.end();
151  II != IE; ++II) {
152  Entries[I->getKey()][II->getKey()].RegEx.reset(new Regex(II->getValue()));
153  }
154  }
155  Regexps.clear();
156  IsCompiled = true;
157 }
158 
160 
162  StringRef Category) const {
163  assert(IsCompiled && "SpecialCaseList::compile() was not called!");
164  StringMap<StringMap<Entry> >::const_iterator I = Entries.find(Section);
165  if (I == Entries.end()) return false;
166  StringMap<Entry>::const_iterator II = I->second.find(Category);
167  if (II == I->second.end()) return false;
168 
169  return II->getValue().match(Query);
170 }
171 
172 } // namespace llvm
std::error_code getError() const
Definition: ErrorOr.h:169
Represents either an error or a value T.
Definition: ErrorOr.h:68
const ValueTy & getValue() const
Definition: StringMap.h:143
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
iterator find(StringRef Key)
Definition: StringMap.h:315
StringRef getBuffer() const
Definition: MemoryBuffer.h:59
static std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths)
Parses the special case list entries from files.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Definition: StringMap.h:341
Function Alias Analysis false
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:115
static bool isLiteralERE(StringRef Str)
If this function returns true, ^Str$ is an extended regular expression that matches Str and only Str...
Definition: Regex.cpp:189
void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \t\n\v\f\r")
SplitString - Split up the specified string according to the specified delimiters, appending the result fragments to the output list.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
static ManagedStatic< CodeViewErrorCategory > Category
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:40
std::unique_ptr< Regex > RegEx
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:223
Represents a set of regular expressions.
bool inSection(StringRef Section, StringRef Query, StringRef Category=StringRef()) const
Returns true, if special case list contains a line.
bool isDefinitelyOut(StringRef Query) const
Returns true, if special case list definitely does not have a line that matches the query...
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:119
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
#define I(x, y, z)
Definition: MD5.cpp:54
static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read, bool &Write, bool &Effects, bool &StackPointer)
static std::unique_ptr< SpecialCaseList > create(const std::vector< std::string > &Paths, std::string &Error)
Parses the special case list entries from files.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:23
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
iterator end()
Definition: StringMap.h:305
reference get()
Definition: ErrorOr.h:166
bool match(StringRef Query) const