[libFuzzer] reinstate -dump_coverage, which is still in use (reverts r332036)

llvm-svn: 332876
GitOrigin-RevId: 69c2b71a5183fe7aa44f5caa9a192cb80ac05a59
diff --git a/FuzzerDriver.cpp b/FuzzerDriver.cpp
index 26e5548..dfb3d49 100644
--- a/FuzzerDriver.cpp
+++ b/FuzzerDriver.cpp
@@ -615,6 +615,7 @@
   Options.PrintFinalStats = Flags.print_final_stats;
   Options.PrintCorpusStats = Flags.print_corpus_stats;
   Options.PrintCoverage = Flags.print_coverage;
+  Options.DumpCoverage = Flags.dump_coverage;
   Options.UseFeatureFrequency = Flags.use_feature_frequency;
   if (Flags.exit_on_src_pos)
     Options.ExitOnSrcPos = Flags.exit_on_src_pos;
diff --git a/FuzzerFlags.def b/FuzzerFlags.def
index 1ff3fd9..139e618 100644
--- a/FuzzerFlags.def
+++ b/FuzzerFlags.def
@@ -107,7 +107,9 @@
   "If 1, print statistics on corpus elements at exit.")
 FUZZER_FLAG_INT(print_coverage, 0, "If 1, print coverage information as text"
                                    " at exit.")
-FUZZER_DEPRECATED_FLAG(dump_coverage)
+FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated."
+                                  " If 1, dump coverage information as a"
+                                  " .sancov file at exit.")
 FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")
 FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGBUS.")
 FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.")
diff --git a/FuzzerLoop.cpp b/FuzzerLoop.cpp
index 4bf5c78..d5b949c 100644
--- a/FuzzerLoop.cpp
+++ b/FuzzerLoop.cpp
@@ -350,6 +350,8 @@
 void Fuzzer::PrintFinalStats() {
   if (Options.PrintCoverage)
     TPC.PrintCoverage();
+  if (Options.DumpCoverage)
+    TPC.DumpCoverage();
   if (Options.PrintCorpusStats)
     Corpus.PrintStats();
   if (!Options.PrintFinalStats)
diff --git a/FuzzerOptions.h b/FuzzerOptions.h
index 0c51d9e..946f0b9 100644
--- a/FuzzerOptions.h
+++ b/FuzzerOptions.h
@@ -53,6 +53,7 @@
   bool PrintFinalStats = false;
   bool PrintCorpusStats = false;
   bool PrintCoverage = false;
+  bool DumpCoverage = false;
   bool DetectLeaks = true;
   int PurgeAllocatorIntervalSec = 1;
   int UseFeatureFrequency = false;
diff --git a/FuzzerTracePC.cpp b/FuzzerTracePC.cpp
index ed62cdc..fb8544f 100644
--- a/FuzzerTracePC.cpp
+++ b/FuzzerTracePC.cpp
@@ -298,6 +298,15 @@
   IterateCoveredFunctions(CoveredFunctionCallback);
 }
 
+void TracePC::DumpCoverage() {
+  if (EF->__sanitizer_dump_coverage) {
+    Vector<uintptr_t> PCsCopy(GetNumPCs());
+    for (size_t i = 0; i < GetNumPCs(); i++)
+      PCsCopy[i] = PCs()[i] ? GetPreviousInstructionPc(PCs()[i]) : 0;
+    EF->__sanitizer_dump_coverage(PCsCopy.data(), PCsCopy.size());
+  }
+}
+
 // Value profile.
 // We keep track of various values that affect control flow.
 // These values are inserted into a bit-set-based hash map.
diff --git a/FuzzerTracePC.h b/FuzzerTracePC.h
index e1db512..c17626c 100644
--- a/FuzzerTracePC.h
+++ b/FuzzerTracePC.h
@@ -102,6 +102,7 @@
   void PrintModuleInfo();
 
   void PrintCoverage();
+  void DumpCoverage();
 
   template<class CallBack>
   void IterateCoveredFunctions(CallBack CB);