[compiler-rt] r352700 - [libFuzzer] experimental performance optimization -lazy_counters, off by default. Posix-only for now, tested on Linux

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 30 16:09:44 PST 2019


Author: kcc
Date: Wed Jan 30 16:09:43 2019
New Revision: 352700

URL: http://llvm.org/viewvc/llvm-project?rev=352700&view=rev
Log:
[libFuzzer] experimental performance optimization -lazy_counters, off by default. Posix-only for now, tested on Linux

Modified:
    compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def
    compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h
    compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h
    compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h
    compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h
    compiler-rt/trunk/lib/fuzzer/FuzzerUtilFuchsia.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerUtilPosix.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerUtilWindows.cpp
    compiler-rt/trunk/test/fuzzer/large.test

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp Wed Jan 30 16:09:43 2019
@@ -658,7 +658,10 @@ int FuzzerDriver(int *argc, char ***argv
   Options.HandleXfsz = Flags.handle_xfsz;
   Options.HandleUsr1 = Flags.handle_usr1;
   Options.HandleUsr2 = Flags.handle_usr2;
+  Options.LazyCounters = Flags.lazy_counters;
   SetSignalHandler(Options);
+  if (Options.LazyCounters)
+    TPC.ProtectLazyCounters();
 
   std::atexit(Fuzzer::StaticExitCallback);
 

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def Wed Jan 30 16:09:43 2019
@@ -117,6 +117,9 @@ FUZZER_FLAG_INT(handle_term, 1, "If 1, t
 FUZZER_FLAG_INT(handle_xfsz, 1, "If 1, try to intercept SIGXFSZ.")
 FUZZER_FLAG_INT(handle_usr1, 1, "If 1, try to intercept SIGUSR1.")
 FUZZER_FLAG_INT(handle_usr2, 1, "If 1, try to intercept SIGUSR2.")
+FUZZER_FLAG_INT(lazy_counters, 0, "If 1, a performance optimization is"
+    "enabled for the 8bit inline counters. "
+    "Requires that libFuzzer successfully installs its SEGV handler")
 FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; "
     "if 2, close stderr; if 3, close both. "
     "Be careful, this will also close e.g. stderr of asan.")

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h Wed Jan 30 16:09:43 2019
@@ -59,6 +59,7 @@ public:
   size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; }
 
   static void StaticAlarmCallback();
+  static void StaticSegvSignalCallback(void *Addr);
   static void StaticCrashSignalCallback();
   static void StaticExitCallback();
   static void StaticInterruptCallback();

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp Wed Jan 30 16:09:43 2019
@@ -205,6 +205,11 @@ void Fuzzer::StaticCrashSignalCallback()
   F->CrashCallback();
 }
 
+void Fuzzer::StaticSegvSignalCallback(void *Addr) {
+  if (TPC.UnprotectLazyCounters(Addr)) return;
+  StaticCrashSignalCallback();
+}
+
 void Fuzzer::StaticExitCallback() {
   assert(F);
   F->ExitCallback();

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h Wed Jan 30 16:09:43 2019
@@ -67,6 +67,7 @@ struct FuzzingOptions {
   bool HandleXfsz = false;
   bool HandleUsr1 = false;
   bool HandleUsr2 = false;
+  bool LazyCounters = false;
 };
 
 }  // namespace fuzzer

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp Wed Jan 30 16:09:43 2019
@@ -67,6 +67,45 @@ void TracePC::HandleInline8bitCountersIn
   NumInline8bitCounters += M.Size();
 }
 
