output_csv libfuzzer option
authorMike Aizatsky <aizatsky@chromium.org>
Thu, 12 Nov 2015 04:38:40 +0000 (04:38 +0000)
committerMike Aizatsky <aizatsky@chromium.org>
Thu, 12 Nov 2015 04:38:40 +0000 (04:38 +0000)
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
lib/Fuzzer/FuzzerFlags.def
lib/Fuzzer/FuzzerInternal.h
lib/Fuzzer/FuzzerLoop.cpp

index 664436ed4f92bac972ec8f05f18c394a6752bfa4..c4cfc0651562a2aa5cf1852cf0fcc7b77f80de6e 100644 (file)
@@ -245,6 +245,7 @@ int FuzzerDriver(const std::vector<std::string> &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())
index 8fc955c18bdcdeb2355015014b8be4f8e4b3c521..222fa6d12a6871ec5da96868d84a6b9af7d6a112 100644 (file)
@@ -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.")
index 7cb78fd91eeb2a32701956d0c876cbea65f4ef89..9d1849f210fc150bdf2900707922ce6d0ce736c8 100644 (file)
@@ -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); }
index d3c32626a3bb3c0bb4672912570bd7b3bce87411..455aa625337f847271fbd86e9fe6720810ced009 100644 (file)
@@ -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<seconds>(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<size_t>(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() {