[compiler-rt] r354076 - [libFuzzer] when doing the merge, keep track of the coveraged edges, not just features

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 14 15:12:34 PST 2019


Author: kcc
Date: Thu Feb 14 15:12:33 2019
New Revision: 354076

URL: http://llvm.org/viewvc/llvm-project?rev=354076&view=rev
Log:
[libFuzzer] when doing the merge, keep track of the coveraged edges, not just features

Modified:
    compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerMerge.h
    compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h
    compiler-rt/trunk/lib/fuzzer/tests/FuzzerUnittest.cpp
    compiler-rt/trunk/test/fuzzer/merge-control-file.test
    compiler-rt/trunk/test/fuzzer/merge-sigusr.test
    compiler-rt/trunk/test/fuzzer/merge.test

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp?rev=354076&r1=354075&r2=354076&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp Thu Feb 14 15:12:33 2019
@@ -384,10 +384,10 @@ void Fuzzer::SetMaxMutationLen(size_t Ma
 void Fuzzer::CheckExitOnSrcPosOrItem() {
   if (!Options.ExitOnSrcPos.empty()) {
     static auto *PCsSet = new Set<uintptr_t>;
-    auto HandlePC = [&](uintptr_t PC) {
-      if (!PCsSet->insert(PC).second)
+    auto HandlePC = [&](const TracePC::PCTableEntry *TE) {
+      if (!PCsSet->insert(TE->PC).second)
         return;
-      std::string Descr = DescribePC("%F %L", PC + 1);
+      std::string Descr = DescribePC("%F %L", TE->PC + 1);
       if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) {
         Printf("INFO: found line matching '%s', exiting.\n",
                Options.ExitOnSrcPos.c_str());

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp?rev=354076&r1=354075&r2=354076&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp Thu Feb 14 15:12:33 2019
@@ -42,10 +42,12 @@ void Merger::ParseOrExit(std::istream &I
 // file1
 // file2  # One file name per line.
 // STARTED 0 123  # FileID, file size
-// DONE 0 1 4 6 8  # FileID COV1 COV2 ...
-// STARTED 1 456  # If DONE is missing, the input crashed while processing.
+// FT 0 1 4 6 8  # FileID COV1 COV2 ...
+// COV 0 7 8 9 # FileID COV1 COV1
+// STARTED 1 456  # If FT is missing, the input crashed while processing.
 // STARTED 2 567
-// DONE 2 8 9
+// FT 2 8 9
+// COV 2 11 12
 bool Merger::Parse(std::istream &IS, bool ParseCoverage) {
   LastFailure.clear();
   std::string Line;
@@ -70,11 +72,12 @@ bool Merger::Parse(std::istream &IS, boo
     if (!std::getline(IS, Files[i].Name, '\n'))
       return false;
 
-  // Parse STARTED and DONE lines.
+  // Parse STARTED, FT, and COV lines.
   size_t ExpectedStartMarker = 0;
   const size_t kInvalidStartMarker = -1;
   size_t LastSeenStartMarker = kInvalidStartMarker;
   Vector<uint32_t> TmpFeatures;
+  Set<uintptr_t> PCs;
   while (std::getline(IS, Line, '\n')) {
     std::istringstream ISS1(Line);
     std::string Marker;
@@ -89,8 +92,8 @@ bool Merger::Parse(std::istream &IS, boo
       LastSeenStartMarker = ExpectedStartMarker;
       assert(ExpectedStartMarker < Files.size());
       ExpectedStartMarker++;
-    } else if (Marker == "DONE") {
-      // DONE FILE_ID COV1 COV2 COV3 ...
+    } else if (Marker == "FT") {
+      // FT FILE_ID COV1 COV2 COV3 ...
       size_t CurrentFileIdx = N;
       if (CurrentFileIdx != LastSeenStartMarker)
         return false;
@@ -102,6 +105,11 @@ bool Merger::Parse(std::istream &IS, boo
         std::sort(TmpFeatures.begin(), TmpFeatures.end());
         Files[CurrentFileIdx].Features = TmpFeatures;
       }
+    } else if (Marker == "COV") {
+      if (ParseCoverage)
+        while (ISS1 >> std::hex >> N)
+          if (PCs.insert(N).second)
+            NumCoveredPCs++;
     } else {
       return false;
     }
@@ -199,6 +207,7 @@ void Fuzzer::CrashResistantMergeInternal
 
   std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app);
   Set<size_t> AllFeatures;
+  Set<const TracePC::PCTableEntry *> AllPCs;
   for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) {
     Fuzzer::MaybeExitGracefully();
     auto U = FileToVector(M.Files[i].Name);
@@ -223,16 +232,24 @@ void Fuzzer::CrashResistantMergeInternal
       if (AllFeatures.insert(Feature).second)
         UniqFeatures.insert(Feature);
     });
+    TPC.UpdateObservedPCs();
     // Show stats.
     if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)))
       PrintStats("pulse ");
     // Write the post-run marker and the coverage.
-    OF << "DONE " << i;
+    OF << "FT " << i;
     for (size_t F : UniqFeatures)
       OF << " " << std::hex << F;
     OF << "\n";
+    OF << "COV " << i;
+    TPC.ForEachObservedPC([&](const TracePC::PCTableEntry *TE) {
+      if (AllPCs.insert(TE).second)
+        OF << " " << TPC.PCTableEntryIdx(TE);
+    });
+    OF << "\n";
     OF.flush();
   }
+  PrintStats("DONE ");
 }
 
 static void WriteNewControlFile(const std::string &CFPath,

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerMerge.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerMerge.h?rev=354076&r1=354075&r2=354076&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerMerge.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerMerge.h Thu Feb 14 15:12:33 2019
@@ -56,6 +56,7 @@ struct MergeFileInfo {
 
 struct Merger {
   Vector<MergeFileInfo> Files;
+  size_t NumCoveredPCs = 0;
   size_t NumFilesInFirstCorpus = 0;
   size_t FirstNotProcessedFile = 0;
   std::string LastFailure;

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp?rev=354076&r1=354075&r2=354076&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp Thu Feb 14 15:12:33 2019
@@ -187,18 +187,19 @@ inline ALWAYS_INLINE uintptr_t GetNextIn
 
 void TracePC::UpdateObservedPCs() {
   Vector<uintptr_t> CoveredFuncs;
-  auto ObservePC = [&](uintptr_t PC) {
-    if (ObservedPCs.insert(PC).second && DoPrintNewPCs) {
-      PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", GetNextInstructionPc(PC));
+  auto ObservePC = [&](const PCTableEntry *TE) {
+    if (ObservedPCs.insert(TE).second && DoPrintNewPCs) {
+      PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p",
+              GetNextInstructionPc(TE->PC));
       Printf("\n");
     }
   };
 
-  auto Observe = [&](const PCTableEntry &TE) {
-    if (TE.PCFlags & 1)
-      if (++ObservedFuncs[TE.PC] == 1 && NumPrintNewFuncs)
-        CoveredFuncs.push_back(TE.PC);
-    ObservePC(TE.PC);
+  auto Observe = [&](const PCTableEntry *TE) {
+    if (TE->PCFlags & 1)
+      if (++ObservedFuncs[TE->PC] == 1 && NumPrintNewFuncs)
+        CoveredFuncs.push_back(TE->PC);
+    ObservePC(TE);
   };
 
   if (NumPCsInPCTables) {
@@ -212,7 +213,7 @@ void TracePC::UpdateObservedPCs() {
           if (!R.Enabled) continue;
           for (uint8_t *P = R.Start; P < R.Stop; P++)
             if (*P)
-              Observe(ModulePCTable[i].Start[M.Idx(P)]);
+              Observe(&ModulePCTable[i].Start[M.Idx(P)]);
         }
       }
     }
@@ -226,6 +227,17 @@ void TracePC::UpdateObservedPCs() {
   }
 }
 
+uintptr_t TracePC::PCTableEntryIdx(const PCTableEntry *TE) {
+  size_t TotalTEs = 0;
+  for (size_t i = 0; i < NumPCTables; i++) {
+    auto &M = ModulePCTable[i];
+    if (TE >= M.Start && TE < M.Stop)
+      return TotalTEs + TE - M.Start;
+    TotalTEs += M.Stop - M.Start;
+  }
+  assert(0);
+  return 0;
+}
 
 static std::string GetModuleName(uintptr_t PC) {
   char ModulePathRaw[4096] = "";  // What's PATH_MAX in portable C++?
@@ -303,7 +315,7 @@ void TracePC::PrintCoverage() {
     size_t NumEdges = Last - First;
     Vector<uintptr_t> UncoveredPCs;
     for (auto TE = First; TE < Last; TE++)
-      if (!ObservedPCs.count(TE->PC))
+      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);

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h?rev=354076&r1=354075&r2=354076&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h Thu Feb 14 15:12:33 2019
@@ -122,6 +122,12 @@ class TracePC {
   void ProtectLazyCounters();
   bool UnprotectLazyCounters(void *CounterPtr);
 
+  struct PCTableEntry {
+    uintptr_t PC, PCFlags;
+  };
+
+  uintptr_t PCTableEntryIdx(const PCTableEntry *TE);
+
 private:
   bool UseCounters = false;
   uint32_t UseValueProfileMask = false;
@@ -159,16 +165,11 @@ private:
         CB(Modules[m].Regions[r]);
   }
 
-
-  struct PCTableEntry {
-    uintptr_t PC, PCFlags;
-  };
-
   struct { const PCTableEntry *Start, *Stop; } ModulePCTable[4096];
   size_t NumPCTables;
   size_t NumPCsInPCTables;
 
-  Set<uintptr_t> ObservedPCs;
+  Set<const PCTableEntry*> ObservedPCs;
   std::unordered_map<uintptr_t, uintptr_t> ObservedFuncs;  // PC => Counter.
 
   uint8_t *FocusFunctionCounterPtr = nullptr;

Modified: compiler-rt/trunk/lib/fuzzer/tests/FuzzerUnittest.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/tests/FuzzerUnittest.cpp?rev=354076&r1=354075&r2=354076&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/tests/FuzzerUnittest.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/tests/FuzzerUnittest.cpp Thu Feb 14 15:12:33 2019
@@ -619,7 +619,7 @@ TEST(Merge, Bad) {
     "2\n2\nA\n",
     "2\n2\nA\nB\nC\n",
     "0\n0\n",
-    "1\n1\nA\nDONE 0",
+    "1\n1\nA\nFT 0",
     "1\n1\nA\nSTARTED 1",
   };
   Merger M;
@@ -670,9 +670,9 @@ TEST(Merge, Good) {
 
   EXPECT_TRUE(M.Parse("3\n1\nAA\nBB\nC\n"
                         "STARTED 0 1000\n"
-                        "DONE 0 1 2 3\n"
+                        "FT 0 1 2 3\n"
                         "STARTED 1 1001\n"
-                        "DONE 1 4 5 6 \n"
+                        "FT 1 4 5 6 \n"
                         "STARTED 2 1002\n"
                         "", true));
   EXPECT_EQ(M.Files.size(), 3U);
@@ -693,9 +693,9 @@ TEST(Merge, Good) {
   Set<uint32_t> NewFeatures;
 
   EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n"
-                        "STARTED 0 1000\nDONE 0 1 2 3\n"
-                        "STARTED 1 1001\nDONE 1 4 5 6 \n"
-                        "STARTED 2 1002\nDONE 2 6 1 3 \n"
+                        "STARTED 0 1000\nFT 0 1 2 3\n"
+                        "STARTED 1 1001\nFT 1 4 5 6 \n"
+                        "STARTED 2 1002\nFT 2 6 1 3 \n"
                         "", true));
   EXPECT_EQ(M.Files.size(), 3U);
   EXPECT_EQ(M.NumFilesInFirstCorpus, 2U);
@@ -708,9 +708,9 @@ TEST(Merge, Good) {
   EQ(NewFiles, {});
 
   EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n"
-                        "STARTED 0 1000\nDONE 0 1 2 3\n"
-                        "STARTED 1 1001\nDONE 1 4 5 6 \n"
-                        "STARTED 2 1002\nDONE 2 6 1 3\n"
+                        "STARTED 0 1000\nFT 0 1 2 3\n"
+                        "STARTED 1 1001\nFT 1 4 5 6 \n"
+                        "STARTED 2 1002\nFT 2 6 1 3\n"
                         "", true));
   EQ(M.Files[0].Features, {1, 2, 3});
   EQ(M.Files[1].Features, {4, 5, 6});
@@ -720,8 +720,8 @@ TEST(Merge, Good) {
 
   // Same as the above, but with InitialFeatures.
   EXPECT_TRUE(M.Parse("2\n0\nB\nC\n"
-                        "STARTED 0 1001\nDONE 0 4 5 6 \n"
-                        "STARTED 1 1002\nDONE 1 6 1 3\n"
+                        "STARTED 0 1001\nFT 0 4 5 6 \n"
+                        "STARTED 1 1002\nFT 1 6 1 3\n"
                         "", true));
   EQ(M.Files[0].Features, {4, 5, 6});
   EQ(M.Files[1].Features, {1, 3, 6});
@@ -736,29 +736,29 @@ TEST(Merge, Good) {
 TEST(Merge, Merge) {
 
   Merge("3\n1\nA\nB\nC\n"
-        "STARTED 0 1000\nDONE 0 1 2 3\n"
-        "STARTED 1 1001\nDONE 1 4 5 6 \n"
-        "STARTED 2 1002\nDONE 2 6 1 3 \n",
+        "STARTED 0 1000\nFT 0 1 2 3\n"
+        "STARTED 1 1001\nFT 1 4 5 6 \n"
+        "STARTED 2 1002\nFT 2 6 1 3 \n",
         {"B"}, 3);
 
   Merge("3\n0\nA\nB\nC\n"
-        "STARTED 0 2000\nDONE 0 1 2 3\n"
-        "STARTED 1 1001\nDONE 1 4 5 6 \n"
-        "STARTED 2 1002\nDONE 2 6 1 3 \n",
+        "STARTED 0 2000\nFT 0 1 2 3\n"
+        "STARTED 1 1001\nFT 1 4 5 6 \n"
+        "STARTED 2 1002\nFT 2 6 1 3 \n",
         {"A", "B", "C"}, 6);
 
   Merge("4\n0\nA\nB\nC\nD\n"
-        "STARTED 0 2000\nDONE 0 1 2 3\n"
-        "STARTED 1 1101\nDONE 1 4 5 6 \n"
-        "STARTED 2 1102\nDONE 2 6 1 3 100 \n"
-        "STARTED 3 1000\nDONE 3 1  \n",
+        "STARTED 0 2000\nFT 0 1 2 3\n"
+        "STARTED 1 1101\nFT 1 4 5 6 \n"
+        "STARTED 2 1102\nFT 2 6 1 3 100 \n"
+        "STARTED 3 1000\nFT 3 1  \n",
         {"A", "B", "C", "D"}, 7);
 
   Merge("4\n1\nA\nB\nC\nD\n"
-        "STARTED 0 2000\nDONE 0 4 5 6 7 8\n"
-        "STARTED 1 1100\nDONE 1 1 2 3 \n"
-        "STARTED 2 1100\nDONE 2 2 3 \n"
-        "STARTED 3 1000\nDONE 3 1  \n",
+        "STARTED 0 2000\nFT 0 4 5 6 7 8\n"
+        "STARTED 1 1100\nFT 1 1 2 3 \n"
+        "STARTED 2 1100\nFT 2 2 3 \n"
+        "STARTED 3 1000\nFT 3 1  \n",
         {"B", "D"}, 3);
 }
 

Modified: compiler-rt/trunk/test/fuzzer/merge-control-file.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/merge-control-file.test?rev=354076&r1=354075&r2=354076&view=diff
==============================================================================
--- compiler-rt/trunk/test/fuzzer/merge-control-file.test (original)
+++ compiler-rt/trunk/test/fuzzer/merge-control-file.test Thu Feb 14 15:12:33 2019
@@ -32,9 +32,9 @@ OK_0: MERGE-OUTER: 3 new files with {{.*
 RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1
 RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF
 RUN: echo STARTED 0 1 >> %t/MCF
-RUN: echo DONE 0 11 >> %t/MCF
+RUN: echo FT 0 11 >> %t/MCF
 RUN: echo STARTED 1 2 >> %t/MCF
-RUN: echo DONE 1 12 >> %t/MCF
+RUN: echo FT 1 12 >> %t/MCF
 RUN: %run %t/T.exe -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_2
 OK_2: MERGE-OUTER: control file ok, 3 files total, first not processed file 2
 OK_2: MERGE-OUTER: 3 new files with {{.*}} new features added
@@ -42,10 +42,10 @@ OK_2: MERGE-OUTER: 3 new files with {{.*
 RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1
 RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF
 RUN: echo STARTED 0 1 >> %t/MCF
-RUN: echo DONE 0 11 >> %t/MCF
+RUN: echo FT 0 11 >> %t/MCF
 RUN: echo STARTED 1 2 >> %t/MCF
-RUN: echo DONE 1 12 >> %t/MCF
+RUN: echo FT 1 12 >> %t/MCF
 RUN: echo STARTED 2 2 >> %t/MCF
-RUN: echo DONE 2 13 >> %t/MCF
+RUN: echo FT 2 13 >> %t/MCF
 RUN: %run %t/T.exe -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_3
 OK_3: MERGE-OUTER: nothing to do, merge has been completed before

Modified: compiler-rt/trunk/test/fuzzer/merge-sigusr.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/merge-sigusr.test?rev=354076&r1=354075&r2=354076&view=diff
==============================================================================
--- compiler-rt/trunk/test/fuzzer/merge-sigusr.test (original)
+++ compiler-rt/trunk/test/fuzzer/merge-sigusr.test Thu Feb 14 15:12:33 2019
@@ -22,7 +22,8 @@ RUN: sleep 3
 RUN: cat %t/log | FileCheck %s
 RUN: grep C2/g %t/MCF
 RUN: grep STARTED %t/MCF
-RUN: tail -n 1 %t/MCF | grep DONE
+RUN: tail -n 2 %t/MCF | grep FT
+RUN: tail -n 1 %t/MCF | grep COV
 
 CHECK: INFO: signal received, trying to exit gracefully
 CHECK: INFO: libFuzzer: exiting as requested

Modified: compiler-rt/trunk/test/fuzzer/merge.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/merge.test?rev=354076&r1=354075&r2=354076&view=diff
==============================================================================
--- compiler-rt/trunk/test/fuzzer/merge.test (original)
+++ compiler-rt/trunk/test/fuzzer/merge.test Thu Feb 14 15:12:33 2019
@@ -44,7 +44,7 @@ RUN: cp %t/T0/* %t/T1/
 RUN: rm -f %t/MCF
 RUN: %run %t-FullCoverageSetTest -merge=1 -merge_control_file=%t/MCF %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=MCF
 RUN: grep STARTED %t/MCF
-RUN: grep DONE %t/MCF
+RUN: grep FT %t/MCF
 MCF: MERGE-INNER: using the control file {{.*}}MCF
 MCF: MERGE-OUTER: 3 new files
 




More information about the llvm-commits mailing list