[compiler-rt] dc62d5e - [libFuzzer] Added -print_full_coverage flag.

Max Moroz via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 23 16:09:23 PDT 2020


Author: Max Moroz
Date: 2020-10-23T16:05:54-07:00
New Revision: dc62d5ec97261429b553f2d6b45d96a137211f14

URL: https://github.com/llvm/llvm-project/commit/dc62d5ec97261429b553f2d6b45d96a137211f14
DIFF: https://github.com/llvm/llvm-project/commit/dc62d5ec97261429b553f2d6b45d96a137211f14.diff

LOG: [libFuzzer] Added -print_full_coverage flag.

-print_full_coverage=1 produces a detailed branch coverage dump when run on a single file.
Uses same infrastructure as -print_coverage flag, but prints all branches (regardless of coverage status) in an easy-to-parse format.
Usage: For internal use with machine learning fuzzing models which require detailed coverage information on seed files to generate mutations.

Differential Revision: https://reviews.llvm.org/D85928

Added: 
    compiler-rt/test/fuzzer/dso-cov-input.txt
    compiler-rt/test/fuzzer/full-coverage.test

Modified: 
    compiler-rt/lib/fuzzer/FuzzerDriver.cpp
    compiler-rt/lib/fuzzer/FuzzerFlags.def
    compiler-rt/lib/fuzzer/FuzzerInternal.h
    compiler-rt/lib/fuzzer/FuzzerLoop.cpp
    compiler-rt/lib/fuzzer/FuzzerOptions.h
    compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
    compiler-rt/lib/fuzzer/FuzzerTracePC.h

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
index 83ef642ceeb6..6b674c4e9d7a 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
@@ -321,7 +321,12 @@ int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) {
   if (MaxLen && MaxLen < U.size())
     U.resize(MaxLen);
   F->ExecuteCallback(U.data(), U.size());
-  F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
+  if (Flags.print_full_coverage) {
+    // Leak detection is not needed when collecting full coverage data.
+    F->TPCUpdateObservedPCs();
+  } else {
+    F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
+  }
   return 0;
 }
 
@@ -743,6 +748,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
   Options.PrintFinalStats = Flags.print_final_stats;
   Options.PrintCorpusStats = Flags.print_corpus_stats;
   Options.PrintCoverage = Flags.print_coverage;
+  Options.PrintFullCoverage = Flags.print_full_coverage;
   if (Flags.exit_on_src_pos)
     Options.ExitOnSrcPos = Flags.exit_on_src_pos;
   if (Flags.exit_on_item)

diff  --git a/compiler-rt/lib/fuzzer/FuzzerFlags.def b/compiler-rt/lib/fuzzer/FuzzerFlags.def
index 4d4841b17ae4..ef6c3f8ba8f0 100644
--- a/compiler-rt/lib/fuzzer/FuzzerFlags.def
+++ b/compiler-rt/lib/fuzzer/FuzzerFlags.def
@@ -132,6 +132,8 @@ FUZZER_FLAG_INT(print_corpus_stats, 0,
   "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_FLAG_INT(print_full_coverage, 0, "If 1, print full coverage information "
+                                        "(all branches) as text at exit.")
 FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated.")
 FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")
 FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGBUS.")

diff  --git a/compiler-rt/lib/fuzzer/FuzzerInternal.h b/compiler-rt/lib/fuzzer/FuzzerInternal.h
index 2b172d912227..37c8a01dc3c6 100644
--- a/compiler-rt/lib/fuzzer/FuzzerInternal.h
+++ b/compiler-rt/lib/fuzzer/FuzzerInternal.h
@@ -69,6 +69,7 @@ class Fuzzer {
   bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
               InputInfo *II = nullptr, bool ForceAddToCorpus = false,
               bool *FoundUniqFeatures = nullptr);
+  void TPCUpdateObservedPCs();
 
   // Merge Corpora[1:] into Corpora[0].
   void Merge(const Vector<std::string> &Corpora);

diff  --git a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
index f1895ec2621a..6e3bf44f8b45 100644
--- a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
@@ -354,8 +354,10 @@ void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units,
 }
 
 void Fuzzer::PrintFinalStats() {
+  if (Options.PrintFullCoverage)
+    TPC.PrintCoverage(/*PrintAllCounters=*/true);
   if (Options.PrintCoverage)
-    TPC.PrintCoverage();
+    TPC.PrintCoverage(/*PrintAllCounters=*/false);
   if (Options.PrintCorpusStats)
     Corpus.PrintStats();
   if (!Options.PrintFinalStats)
@@ -545,6 +547,8 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
   return false;
 }
 
+void Fuzzer::TPCUpdateObservedPCs() { TPC.UpdateObservedPCs(); }
+
 size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
   assert(InFuzzingThread());
   *Data = CurrentUnitData;

