13cab2bb3Spatrick //===- FuzzerDataFlowTrace.h - Internal header for the Fuzzer ---*- C++ -* ===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick // fuzzer::DataFlowTrace; reads and handles a data-flow trace. 93cab2bb3Spatrick // 103cab2bb3Spatrick // A data flow trace is generated by e.g. dataflow/DataFlow.cpp 113cab2bb3Spatrick // and is stored on disk in a separate directory. 123cab2bb3Spatrick // 133cab2bb3Spatrick // The trace dir contains a file 'functions.txt' which lists function names, 143cab2bb3Spatrick // oner per line, e.g. 153cab2bb3Spatrick // ==> functions.txt <== 163cab2bb3Spatrick // Func2 173cab2bb3Spatrick // LLVMFuzzerTestOneInput 183cab2bb3Spatrick // Func1 193cab2bb3Spatrick // 203cab2bb3Spatrick // All other files in the dir are the traces, see dataflow/DataFlow.cpp. 213cab2bb3Spatrick // The name of the file is sha1 of the input used to generate the trace. 223cab2bb3Spatrick // 233cab2bb3Spatrick // Current status: 243cab2bb3Spatrick // the data is parsed and the summary is printed, but the data is not yet 253cab2bb3Spatrick // used in any other way. 263cab2bb3Spatrick //===----------------------------------------------------------------------===// 273cab2bb3Spatrick 283cab2bb3Spatrick #ifndef LLVM_FUZZER_DATA_FLOW_TRACE 293cab2bb3Spatrick #define LLVM_FUZZER_DATA_FLOW_TRACE 303cab2bb3Spatrick 313cab2bb3Spatrick #include "FuzzerDefs.h" 323cab2bb3Spatrick #include "FuzzerIO.h" 333cab2bb3Spatrick 343cab2bb3Spatrick #include <unordered_map> 353cab2bb3Spatrick #include <unordered_set> 363cab2bb3Spatrick #include <vector> 373cab2bb3Spatrick #include <string> 383cab2bb3Spatrick 393cab2bb3Spatrick namespace fuzzer { 403cab2bb3Spatrick 413cab2bb3Spatrick int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, 42*810390e3Srobert const std::vector<SizedFile> &CorporaFiles); 433cab2bb3Spatrick 443cab2bb3Spatrick class BlockCoverage { 453cab2bb3Spatrick public: 46d89ec533Spatrick // These functions guarantee no CoverageVector is longer than UINT32_MAX. 473cab2bb3Spatrick bool AppendCoverage(std::istream &IN); 483cab2bb3Spatrick bool AppendCoverage(const std::string &S); 493cab2bb3Spatrick NumCoveredFunctions()503cab2bb3Spatrick size_t NumCoveredFunctions() const { return Functions.size(); } 513cab2bb3Spatrick GetCounter(size_t FunctionId,size_t BasicBlockId)523cab2bb3Spatrick uint32_t GetCounter(size_t FunctionId, size_t BasicBlockId) { 533cab2bb3Spatrick auto It = Functions.find(FunctionId); 54d89ec533Spatrick if (It == Functions.end()) 55d89ec533Spatrick return 0; 563cab2bb3Spatrick const auto &Counters = It->second; 573cab2bb3Spatrick if (BasicBlockId < Counters.size()) 583cab2bb3Spatrick return Counters[BasicBlockId]; 593cab2bb3Spatrick return 0; 603cab2bb3Spatrick } 613cab2bb3Spatrick GetNumberOfBlocks(size_t FunctionId)623cab2bb3Spatrick uint32_t GetNumberOfBlocks(size_t FunctionId) { 633cab2bb3Spatrick auto It = Functions.find(FunctionId); 643cab2bb3Spatrick if (It == Functions.end()) return 0; 653cab2bb3Spatrick const auto &Counters = It->second; 66d89ec533Spatrick return static_cast<uint32_t>(Counters.size()); 673cab2bb3Spatrick } 683cab2bb3Spatrick GetNumberOfCoveredBlocks(size_t FunctionId)693cab2bb3Spatrick uint32_t GetNumberOfCoveredBlocks(size_t FunctionId) { 703cab2bb3Spatrick auto It = Functions.find(FunctionId); 713cab2bb3Spatrick if (It == Functions.end()) return 0; 723cab2bb3Spatrick const auto &Counters = It->second; 733cab2bb3Spatrick uint32_t Result = 0; 743cab2bb3Spatrick for (auto Cnt: Counters) 753cab2bb3Spatrick if (Cnt) 763cab2bb3Spatrick Result++; 773cab2bb3Spatrick return Result; 783cab2bb3Spatrick } 793cab2bb3Spatrick 80*810390e3Srobert std::vector<double> FunctionWeights(size_t NumFunctions) const; clear()813cab2bb3Spatrick void clear() { Functions.clear(); } 823cab2bb3Spatrick 833cab2bb3Spatrick private: 84*810390e3Srobert typedef std::vector<uint32_t> CoverageVector; 853cab2bb3Spatrick NumberOfCoveredBlocks(const CoverageVector & Counters)863cab2bb3Spatrick uint32_t NumberOfCoveredBlocks(const CoverageVector &Counters) const { 873cab2bb3Spatrick uint32_t Res = 0; 883cab2bb3Spatrick for (auto Cnt : Counters) 893cab2bb3Spatrick if (Cnt) 903cab2bb3Spatrick Res++; 913cab2bb3Spatrick return Res; 923cab2bb3Spatrick } 933cab2bb3Spatrick NumberOfUncoveredBlocks(const CoverageVector & Counters)943cab2bb3Spatrick uint32_t NumberOfUncoveredBlocks(const CoverageVector &Counters) const { 95d89ec533Spatrick return static_cast<uint32_t>(Counters.size()) - 96d89ec533Spatrick NumberOfCoveredBlocks(Counters); 973cab2bb3Spatrick } 983cab2bb3Spatrick SmallestNonZeroCounter(const CoverageVector & Counters)993cab2bb3Spatrick uint32_t SmallestNonZeroCounter(const CoverageVector &Counters) const { 1003cab2bb3Spatrick assert(!Counters.empty()); 1013cab2bb3Spatrick uint32_t Res = Counters[0]; 1023cab2bb3Spatrick for (auto Cnt : Counters) 1033cab2bb3Spatrick if (Cnt) 1043cab2bb3Spatrick Res = Min(Res, Cnt); 1053cab2bb3Spatrick assert(Res); 1063cab2bb3Spatrick return Res; 1073cab2bb3Spatrick } 1083cab2bb3Spatrick 1093cab2bb3Spatrick // Function ID => vector of counters. 1103cab2bb3Spatrick // Each counter represents how many input files trigger the given basic block. 1113cab2bb3Spatrick std::unordered_map<size_t, CoverageVector> Functions; 1123cab2bb3Spatrick // Functions that have DFT entry. 1133cab2bb3Spatrick std::unordered_set<size_t> FunctionsWithDFT; 1143cab2bb3Spatrick }; 1153cab2bb3Spatrick 1163cab2bb3Spatrick class DataFlowTrace { 1173cab2bb3Spatrick public: 1183cab2bb3Spatrick void ReadCoverage(const std::string &DirPath); 1193cab2bb3Spatrick bool Init(const std::string &DirPath, std::string *FocusFunction, 120*810390e3Srobert std::vector<SizedFile> &CorporaFiles, Random &Rand); Clear()1213cab2bb3Spatrick void Clear() { Traces.clear(); } Get(const std::string & InputSha1)122*810390e3Srobert const std::vector<uint8_t> *Get(const std::string &InputSha1) const { 1233cab2bb3Spatrick auto It = Traces.find(InputSha1); 1243cab2bb3Spatrick if (It != Traces.end()) 1253cab2bb3Spatrick return &It->second; 1263cab2bb3Spatrick return nullptr; 1273cab2bb3Spatrick } 1283cab2bb3Spatrick 1293cab2bb3Spatrick private: 1303cab2bb3Spatrick // Input's sha1 => DFT for the FocusFunction. 131*810390e3Srobert std::unordered_map<std::string, std::vector<uint8_t>> Traces; 1323cab2bb3Spatrick BlockCoverage Coverage; 1333cab2bb3Spatrick std::unordered_set<std::string> CorporaHashes; 1343cab2bb3Spatrick }; 1353cab2bb3Spatrick } // namespace fuzzer 1363cab2bb3Spatrick 1373cab2bb3Spatrick #endif // LLVM_FUZZER_DATA_FLOW_TRACE 138