LCOV - code coverage report
Current view: top level - lib/Support - SpecialCaseList.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 92 94 97.9 %
Date: 2018-10-20 13:21:21 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      17             : #include "llvm/Support/SpecialCaseList.h"
      18             : #include "llvm/ADT/SmallVector.h"
      19             : #include "llvm/ADT/StringExtras.h"
      20             : #include "llvm/Support/MemoryBuffer.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       11893 : bool SpecialCaseList::Matcher::insert(std::string Regexp,
      30             :                                       unsigned LineNumber,
      31             :                                       std::string &REError) {
      32       11893 :   if (Regexp.empty()) {
      33             :     REError = "Supplied regexp was blank";
      34           1 :     return false;
      35             :   }
      36             : 
      37       11892 :   if (Regex::isLiteralERE(Regexp)) {
      38       11127 :     Strings[Regexp] = LineNumber;
      39       11127 :     return true;
      40             :   }
      41        1530 :   Trigrams.insert(Regexp);
      42             : 
      43             :   // Replace * with .*
      44        1927 :   for (size_t pos = 0; (pos = Regexp.find('*', pos)) != std::string::npos;
      45        1162 :        pos += strlen(".*")) {
      46        1162 :     Regexp.replace(pos, strlen("*"), ".*");
      47             :   }
      48             : 
      49        1530 :   Regexp = (Twine("^(") + StringRef(Regexp) + ")$").str();
      50             : 
      51             :   // Check that the regexp is valid.
      52        1530 :   Regex CheckRE(Regexp);
      53         765 :   if (!CheckRE.isValid(REError))
      54             :     return false;
      55             : 
      56        1526 :   RegExes.emplace_back(
      57         763 :       std::make_pair(make_unique<Regex>(std::move(CheckRE)), LineNumber));
      58         763 :   return true;
      59             : }
      60             : 
      61        4357 : unsigned SpecialCaseList::Matcher::match(StringRef Query) const {
      62        4357 :   auto It = Strings.find(Query);
      63        8714 :   if (It != Strings.end())
      64          72 :     return It->second;
      65        4285 :   if (Trigrams.isDefinitelyOut(Query))
      66             :     return false;
      67        3155 :   for (auto& RegExKV : RegExes)
      68        2951 :     if (RegExKV.first->match(Query))
      69        2680 :       return RegExKV.second;
      70             :   return 0;
      71             : }
      72             : 
      73             : std::unique_ptr<SpecialCaseList>
      74      137792 : SpecialCaseList::create(const std::vector<std::string> &Paths,
      75             :                         std::string &Error) {
      76      275584 :   std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
      77      137792 :   if (SCL->createInternal(Paths, Error))
      78             :     return SCL;
      79             :   return nullptr;
      80             : }
      81             : 
      82          48 : std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
      83             :                                                          std::string &Error) {
      84          96 :   std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
      85          48 :   if (SCL->createInternal(MB, Error))
      86             :     return SCL;
      87             :   return nullptr;
      88             : }
      89             : 
      90             : std::unique_ptr<SpecialCaseList>
      91      111361 : SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
      92             :   std::string Error;
      93      111361 :   if (auto SCL = create(Paths, Error))
      94      222722 :     return SCL;
      95           0 :   report_fatal_error(Error);
      96             : }
      97             : 
      98      174902 : bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
      99             :                                      std::string &Error) {
     100      174902 :   StringMap<size_t> Sections;
     101      175214 :   for (const auto &Path : Paths) {
     102             :     ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
     103         314 :         MemoryBuffer::getFile(Path);
     104         314 :     if (std::error_code EC = FileOrErr.getError()) {
     105           3 :       Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
     106             :       return false;
     107             :     }
     108             :     std::string ParseError;
     109         313 :     if (!parse(FileOrErr.get().get(), Sections, ParseError)) {
     110           2 :       Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
     111             :       return false;
     112             :     }
     113             :   }
     114             :   return true;
     115             : }
     116             : 
     117          48 : bool SpecialCaseList::createInternal(const MemoryBuffer *MB,
     118             :                                      std::string &Error) {
     119          48 :   StringMap<size_t> Sections;
     120          48 :   if (!parse(MB, Sections, Error))
     121           8 :     return false;
     122             :   return true;
     123             : }
     124             : 
     125         361 : bool SpecialCaseList::parse(const MemoryBuffer *MB,
     126             :                             StringMap<size_t> &SectionsMap,
     127             :                             std::string &Error) {
     128             :   // Iterate through each line in the blacklist file.
     129             :   SmallVector<StringRef, 16> Lines;
     130         361 :   MB->getBuffer().split(Lines, '\n');
     131             : 
     132             :   unsigned LineNo = 1;
     133             :   StringRef Section = "*";
     134             : 
     135       14841 :   for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
     136       14489 :     *I = I->trim();
     137             :     // Ignore empty lines and lines starting with "#"
     138       14489 :     if (I->empty() || I->startswith("#"))
     139        2855 :       continue;
     140             : 
     141             :     // Save section names
     142             :     if (I->startswith("[")) {
     143             :       if (!I->endswith("]")) {
     144           3 :         Error = (Twine("malformed section header on line ") + Twine(LineNo) +
     145           3 :                  ": " + *I).str();
     146           4 :         return false;
     147             :       }
     148             : 
     149          58 :       Section = I->slice(1, I->size() - 1);
     150             : 
     151             :       std::string REError;
     152          58 :       Regex CheckRE(Section);
     153          58 :       if (!CheckRE.isValid(REError)) {
     154             :         Error =
     155           1 :             (Twine("malformed regex for section ") + Section + ": '" + REError)
     156           1 :                 .str();
     157           1 :         return false;
     158             :       }
     159             : 
     160          57 :       continue;
     161             :     }
     162             : 
     163             :     // Get our prefix and unparsed regexp.
     164       11630 :     std::pair<StringRef, StringRef> SplitLine = I->split(":");
     165       11630 :     StringRef Prefix = SplitLine.first;
     166       11630 :     if (SplitLine.second.empty()) {
     167             :       // Missing ':' in the line.
     168           2 :       Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
     169           2 :                SplitLine.first + "'").str();
     170           2 :       return false;
     171             :     }
     172             : 
     173       11628 :     std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
     174             :     std::string Regexp = SplitRegexp.first;
     175       11628 :     StringRef Category = SplitRegexp.second;
     176             : 
     177             :     // Create this section if it has not been seen before.
     178       23256 :     if (SectionsMap.find(Section) == SectionsMap.end()) {
     179         530 :       std::unique_ptr<Matcher> M = make_unique<Matcher>();
     180             :       std::string REError;
     181         530 :       if (!M->insert(Section, LineNo, REError)) {
     182           0 :         Error = (Twine("malformed section ") + Section + ": '" + REError).str();
     183             :         return false;
     184             :       }
     185             : 
     186         265 :       SectionsMap[Section] = Sections.size();
     187         265 :       Sections.emplace_back(std::move(M));
     188             :     }
     189             : 
     190       23256 :     auto &Entry = Sections[SectionsMap[Section]].Entries[Prefix][Category];
     191             :     std::string REError;
     192       23256 :     if (!Entry.insert(std::move(Regexp), LineNo, REError)) {
     193           3 :       Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
     194           6 :                SplitLine.second + "': " + REError).str();
     195             :       return false;
     196             :     }
     197             :   }
     198             :   return true;
     199             : }
     200             : 
     201      146730 : SpecialCaseList::~SpecialCaseList() {}
     202             : 
     203        1287 : bool SpecialCaseList::inSection(StringRef Section, StringRef Prefix,
     204             :                                 StringRef Query, StringRef Category) const {
     205        1287 :   return inSectionBlame(Section, Prefix, Query, Category);
     206             : }
     207             : 
     208        1298 : unsigned SpecialCaseList::inSectionBlame(StringRef Section, StringRef Prefix,
     209             :                                          StringRef Query,
     210             :                                          StringRef Category) const {
     211        2301 :   for (auto &SectionIter : Sections)
     212        1133 :     if (SectionIter.SectionMatcher->match(Section)) {
     213             :       unsigned Blame =
     214        1109 :           inSectionBlame(SectionIter.Entries, Prefix, Query, Category);
     215        1109 :       if (Blame)
     216             :         return Blame;
     217             :     }
     218             :   return 0;
     219             : }
     220             : 
     221        2339 : unsigned SpecialCaseList::inSectionBlame(const SectionEntries &Entries,
     222             :                                          StringRef Prefix, StringRef Query,
     223             :                                          StringRef Category) const {
     224        2339 :   SectionEntries::const_iterator I = Entries.find(Prefix);
     225        4678 :   if (I == Entries.end()) return 0;
     226        1322 :   StringMap<Matcher>::const_iterator II = I->second.find(Category);
     227        2644 :   if (II == I->second.end()) return 0;
     228             : 
     229        1116 :   return II->getValue().match(Query);
     230             : }
     231             : 
     232             : }  // namespace llvm

Generated by: LCOV version 1.13