diff  --git a/compiler-rt/lib/fuzzer/FuzzerOptions.h b/compiler-rt/lib/fuzzer/FuzzerOptions.h
index 20b810b2867f..21155e9c5692 100644
--- a/compiler-rt/lib/fuzzer/FuzzerOptions.h
+++ b/compiler-rt/lib/fuzzer/FuzzerOptions.h
@@ -68,6 +68,7 @@ struct FuzzingOptions {
   bool PrintFinalStats = false;
   bool PrintCorpusStats = false;
   bool PrintCoverage = false;
+  bool PrintFullCoverage = false;
   bool DumpCoverage = false;
   bool DetectLeaks = true;
   int PurgeAllocatorIntervalSec = 1;

diff  --git a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
index b2ca7693e540..91e94d824002 100644
--- a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
@@ -269,7 +269,7 @@ bool TracePC::ObservedFocusFunction() {
   return FocusFunctionCounterPtr && *FocusFunctionCounterPtr;
 }
 
-void TracePC::PrintCoverage() {
+void TracePC::PrintCoverage(bool PrintAllCounters) {
   if (!EF->__sanitizer_symbolize_pc ||
       !EF->__sanitizer_get_module_and_offset_for_pc) {
     Printf("INFO: __sanitizer_symbolize_pc or "
@@ -277,7 +277,7 @@ void TracePC::PrintCoverage() {
            " not printing coverage\n");
     return;
   }
-  Printf("COVERAGE:\n");
+  Printf(PrintAllCounters ? "FULL COVERAGE:\n" : "COVERAGE:\n");
   auto CoveredFunctionCallback = [&](const PCTableEntry *First,
                                      const PCTableEntry *Last,
                                      uintptr_t Counter) {
@@ -292,17 +292,33 @@ void TracePC::PrintCoverage() {
     std::string LineStr = DescribePC("%l", VisualizePC);
     size_t NumEdges = Last - First;
     Vector<uintptr_t> UncoveredPCs;
+    Vector<uintptr_t> CoveredPCs;
     for (auto TE = First; TE < Last; TE++)
       if (!ObservedPCs.count(TE))
         UncoveredPCs.push_back(TE->PC);
-    Printf("%sCOVERED_FUNC: hits: %zd", Counter ? "" : "UN", Counter);
-    Printf(" edges: %zd/%zd", NumEdges - UncoveredPCs.size(), NumEdges);
-    Printf(" %s %s:%s\n", FunctionStr.c_str(), FileStr.c_str(),
-           LineStr.c_str());
-    if (Counter)
+      else
+        CoveredPCs.push_back(TE->PC);
+
+    if (PrintAllCounters) {
+      Printf("U");
       for (auto PC : UncoveredPCs)
-        Printf("  UNCOVERED_PC: %s\n",
-               DescribePC("%s:%l", GetNextInstructionPc(PC)).c_str());
+        Printf(DescribePC(" %l", GetNextInstructionPc(PC)).c_str());
+      Printf("\n");
+
+      Printf("C");
+      for (auto PC : CoveredPCs)
+        Printf(DescribePC(" %l", GetNextInstructionPc(PC)).c_str());
+      Printf("\n");
+    } else {
+      Printf("%sCOVERED_FUNC: hits: %zd", Counter ? "" : "UN", Counter);
+      Printf(" edges: %zd/%zd", NumEdges - UncoveredPCs.size(), NumEdges);
+      Printf(" %s %s:%s\n", FunctionStr.c_str(), FileStr.c_str(),
+             LineStr.c_str());
+      if (Counter)
+        for (auto PC : UncoveredPCs)
+          Printf("  UNCOVERED_PC: %s\n",
+                 DescribePC("%s:%l", GetNextInstructionPc(PC)).c_str());
+    }
   };
 
   IterateCoveredFunctions(CoveredFunctionCallback);

diff  --git a/compiler-rt/lib/fuzzer/FuzzerTracePC.h b/compiler-rt/lib/fuzzer/FuzzerTracePC.h
index 4601300cb9dc..00909230731d 100644
--- a/compiler-rt/lib/fuzzer/FuzzerTracePC.h
+++ b/compiler-rt/lib/fuzzer/FuzzerTracePC.h
@@ -94,7 +94,7 @@ class TracePC {
 
   void PrintModuleInfo();
 
-  void PrintCoverage();
+  void PrintCoverage(bool PrintAllCounters);
 
   template<class CallBack>
   void IterateCoveredFunctions(CallBack CB);

diff  --git a/compiler-rt/test/fuzzer/dso-cov-input.txt b/compiler-rt/test/fuzzer/dso-cov-input.txt
new file mode 100644
index 000000000000..6db78894e3e7
--- /dev/null
+++ b/compiler-rt/test/fuzzer/dso-cov-input.txt
@@ -0,0 +1 @@
+123457
\ No newline at end of file

diff  --git a/compiler-rt/test/fuzzer/full-coverage.test b/compiler-rt/test/fuzzer/full-coverage.test
new file mode 100644
index 000000000000..688332d5877c
--- /dev/null
+++ b/compiler-rt/test/fuzzer/full-coverage.test
@@ -0,0 +1,15 @@
+# FIXME: Disabled on Windows because -fPIC cannot be used to compile for Windows.
+UNSUPPORTED: windows
+XFAIL: s390x
+RUN: %cpp_compiler %S/DSO1.cpp -fPIC %ld_flags_rpath_so1 -O0 -shared -o %dynamiclib1
+RUN: %cpp_compiler %S/DSO2.cpp -fPIC %ld_flags_rpath_so2 -O0 -shared -o %dynamiclib2
+RUN: %cpp_compiler %S/DSOTestMain.cpp %S/DSOTestExtra.cpp %ld_flags_rpath_exe1 %ld_flags_rpath_exe2 -o %t-DSOTest
+
+RUN: %run %t-DSOTest -print_full_coverage=1 %S/dso-cov-input.txt 2>&1 | FileCheck %s
+CHECK: FULL COVERAGE:
+CHECK-DAG: U{{( [0-9]+)*}}
+CHECK-DAG: C{{( [0-9]+)*}}
+CHECK-DAG: U{{( [0-9]+)*}}
+CHECK-DAG: U{{( [0-9]+)*}}
+CHECK-DAG: C{{( [0-9]+)*}}
+CHECK-DAG: U{{( [0-9]+)*}}


        


More information about the llvm-commits mailing list