+// Mark all full page counter regions as PROT_NONE and set Enabled=false.
+// The first time the instrumented code hits such a protected/disabled
+// counter region we should catch a SEGV and call UnprotectLazyCounters,
+// which will mark the page as PROT_READ|PROT_WRITE and set Enabled=true.
+//
+// Whenever other functions iterate over the counters they should ignore
+// regions with Enabled=false.
+void TracePC::ProtectLazyCounters() {
+  size_t NumPagesProtected = 0;
+  IterateCounterRegions([&](Module::Region &R) {
+    if (!R.OneFullPage) return;
+    if (Mprotect(R.Start, R.Stop - R.Start, false)) {
+      R.Enabled = false;
+      NumPagesProtected++;
+    }
+  });
+  if (NumPagesProtected)
+    Printf("INFO: %zd pages of counters where protected;"
+           " libFuzzer's SEGV handler must be installed\n",
+           NumPagesProtected);
+}
+
+bool TracePC::UnprotectLazyCounters(void *CounterPtr) {
+  // Printf("UnprotectLazyCounters: %p\n", CounterPtr);
+  if (!CounterPtr)
+    return false;
+  bool Done = false;
+  uint8_t *Addr = reinterpret_cast<uint8_t *>(CounterPtr);
+  IterateCounterRegions([&](Module::Region &R) {
+    if (!R.OneFullPage || R.Enabled || Done) return;
+    if (Addr >= R.Start && Addr < R.Stop)
+      if (Mprotect(R.Start, R.Stop - R.Start, true)) {
+        R.Enabled = true;
+        Done = true;
+      }
+  });
+  return Done;
+}
+
 void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) {
   const PCTableEntry *B = reinterpret_cast<const PCTableEntry *>(Start);
   const PCTableEntry *E = reinterpret_cast<const PCTableEntry *>(Stop);

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h Wed Jan 30 16:09:43 2019
@@ -119,6 +119,9 @@ class TracePC {
   void SetFocusFunction(const std::string &FuncName);
   bool ObservedFocusFunction();
 
+  void ProtectLazyCounters();
+  bool UnprotectLazyCounters(void *CounterPtr);
+
 private:
   bool UseCounters = false;
   uint32_t UseValueProfileMask = false;

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h Wed Jan 30 16:09:43 2019
@@ -52,6 +52,8 @@ void SetSignalHandler(const FuzzingOptio
 
 void SleepSeconds(int Seconds);
 
+bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite);
+
 unsigned long GetPid();
 
 size_t GetPeakRSSMb();

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerUtilFuchsia.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerUtilFuchsia.cpp?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerUtilFuchsia.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerUtilFuchsia.cpp Wed Jan 30 16:09:43 2019
@@ -287,6 +287,10 @@ void CrashHandler(zx_handle_t *Event) {
 
 } // namespace
 
+bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
+  return false;  // UNIMPLEMENTED
+}
+
 // Platform specific functions.
 void SetSignalHandler(const FuzzingOptions &Options) {
   // Set up alarm handler if needed.

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerUtilPosix.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerUtilPosix.cpp?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerUtilPosix.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerUtilPosix.cpp Wed Jan 30 16:09:43 2019
@@ -18,6 +18,7 @@
 #include <iomanip>
 #include <signal.h>
 #include <stdio.h>
+#include <sys/mman.h>
 #include <sys/resource.h>
 #include <sys/syscall.h>
 #include <sys/time.h>
@@ -31,6 +32,11 @@ static void AlarmHandler(int, siginfo_t
   Fuzzer::StaticAlarmCallback();
 }
 
+static void SegvHandler(int, siginfo_t *si, void *) {
+  assert(si->si_signo == SIGSEGV);
+  Fuzzer::StaticSegvSignalCallback(si->si_addr);
+}
+
 static void CrashHandler(int, siginfo_t *, void *) {
   Fuzzer::StaticCrashSignalCallback();
 }
@@ -64,6 +70,7 @@ static void SetSigaction(int signum,
   }
 
   sigact = {};
+  sigact.sa_flags = SA_SIGINFO;
   sigact.sa_sigaction = callback;
   if (sigaction(signum, &sigact, 0)) {
     Printf("libFuzzer: sigaction failed with %d\n", errno);
@@ -82,6 +89,11 @@ void SetTimer(int Seconds) {
   SetSigaction(SIGALRM, AlarmHandler);
 }
 
+bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
+  return 0 == mprotect(Ptr, Size,
+                       AllowReadWrite ? (PROT_READ | PROT_WRITE) : PROT_NONE);
+}
+
 void SetSignalHandler(const FuzzingOptions& Options) {
   if (Options.UnitTimeoutSec > 0)
     SetTimer(Options.UnitTimeoutSec / 2 + 1);
@@ -90,7 +102,7 @@ void SetSignalHandler(const FuzzingOptio
   if (Options.HandleTerm)
     SetSigaction(SIGTERM, InterruptHandler);
   if (Options.HandleSegv)
-    SetSigaction(SIGSEGV, CrashHandler);
+    SetSigaction(SIGSEGV, SegvHandler);
   if (Options.HandleBus)
     SetSigaction(SIGBUS, CrashHandler);
   if (Options.HandleAbrt)

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerUtilWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerUtilWindows.cpp?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerUtilWindows.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerUtilWindows.cpp Wed Jan 30 16:09:43 2019
@@ -111,6 +111,10 @@ static TimerQ Timer;
 
 static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
 
+bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
+  return false;  // UNIMPLEMENTED
+}
+
 void SetSignalHandler(const FuzzingOptions& Options) {
   HandlerOpt = &Options;
 

Modified: compiler-rt/trunk/test/fuzzer/large.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/large.test?rev=352700&r1=352699&r2=352700&view=diff
==============================================================================
--- compiler-rt/trunk/test/fuzzer/large.test (original)
+++ compiler-rt/trunk/test/fuzzer/large.test Wed Jan 30 16:09:43 2019
@@ -1,2 +1,6 @@
+REQUIRES: linux
 RUN: %cpp_compiler %S/LargeTest.cpp -o %t-LargeTest
 RUN: %run %t-LargeTest -runs=10000
+RUN: ASAN_OPTIONS=handle_segv=0 %run %t-LargeTest -runs=10000 -lazy_counters=1 2>&1 | FileCheck %s
+
+CHECK: pages of counters where protected; libFuzzer's SEGV handler must be installed




More information about the llvm-commits mailing list