From c1a030fd64211aab1555b6d0cc2818c86ab9390d Mon Sep 17 00:00:00 2001 From: Mike Aizatsky Date: Thu, 12 Nov 2015 04:38:40 +0000 Subject: [PATCH] output_csv libfuzzer option Summary: The option outputs statistics in CSV format preceded by 1 header line. This is intended for machine processing of the output. -verbosity=0 should likely be set. Differential Revision: http://reviews.llvm.org/D14600 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252856 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Fuzzer/FuzzerDriver.cpp | 1 + lib/Fuzzer/FuzzerFlags.def | 1 + lib/Fuzzer/FuzzerInternal.h | 1 + lib/Fuzzer/FuzzerLoop.cpp | 30 ++++++++++++++++++++++-------- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/Fuzzer/FuzzerDriver.cpp b/lib/Fuzzer/FuzzerDriver.cpp index 664436ed4f9..c4cfc065156 100644 --- a/lib/Fuzzer/FuzzerDriver.cpp +++ b/lib/Fuzzer/FuzzerDriver.cpp @@ -245,6 +245,7 @@ int FuzzerDriver(const std::vector &Args, Options.OnlyASCII = Flags.only_ascii; Options.TBMDepth = Flags.tbm_depth; Options.TBMWidth = Flags.tbm_width; + Options.OutputCSV = Flags.output_csv; if (Flags.runs >= 0) Options.MaxNumberOfRuns = Flags.runs; if (!Inputs->empty()) diff --git a/lib/Fuzzer/FuzzerFlags.def b/lib/Fuzzer/FuzzerFlags.def index 8fc955c18bd..222fa6d12a6 100644 --- a/lib/Fuzzer/FuzzerFlags.def +++ b/lib/Fuzzer/FuzzerFlags.def @@ -69,3 +69,4 @@ FUZZER_FLAG_STRING(artifact_prefix, "Write fuzzing artifacts (crash, " "$(artifact_prefix)file") FUZZER_FLAG_INT(drill, 0, "Experimental: fuzz using a single unit as the seed " "corpus, then merge with the initial corpus") +FUZZER_FLAG_INT(output_csv, 0, "Enable pulse output in CSV format.") diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index 7cb78fd91ee..9d1849f210f 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -96,6 +96,7 @@ class Fuzzer { std::string ArtifactPrefix = "./"; bool SaveArtifacts = true; bool PrintNEW = true; // Print a status line when new units are found; + bool OutputCSV = false; }; Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options); void AddToCorpus(const Unit &U) { Corpus.push_back(U); } diff --git a/lib/Fuzzer/FuzzerLoop.cpp b/lib/Fuzzer/FuzzerLoop.cpp index d3c32626a3b..455aa625337 100644 --- a/lib/Fuzzer/FuzzerLoop.cpp +++ b/lib/Fuzzer/FuzzerLoop.cpp @@ -108,9 +108,23 @@ void Fuzzer::AlarmCallback() { } void Fuzzer::PrintStats(const char *Where, const char *End) { - if (!Options.Verbosity) return; size_t Seconds = secondsSinceProcessStartUp(); size_t ExecPerSec = (Seconds ? TotalNumberOfRuns / Seconds : 0); + + if (Options.OutputCSV) { + static bool csvHeaderPrinted = false; + if (!csvHeaderPrinted) { + csvHeaderPrinted = true; + Printf("runs,block_cov,bits,cc_cov,corpus,execs_per_sec,tbms,reason\n"); + } + Printf("%zd,%zd,%zd,%zd,%zd,%zd,%zd,%s\n", TotalNumberOfRuns, + LastRecordedBlockCoverage, TotalBits(), + LastRecordedCallerCalleeCoverage, Corpus.size(), ExecPerSec, + TotalNumberOfExecutedTraceBasedMutations, Where); + } + + if (!Options.Verbosity) + return; Printf("#%zd\t%s", TotalNumberOfRuns, Where); if (LastRecordedBlockCoverage) Printf(" cov: %zd", LastRecordedBlockCoverage); @@ -144,8 +158,7 @@ void Fuzzer::RereadOutputCorpus() { CurrentUnit.insert(CurrentUnit.begin(), X.begin(), X.end()); if (RunOne(CurrentUnit)) { Corpus.push_back(X); - if (Options.Verbosity >= 1) - PrintStats("RELOAD"); + PrintStats("RELOAD"); } } } @@ -198,9 +211,8 @@ bool Fuzzer::RunOne(const Unit &U) { auto UnitStopTime = system_clock::now(); auto TimeOfUnit = duration_cast(UnitStopTime - UnitStartTime).count(); - if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) - && secondsSinceProcessStartUp() >= 2 - && Options.Verbosity) + if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && + secondsSinceProcessStartUp() >= 2) PrintStats("pulse "); if (TimeOfUnit > TimeOfLongestUnitInSeconds && TimeOfUnit >= Options.ReportSlowUnits) { @@ -452,11 +464,11 @@ void Fuzzer::Loop() { SyncCorpus(); RereadOutputCorpus(); if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) - return; + break; if (Options.MaxTotalTimeSec > 0 && secondsSinceProcessStartUp() > static_cast(Options.MaxTotalTimeSec)) - return; + break; CurrentUnit = Corpus[J1]; // Optionally, cross with another unit. if (Options.DoCrossOver && USF.GetRand().RandBool()) { @@ -476,6 +488,8 @@ void Fuzzer::Loop() { // Perform several mutations and runs. MutateAndTestOne(&CurrentUnit); } + + PrintStats("DONE ", "\n"); } void Fuzzer::SyncCorpus() { -- 2.34.1