[llvm] r310771 - [libFuzzer] experimental support for Clang's coverage (fprofile-instr-generate), Linux-only

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 11 16:03:22 PDT 2017


Author: kcc
Date: Fri Aug 11 16:03:22 2017
New Revision: 310771

URL: http://llvm.org/viewvc/llvm-project?rev=310771&view=rev
Log:
[libFuzzer] experimental support for Clang's coverage (fprofile-instr-generate), Linux-only

Added:
    llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp
    llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test
Modified:
    llvm/trunk/lib/Fuzzer/CMakeLists.txt
    llvm/trunk/lib/Fuzzer/FuzzerDefs.h
    llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
    llvm/trunk/lib/Fuzzer/FuzzerTracePC.h

Modified: llvm/trunk/lib/Fuzzer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/CMakeLists.txt?rev=310771&r1=310770&r2=310771&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/CMakeLists.txt (original)
+++ llvm/trunk/lib/Fuzzer/CMakeLists.txt Fri Aug 11 16:03:22 2017
@@ -31,6 +31,7 @@ endif()
 
 if (LIBFUZZER_ENABLE)
   add_library(LLVMFuzzerNoMainObjects OBJECT
+      FuzzerClangCounters.cpp
       FuzzerCrossOver.cpp
       FuzzerDriver.cpp
       FuzzerExtFunctionsDlsym.cpp

Added: llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp?rev=310771&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp (added)
+++ llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp Fri Aug 11 16:03:22 2017
@@ -0,0 +1,49 @@
+//===- FuzzerExtraCounters.cpp - Extra coverage counters ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Coverage counters from Clang's SourceBasedCodeCoverage.
+//===----------------------------------------------------------------------===//
+
+// Support for SourceBasedCodeCoverage is experimental:
+// * Works only for the main binary, not DSOs yet.
+// * Works only on Linux.
+// * Does not implement print_pcs/print_coverage yet.
+// * Is not fully evaluated for performance and sensitivity.
+//   We expect large performance drop due to 64-bit counters,
+//   and *maybe* better sensitivity due to more fine-grained counters.
+//   Preliminary comparison on a single benchmark (RE2) shows
+//   a bit worse sensitivity though.
+
+#include "FuzzerDefs.h"
+
+#if LIBFUZZER_LINUX
+__attribute__((weak)) extern uint64_t __start___llvm_prf_cnts;
+__attribute__((weak)) extern uint64_t __stop___llvm_prf_cnts;
+namespace fuzzer {
+uint64_t *ClangCountersBegin() { return &__start___llvm_prf_cnts; }
+uint64_t *ClangCountersEnd() { return &__stop___llvm_prf_cnts; }
+}  // namespace fuzzer
+#else
+// TODO: Implement on Mac (if the data shows it's worth it).
+//__attribute__((visibility("hidden")))
+//extern uint64_t CountersStart __asm("section$start$__DATA$__llvm_prf_cnts");
+//__attribute__((visibility("hidden")))
+//extern uint64_t CountersEnd __asm("section$end$__DATA$__llvm_prf_cnts");
+namespace fuzzer {
+uint64_t *ClangCountersBegin() { return nullptr; }
+uint64_t *ClangCountersEnd() { return  nullptr; }
+}  // namespace fuzzer
+#endif
+
+namespace fuzzer {
+ATTRIBUTE_NO_SANITIZE_ALL
+void ClearClangCounters() {  // hand-written memset, don't asan-ify.
+  for (auto P = ClangCountersBegin(); P < ClangCountersEnd(); P++)
+    *P = 0;
+}
+}

Modified: llvm/trunk/lib/Fuzzer/FuzzerDefs.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDefs.h?rev=310771&r1=310770&r2=310771&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerDefs.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerDefs.h Fri Aug 11 16:03:22 2017
@@ -123,6 +123,10 @@ uint8_t *ExtraCountersBegin();
 uint8_t *ExtraCountersEnd();
 void ClearExtraCounters();
 
+uint64_t *ClangCountersBegin();
+uint64_t *ClangCountersEnd();
+void ClearClangCounters();
+
 }  // namespace fuzzer
 
 #endif  // LLVM_FUZZER_DEFS_H

Modified: llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp?rev=310771&r1=310770&r2=310771&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp Fri Aug 11 16:03:22 2017
@@ -126,6 +126,8 @@ void TracePC::PrintModuleInfo() {
       _Exit(1);
     }
   }
+  if (size_t NumClangCounters = ClangCountersEnd() - ClangCountersBegin())
+    Printf("INFO: %zd Clang Coverage Counters\n", NumClangCounters);
 }
 
 ATTRIBUTE_NO_SANITIZE_ALL
