LCOV - code coverage report
Current view: top level - lib/Support - SpecialCaseList.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 93 95 97.9 %
Date: 2018-07-13 00:08:38 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       11977 : bool SpecialCaseList::Matcher::insert(std::string Regexp,
      30             :                                       unsigned LineNumber,
      31             :                                       std::string &REError) {
      32       11977 :   if (Regexp.empty()) {
      33             :     REError = "Supplied regexp was blank";
      34           1 :     return false;
      35             :   }
      36             : 
      37       11976 :   if (Regex::isLiteralERE(Regexp)) {
      38       22254 :     Strings[Regexp] = LineNumber;
      39       11127 :     return true;
      40             :   }
      41        2547 :   Trigrams.insert(Regexp);
      42             : 
      43             :   // Replace * with .*
      44        3357 :   for (size_t pos = 0; (pos = Regexp.find('*', pos)) != std::string::npos;
      45        1254 :        pos += strlen(".*")) {
      46        1254 :     Regexp.replace(pos, strlen("*"), ".*");
      47             :   }
      48             : 
      49        1698 :   Regexp = (Twine("^(") + StringRef(Regexp) + ")$").str();
      50             : 
      51             :   // Check that the regexp is valid.
      52        1698 :   Regex CheckRE(Regexp);
      53         849 :   if (!CheckRE.isValid(REError))
      54             :     return false;
      55             : 
      56        1694 :   RegExes.emplace_back(
      57         847 :       std::make_pair(make_unique<Regex>(std::move(CheckRE)), LineNumber));
      58         847 :   return true;
      59             : }
      60             : 
      61        4361 : unsigned SpecialCaseList::Matcher::match(StringRef Query) const {
      62        4361 :   auto It = Strings.find(Query);
      63        8722 :   if (It != Strings.end())
      64          72 :     return It->second;
      65        4289 :   if (Trigrams.isDefinitelyOut(Query))
      66             :     return false;
      67        2930 :   for (auto& RegExKV : RegExes)
      68        2997 :     if (RegExKV.first->match(Query))
      69        2741 :       return RegExKV.second;
      70             :   return 0;
      71             : }
      72             : 
      73             : std::unique_ptr<SpecialCaseList>
      74      111831 : SpecialCaseList::create(const std::vector<std::string> &Paths,
      75             :                         std::string &Error) {
      76      223663 :   std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
      77      111831 :   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       94585 : SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
      92             :   std::string Error;
      93      189170 :   if (auto SCL = create(Paths, Error))
      94      189170 :     return SCL;
      95           0 :   report_fatal_error(Error);
      96             : }
      97             : 
      98      143349 : bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
      99             :                                      std::string &Error) {
     100      143349 :   StringMap<size_t> Sections;
     101      143349 :   for (const auto &Path : Paths) {
     102             :     ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
     103         318 :         MemoryBuffer::getFile(Path);
     104         318 :     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         317 :     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             :     return false;
     122          40 :   return true;
     123             : }
     124             : 
     125         365 : 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         365 :   MB->getBuffer().split(Lines, '\n');
     131             : 
     132             :   unsigned LineNo = 1;
     133             :   StringRef Section = "*";
     134             : 
     135       29589 :   for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
     136       14621 :     *I = I->trim();
     137             :     // Ignore empty lines and lines starting with "#"
     138       17471 :     if (I->empty() || I->startswith("#"))
     139        5757 :       continue;
     140             : 
     141             :     // Save section names
     142             :     if (I->startswith("[")) {
     143             :       if (!I->endswith("]")) {
     144           6 :         Error = (Twine("malformed section header on line ") + Twine(LineNo) +
     145           9 :                  ": " + *I).str();
     146           7 :         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           1 :         Error =
     155           1 :             (Twine("malformed regex for section ") + Section + ": '" + REError)
     156           2 :                 .str();
     157           1 :         return false;
     158             :       }
     159             : 
     160          57 :       continue;
     161             :     }
     162             : 
     163             :     // Get our prefix and unparsed regexp.
     164       11710 :     std::pair<StringRef, StringRef> SplitLine = I->split(":");
     165       11710 :     StringRef Prefix = SplitLine.first;
     166       11710 :     if (SplitLine.second.empty()) {
     167             :       // Missing ':' in the line.
     168           4 :       Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
     169           6 :                SplitLine.first + "'").str();
     170           2 :       return false;
     171             :     }
     172             : 
     173       11708 :     std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
     174             :     std::string Regexp = SplitRegexp.first;
     175       11708 :     StringRef Category = SplitRegexp.second;
     176             : 
     177             :     // Create this section if it has not been seen before.
     178       35124 :     if (SectionsMap.find(Section) == SectionsMap.end()) {
     179         538 :       std::unique_ptr<Matcher> M = make_unique<Matcher>();
     180             :       std::string REError;
     181         538 :       if (!M->insert(Section, LineNo, REError)) {
     182           0 :         Error = (Twine("malformed section ") + Section + ": '" + REError).str();
     183             :         return false;
     184             :       }
     185             : 
     186         538 :       SectionsMap[Section] = Sections.size();
     187         269 :       Sections.emplace_back(std::move(M));
     188             :     }
     189             : 
     190       23416 :     auto &Entry = Sections[SectionsMap[Section]].Entries[Prefix][Category];
     191             :     std::string REError;
     192       23416 :     if (!Entry.insert(std::move(Regexp), LineNo, REError)) {
     193           6 :       Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
     194           9 :                SplitLine.second + "': " + REError).str();
     195             :       return false;
     196             :     }
     197             :   }
     198             :   return true;
     199             : }
     200             : 
     201      134711 : 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        1298 :   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        2345 : unsigned SpecialCaseList::inSectionBlame(const SectionEntries &Entries,
     222             :                                          StringRef Prefix, StringRef Query,
     223             :                                          StringRef Category) const {
     224        2345 :   SectionEntries::const_iterator I = Entries.find(Prefix);
     225        4690 :   if (I == Entries.end()) return 0;
     226        1325 :   StringMap<Matcher>::const_iterator II = I->second.find(Category);
     227        2650 :   if (II == I->second.end()) return 0;
     228             : 
     229        1119 :   return II->getValue().match(Query);
     230             : }
     231             : 
     232             : }  // namespace llvm

Generated by: LCOV version 1.13