LLVM  8.0.1
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 
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/Support/Regex.h"
22 #include <string>
23 #include <system_error>
24 #include <utility>
25 
26 #include <stdio.h>
27 namespace llvm {
28 
29 bool SpecialCaseList::Matcher::insert(std::string Regexp,
30  unsigned LineNumber,
31  std::string &REError) {
32  if (Regexp.empty()) {
33  REError = "Supplied regexp was blank";
34  return false;
35  }
36 
37  if (Regex::isLiteralERE(Regexp)) {
38  Strings[Regexp] = LineNumber;
39  return true;
40  }
41  Trigrams.insert(Regexp);
42 
43  // Replace * with .*
44  for (size_t pos = 0; (pos = Regexp.find('*', pos)) != std::string::npos;
45  pos += strlen(".*")) {
46  Regexp.replace(pos, strlen("*"), ".*");
47  }
48 
49  Regexp = (Twine("^(") + StringRef(Regexp) + ")$").str();
50 
51  // Check that the regexp is valid.
52  Regex CheckRE(Regexp);
53  if (!CheckRE.isValid(REError))
54  return false;
55 
56  RegExes.emplace_back(
57  std::make_pair(make_unique<Regex>(std::move(CheckRE)), LineNumber));
58  return true;
59 }
60 
62  auto It = Strings.find(Query);
63  if (It != Strings.end())
64  return It->second;
65  if (Trigrams.isDefinitelyOut(Query))
66  return false;
67  for (auto& RegExKV : RegExes)
68  if (RegExKV.first->match(Query))
69  return RegExKV.second;
70  return 0;
71 }
72 
73 std::unique_ptr<SpecialCaseList>
74 SpecialCaseList::create(const std::vector<std::string> &Paths,
75  std::string &Error) {
76  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
77  if (SCL->createInternal(Paths, Error))
78  return SCL;
79  return nullptr;
80 }
81 
82 std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
83  std::string &Error) {
84  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
85  if (SCL->createInternal(MB, Error))
86  return SCL;
87  return nullptr;
88 }
89 
90 std::unique_ptr<SpecialCaseList>
91 SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
92  std::string Error;
93  if (auto SCL = create(Paths, Error))
94  return SCL;
95  report_fatal_error(Error);
96 }
97 
98 bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
99  std::string &Error) {
101  for (const auto &Path : Paths) {
103  MemoryBuffer::getFile(Path);
104  if (std::error_code EC = FileOrErr.getError()) {
105  Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
106  return false;
107  }
108  std::string ParseError;
109  if (!parse(FileOrErr.get().get(), Sections, ParseError)) {
110  Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
111  return false;
112  }
113  }
114  return true;
115 }
116 
118  std::string &Error) {
120  if (!parse(MB, Sections, Error))
121  return false;
122  return true;
123 }
124 
126  StringMap<size_t> &SectionsMap,
127  std::string &Error) {
128  // Iterate through each line in the blacklist file.
130  MB->getBuffer().split(Lines, '\n');
131 
132  unsigned LineNo = 1;
133  StringRef Section = "*";
134 
135  for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
136  *I = I->trim();
137  // Ignore empty lines and lines starting with "#"
138  if (I->empty() || I->startswith("#"))
139  continue;
140 
141  // Save section names
142  if (I->startswith("[")) {
143  if (!I->endswith("]")) {
144  Error = (Twine("malformed section header on line ") + Twine(LineNo) +
145  ": " + *I).str();
146  return false;
147  }
148 
149  Section = I->slice(1, I->size() - 1);
150 
151  std::string REError;
152  Regex CheckRE(Section);
153  if (!CheckRE.isValid(REError)) {
154  Error =
155  (Twine("malformed regex for section ") + Section + ": '" + REError)
156  .str();
157  return false;
158  }
159 
160  continue;
161  }
162 
163  // Get our prefix and unparsed regexp.
164  std::pair<StringRef, StringRef> SplitLine = I->split(":");
165  StringRef Prefix = SplitLine.first;
166  if (SplitLine.second.empty()) {
167  // Missing ':' in the line.
168  Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
169  SplitLine.first + "'").str();
170  return false;
171  }
172 
173  std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
174  std::string Regexp = SplitRegexp.first;
175  StringRef Category = SplitRegexp.second;
176 
177  // Create this section if it has not been seen before.
178  if (SectionsMap.find(Section) == SectionsMap.end()) {
179  std::unique_ptr<Matcher> M = make_unique<Matcher>();
180  std::string REError;
181  if (!M->insert(Section, LineNo, REError)) {
182  Error = (Twine("malformed section ") + Section + ": '" + REError).str();
183  return false;
184  }
185 
186  SectionsMap[Section] = Sections.size();
187  Sections.emplace_back(std::move(M));
188  }
189 
190  auto &Entry = Sections[SectionsMap[Section]].Entries[Prefix][Category];
191  std::string REError;
192  if (!Entry.insert(std::move(Regexp), LineNo, REError)) {
193  Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
194  SplitLine.second + "': " + REError).str();
195  return false;
196  }
197  }
198  return true;
199 }
200 
202 
204  StringRef Query, StringRef Category) const {
205  return inSectionBlame(Section, Prefix, Query, Category);
206 }
207 
210  StringRef Category) const {
211  for (auto &SectionIter : Sections)
212  if (SectionIter.SectionMatcher->match(Section)) {
213  unsigned Blame =
214  inSectionBlame(SectionIter.Entries, Prefix, Query, Category);
215  if (Blame)
216  return Blame;
217  }
218  return 0;
219 }
220 
223  StringRef Category) const {
224  SectionEntries::const_iterator I = Entries.find(Prefix);
225  if (I == Entries.end()) return 0;
226  StringMap<Matcher>::const_iterator II = I->second.find(Category);
227  if (II == I->second.end()) return 0;
228 
229  return II->getValue().match(Query);
230 }
231 
232 } // namespace llvm
Represents either an error or a value T.
Definition: ErrorOr.h:57
StringRef getBuffer() const
Definition: MemoryBuffer.h:64
unsigned inSectionBlame(StringRef Section, StringRef Prefix, StringRef Query, StringRef Category=StringRef()) const
Returns the line number corresponding to the special case list entry if the special case list contain...
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
This class represents lattice values for constants.
Definition: AllocatorList.h:24
bool createInternal(const std::vector< std::string > &Paths, std::string &Error)
bool isDefinitelyOut(StringRef Query) const
Returns true, if special case list definitely does not have a line that matches the query...
iterator find(StringRef Key)
Definition: StringMap.h:333
bool inSection(StringRef Section, StringRef Prefix, StringRef Query, StringRef Category=StringRef()) const
Returns true, if special case list contains a line.
static std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths)
Parses the special case list entries from files.
unsigned match(StringRef Query) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
bool parse(const MemoryBuffer *MB, StringMap< size_t > &SectionsMap, std::string &Error)
Parses just-constructed SpecialCaseList entries from a memory buffer.
void insert(std::string Regex)
Inserts a new Regex into the index.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:129
std::error_code getError() const
Definition: ErrorOr.h:160
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:194
std::vector< Section > Sections
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:727
bool isValid(std::string &Error) const
isValid - returns the error encountered during regex compilation, or matching, if any...
Definition: Regex.cpp:56
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:42
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:220
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:133
#define I(x, y, z)
Definition: MD5.cpp:58
static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read, bool &Write, bool &Effects, bool &StackPointer)
bool insert(std::string Regexp, unsigned LineNumber, std::string &REError)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
static std::unique_ptr< SpecialCaseList > create(const std::vector< std::string > &Paths, std::string &Error)
Parses the special case list entries from files.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
iterator end()
Definition: StringMap.h:318
reference get()
Definition: ErrorOr.h:157