@@ -137,13 +139,12 @@ void TracePC::HandleCallerCallee(uintptr
 }
 
 void TracePC::UpdateObservedPCs() {
+  auto Observe = [&](uintptr_t PC) {
+    bool Inserted = ObservedPCs.insert(PC).second;
+    if (Inserted && DoPrintNewPCs)
+      PrintPC("\tNEW_PC: %p %F %L\n", "\tNEW_PC: %p\n", PC + 1);
+  };
   if (NumPCsInPCTables) {
-    auto Observe = [&](uintptr_t PC) {
-      bool Inserted = ObservedPCs.insert(PC).second;
-      if (Inserted && DoPrintNewPCs)
-        PrintPC("\tNEW_PC: %p %F %L\n", "\tNEW_PC: %p\n", PC + 1);
-    };
-
     if (NumInline8bitCounters == NumPCsInPCTables) {
       for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
         uint8_t *Beg = ModuleCounters[i].Start;
@@ -167,6 +168,13 @@ void TracePC::UpdateObservedPCs() {
       }
     }
   }
+  if (size_t NumClangCounters =
+      ClangCountersEnd() - ClangCountersBegin()) {
+    auto P = ClangCountersBegin();
+    for (size_t Idx = 0; Idx < NumClangCounters; Idx++)
+      if (P[Idx])
+        Observe((uintptr_t)Idx);
+  }
 }
 
 inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {

Modified: llvm/trunk/lib/Fuzzer/FuzzerTracePC.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTracePC.h?rev=310771&r1=310770&r2=310771&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerTracePC.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerTracePC.h Fri Aug 11 16:03:22 2017
@@ -91,6 +91,7 @@ class TracePC {
       memset(Counters(), 0, GetNumPCs());
     ClearExtraCounters();
     ClearInlineCounters();
+    ClearClangCounters();
   }
 
   void ClearInlineCounters();
@@ -196,14 +197,9 @@ void ForEachNonZeroByte(const uint8_t *B
       Handle8bitCounter(FirstFeature, P - Begin, V);
 }
 
-template <class Callback>  // bool Callback(size_t Feature)
-ATTRIBUTE_NO_SANITIZE_ADDRESS
-__attribute__((noinline))
-void TracePC::CollectFeatures(Callback HandleFeature) const {
-  uint8_t *Counters = this->Counters();
-  size_t N = GetNumPCs();
-  auto Handle8bitCounter = [&](size_t FirstFeature,
-                               size_t Idx, uint8_t Counter) {
+// Given a non-zero Counters returns a number in [0,7].
+template<class T>
+unsigned CounterToFeature(T Counter) {
     assert(Counter);
     unsigned Bit = 0;
     /**/ if (Counter >= 128) Bit = 7;
@@ -213,7 +209,18 @@ void TracePC::CollectFeatures(Callback H
     else if (Counter >= 4) Bit = 3;
     else if (Counter >= 3) Bit = 2;
     else if (Counter >= 2) Bit = 1;
-    HandleFeature(FirstFeature + Idx * 8 + Bit);
+    return Bit;
+}
+
+template <class Callback>  // bool Callback(size_t Feature)
+ATTRIBUTE_NO_SANITIZE_ADDRESS
+__attribute__((noinline))
+void TracePC::CollectFeatures(Callback HandleFeature) const {
+  uint8_t *Counters = this->Counters();
+  size_t N = GetNumPCs();
+  auto Handle8bitCounter = [&](size_t FirstFeature,
+                               size_t Idx, uint8_t Counter) {
+    HandleFeature(FirstFeature + Idx * 8 + CounterToFeature(Counter));
   };
 
   size_t FirstFeature = 0;
@@ -231,6 +238,14 @@ void TracePC::CollectFeatures(Callback H
     }
   }
 
+  if (size_t NumClangCounters = ClangCountersEnd() - ClangCountersBegin()) {
+    auto P = ClangCountersBegin();
+    for (size_t Idx = 0; Idx < NumClangCounters; Idx++)
+      if (auto Cnt = P[Idx])
+        HandleFeature(FirstFeature + Idx * 8 + CounterToFeature(Cnt));
+    FirstFeature += NumClangCounters;
+  }
+
   ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), FirstFeature,
                      Handle8bitCounter);
   FirstFeature += (ExtraCountersEnd() - ExtraCountersBegin()) * 8;

Added: llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test?rev=310771&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test (added)
+++ llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test Fri Aug 11 16:03:22 2017
@@ -0,0 +1,7 @@
+# Test libFuzzer + -fprofile-instr-generate
+REQUIRES: linux
+RUN: %cpp_compiler %S/SimpleTest.cpp -fsanitize-coverage=0 -fprofile-instr-generate -o %t-SimpleTest-fprofile-instr-generate
+CHECK-NOT: INFO: Loaded 1 modules
+CHECK: INFO: {{.*}} Clang Coverage Counters
+CHECK: BINGO
+RUN: not %t-SimpleTest-fprofile-instr-generate -runs=1000000 -seed=1 2>&1 | FileCheck %s




More information about the llvm-commits mailing list