LLVM  14.0.0git
SpecialCaseList.cpp
Go to the documentation of this file.
1 //===-- SpecialCaseList.cpp - special case list for sanitizers ------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This is a utility class for instrumentation passes (like AddressSanitizer
10 // or ThreadSanitizer) to avoid instrumenting some functions or global
11 // variables, or to instrument some functions or global variables in a specific
12 // way, based on a user-supplied list.
13 //
14 //===----------------------------------------------------------------------===//
15 
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringExtras.h"
20 #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(std::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 (const 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  llvm::vfs::FileSystem &FS, std::string &Error) {
76  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
77  if (SCL->createInternal(Paths, FS, 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,
93  std::string Error;
94  if (auto SCL = create(Paths, FS, Error))
95  return SCL;
97 }
98 
99 bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
100  vfs::FileSystem &VFS, std::string &Error) {
102  for (const auto &Path : Paths) {
104  VFS.getBufferForFile(Path);
105  if (std::error_code EC = FileOrErr.getError()) {
106  Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
107  return false;
108  }
109  std::string ParseError;
110  if (!parse(FileOrErr.get().get(), Sections, ParseError)) {
111  Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
112  return false;
113  }
114  }
115  return true;
116 }
117 
119  std::string &Error) {
121  if (!parse(MB, Sections, Error))
122  return false;
123  return true;
124 }
125 
127  StringMap<size_t> &SectionsMap,
128  std::string &Error) {
129  // Iterate through each line in the exclusion list file.
131  MB->getBuffer().split(Lines, '\n');
132 
133  unsigned LineNo = 1;
134  StringRef Section = "*";
135 
136  for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
137  *I = I->trim();
138  // Ignore empty lines and lines starting with "#"
139  if (I->empty() || I->startswith("#"))
140  continue;
141 
142  // Save section names
143  if (I->startswith("[")) {
144  if (!I->endswith("]")) {
145  Error = (Twine("malformed section header on line ") + Twine(LineNo) +
146  ": " + *I).str();
147  return false;
148  }
149 
150  Section = I->slice(1, I->size() - 1);
151 
152  std::string REError;
153  Regex CheckRE(Section);
154  if (!CheckRE.isValid(REError)) {
155  Error =
156  (Twine("malformed regex for section ") + Section + ": '" + REError)
157  .str();
158  return false;
159  }
160 
161  continue;
162  }
163 
164  // Get our prefix and unparsed regexp.
165  std::pair<StringRef, StringRef> SplitLine = I->split(":");
166  StringRef Prefix = SplitLine.first;
167  if (SplitLine.second.empty()) {
168  // Missing ':' in the line.
169  Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
170  SplitLine.first + "'").str();
171  return false;
172  }
173 
174  std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
175  std::string Regexp = std::string(SplitRegexp.first);
176  StringRef Category = SplitRegexp.second;
177 
178  // Create this section if it has not been seen before.
179  if (SectionsMap.find(Section) == SectionsMap.end()) {
180  std::unique_ptr<Matcher> M = std::make_unique<Matcher>();
181  std::string REError;
182  if (!M->insert(std::string(Section), LineNo, REError)) {
183  Error = (Twine("malformed section ") + Section + ": '" + REError).str();
184  return false;
185  }
186 
187  SectionsMap[Section] = Sections.size();
188  Sections.emplace_back(std::move(M));
189  }
190 
191  auto &Entry = Sections[SectionsMap[Section]].Entries[Prefix][Category];
192  std::string REError;
193  if (!Entry.insert(std::move(Regexp), LineNo, REError)) {
194  Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
195  SplitLine.second + "': " + REError).str();
196  return false;
197  }
198  }
199  return true;
200 }
201 
203 
205  StringRef Query, StringRef Category) const {
206  return inSectionBlame(Section, Prefix, Query, Category);
207 }
208 
210  StringRef Query,
211  StringRef Category) const {
212  for (const auto &SectionIter : Sections)
213  if (SectionIter.SectionMatcher->match(Section)) {
214  unsigned Blame =
215  inSectionBlame(SectionIter.Entries, Prefix, Query, Category);
216  if (Blame)
217  return Blame;
218  }
219  return 0;
220 }
221 
223  StringRef Prefix, StringRef Query,
224  StringRef Category) const {
225  SectionEntries::const_iterator I = Entries.find(Prefix);
226  if (I == Entries.end()) return 0;
227  StringMap<Matcher>::const_iterator II = I->second.find(Category);
228  if (II == I->second.end()) return 0;
229 
230  return II->getValue().match(Query);
231 }
232 
233 } // namespace llvm
MemoryBuffer.h
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::SpecialCaseList::~SpecialCaseList
~SpecialCaseList()
Definition: SpecialCaseList.cpp:202
llvm::SpecialCaseList::inSection
bool inSection(StringRef Section, StringRef Prefix, StringRef Query, StringRef Category=StringRef()) const
Returns true, if special case list contains a line.
Definition: SpecialCaseList.cpp:204
llvm::cl::Prefix
@ Prefix
Definition: CommandLine.h:164
llvm::SpecialCaseList::create
static std::unique_ptr< SpecialCaseList > create(const std::vector< std::string > &Paths, llvm::vfs::FileSystem &FS, std::string &Error)
Parses the special case list entries from files.
Definition: SpecialCaseList.cpp:74
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::SpecialCaseList::createInternal
bool createInternal(const std::vector< std::string > &Paths, vfs::FileSystem &VFS, std::string &Error)
Definition: SpecialCaseList.cpp:99
llvm::SpecialCaseList::inSectionBlame
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...
Definition: SpecialCaseList.cpp:209
llvm::StringMap::end
iterator end()
Definition: StringMap.h:203
llvm::StringMap::find
iterator find(StringRef Key)
Definition: StringMap.h:216
llvm::MemoryBuffer
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:50
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:78
llvm::vfs::FileSystem::getBufferForFile
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
This is a convenience method that opens a file, gets its content and then closes the file.
Definition: VirtualFileSystem.cpp:115
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::StringRef::split
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:749
llvm::StringMapConstIterator
Definition: StringMap.h:24
llvm::ErrorOr::getError
std::error_code getError() const
Definition: ErrorOr.h:153
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
llvm::SpecialCaseList::parse
bool parse(const MemoryBuffer *MB, StringMap< size_t > &SectionsMap, std::string &Error)
Parses just-constructed SpecialCaseList entries from a memory buffer.
Definition: SpecialCaseList.cpp:126
llvm::MemoryBuffer::getBuffer
StringRef getBuffer() const
Definition: MemoryBuffer.h:69
llvm::SpecialCaseList::Section
Definition: SpecialCaseList.h:136
llvm::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:108
llvm::SpecialCaseList::Sections
std::vector< Section > Sections
Definition: SpecialCaseList.h:143
llvm::SpecialCaseList::Matcher::insert
bool insert(std::string Regexp, unsigned LineNumber, std::string &REError)
Definition: SpecialCaseList.cpp:29
llvm::TrigramIndex::insert
void insert(const std::string &Regex)
Inserts a new Regex into the index.
Definition: TrigramIndex.cpp:28
llvm::Regex::isLiteralERE
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:212
llvm::SpecialCaseList::SpecialCaseList
SpecialCaseList()=default
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
I
#define I(x, y, z)
Definition: MD5.cpp:59
StringExtras.h
llvm::SpecialCaseList::createOrDie
static std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths, llvm::vfs::FileSystem &FS)
Parses the special case list entries from files.
Definition: SpecialCaseList.cpp:91
Regex.h
llvm::Regex::isValid
bool isValid(std::string &Error) const
isValid - returns the error encountered during regex compilation, if any.
Definition: Regex.cpp:72
llvm::X86AS::FS
@ FS
Definition: X86.h:188
llvm::SpecialCaseList::Matcher::match
unsigned match(StringRef Query) const
Definition: SpecialCaseList.cpp:61
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
VirtualFileSystem.h
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::vfs::FileSystem
The virtual file system interface.
Definition: VirtualFileSystem.h:245
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
SpecialCaseList.h
SmallVector.h
llvm::ErrorOr::get
reference get()
Definition: ErrorOr.h:150
llvm::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:56
llvm::Regex
Definition: Regex.h:28