[compiler-rt] r352603 - [libFuzzer] refactor the handling of instrumentation counters so that they are grouped in regions one full page each. Needed for future optimization. NFC

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 29 22:15:52 PST 2019


Author: kcc
Date: Tue Jan 29 22:15:52 2019
New Revision: 352603

URL: http://llvm.org/viewvc/llvm-project?rev=352603&view=rev
Log:
[libFuzzer] refactor the handling of instrumentation counters so that they are grouped in regions one full page each. Needed for future optimization. NFC

Added:
    compiler-rt/trunk/test/fuzzer/large.test
Modified:
    compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h
    compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp?rev=352603&r1=352602&r2=352603&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp Tue Jan 29 22:15:52 2019
@@ -37,12 +37,34 @@ size_t TracePC::GetTotalPCCoverage() {
 
 void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) {
   if (Start == Stop) return;
-  if (NumModulesWithInline8bitCounters &&
-      ModuleCounters[NumModulesWithInline8bitCounters-1].Start == Start) return;
-  assert(NumModulesWithInline8bitCounters <
-         sizeof(ModuleCounters) / sizeof(ModuleCounters[0]));
-  ModuleCounters[NumModulesWithInline8bitCounters++] = {Start, Stop};
-  NumInline8bitCounters += Stop - Start;
+  if (NumModules &&
+      Modules[NumModules - 1].Start() == Start)
+    return;
+  assert(NumModules <
+         sizeof(Modules) / sizeof(Modules[0]));
+  auto &M = Modules[NumModules++];
+  uint8_t *AlignedStart = RoundUpByPage(Start);
+  uint8_t *AlignedStop  = RoundDownByPage(Stop);
+  size_t NumFullPages = AlignedStop > AlignedStart ?
+                        (AlignedStop - AlignedStart) / PageSize() : 0;
+  bool NeedFirst = Start < AlignedStart || !NumFullPages;
+  bool NeedLast  = Stop > AlignedStop && AlignedStop >= AlignedStart;
+  M.NumRegions = NumFullPages + NeedFirst + NeedLast;;
+  assert(M.NumRegions > 0);
+  M.Regions = new Module::Region[M.NumRegions];
+  assert(M.Regions);
+  size_t R = 0;
+  if (NeedFirst)
+    M.Regions[R++] = {Start, std::min(Stop, AlignedStart), true, false};
+  for (uint8_t *P = AlignedStart; P < AlignedStop; P += PageSize())
+    M.Regions[R++] = {P, P + PageSize(), true, true};
+  if (NeedLast)
+    M.Regions[R++] = {AlignedStop, Stop, true, false};
+  assert(R == M.NumRegions);
+  assert(M.Size() == (size_t)(Stop - Start));
+  assert(M.Stop() == Stop);
+  assert(M.Start() == Start);
+  NumInline8bitCounters += M.Size();
 }
 
 void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) {
@@ -55,12 +77,12 @@ void TracePC::HandlePCsInit(const uintpt
 }
 
 void TracePC::PrintModuleInfo() {
-  if (NumModulesWithInline8bitCounters) {
+  if (NumModules) {
     Printf("INFO: Loaded %zd modules   (%zd inline 8-bit counters): ",
-           NumModulesWithInline8bitCounters, NumInline8bitCounters);
-    for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++)
-      Printf("%zd [%p, %p), ", ModuleCounters[i].Stop - ModuleCounters[i].Start,
-             ModuleCounters[i].Start, ModuleCounters[i].Stop);
+           NumModules, NumInline8bitCounters);
+    for (size_t i = 0; i < NumModules; i++)
+      Printf("%zd [%p, %p), ", Modules[i].Size(), Modules[i].Start(),
+             Modules[i].Stop());
     Printf("\n");
   }
   if (NumPCTables) {
@@ -142,14 +164,17 @@ void TracePC::UpdateObservedPCs() {
 
   if (NumPCsInPCTables) {
     if (NumInline8bitCounters == NumPCsInPCTables) {
-      for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
-        uint8_t *Beg = ModuleCounters[i].Start;
-        size_t Size = ModuleCounters[i].Stop - Beg;
-        assert(Size ==
+      for (size_t i = 0; i < NumModules; i++) {
+        auto &M = Modules[i];
+        assert(M.Size() ==
                (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start));
-        for (size_t j = 0; j < Size; j++)
-          if (Beg[j])
-            Observe(ModulePCTable[i].Start[j]);
+        for (size_t r = 0; r < M.NumRegions; r++) {
+          auto &R = M.Regions[r];
+          if (!R.Enabled) continue;
+          for (uint8_t *P = R.Start; P < R.Stop; P++)
+            if (*P)
+              Observe(ModulePCTable[i].Start[M.Idx(P)]);
+        }
       }
     }
   }
@@ -192,10 +217,10 @@ void TracePC::IterateCoveredFunctions(Ca
 
 void TracePC::SetFocusFunction(const std::string &FuncName) {
   // This function should be called once.
-  assert(FocusFunction.first > NumModulesWithInline8bitCounters);
+  assert(!FocusFunctionCounterPtr);
   if (FuncName.empty())
     return;
-  for (size_t M = 0; M < NumModulesWithInline8bitCounters; M++) {
+  for (size_t M = 0; M < NumModules; M++) {
     auto &PCTE = ModulePCTable[M];
     size_t N = PCTE.Stop - PCTE.Start;
     for (size_t I = 0; I < N; I++) {
@@ -205,22 +230,14 @@ void TracePC::SetFocusFunction(const std
         Name = Name.substr(3, std::string::npos);
       if (FuncName != Name) continue;
       Printf("INFO: Focus function is set to '%s'\n", Name.c_str());
-      FocusFunction = {M, I};
+      FocusFunctionCounterPtr = Modules[M].Start() + I;
       return;
     }
   }
 }
 
 bool TracePC::ObservedFocusFunction() {
-  size_t I = FocusFunction.first;
-  size_t J = FocusFunction.second;
-  if (I >= NumModulesWithInline8bitCounters)
-    return false;
-  auto &MC = ModuleCounters[I];
-  size_t Size = MC.Stop - MC.Start;
-  if (J >= Size)
-    return false;
-  return MC.Start[J] != 0;
+  return FocusFunctionCounterPtr && *FocusFunctionCounterPtr;
 }
 
 void TracePC::PrintCoverage() {
@@ -330,11 +347,10 @@ static size_t InternalStrnlen2(const cha
 }
 
 void TracePC::ClearInlineCounters() {
-  for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
-    uint8_t *Beg = ModuleCounters[i].Start;
-    size_t Size = ModuleCounters[i].Stop - Beg;
-    memset(Beg, 0, Size);
-  }
+  IterateCounterRegions([](const Module::Region &R){
+    if (R.Enabled)
+      memset(R.Start, 0, R.Stop - R.Start);
+  });
 }
 
 ATTRIBUTE_NO_SANITIZE_ALL

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h?rev=352603&r1=352602&r2=352603&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h Tue Jan 29 22:15:52 2019
@@ -125,10 +125,38 @@ private:
   bool DoPrintNewPCs = false;
   size_t NumPrintNewFuncs = 0;
 
-  struct { uint8_t *Start, *Stop; } ModuleCounters[4096];
-  size_t NumModulesWithInline8bitCounters;  // linker-initialized.
+  // Module represents the array of 8-bit counters split into regions
+  // such that every region, except maybe the first and the last one, is one
+  // full page.
+  struct Module {
+    struct Region {
+      uint8_t *Start, *Stop;
+      bool Enabled;
+      bool OneFullPage;
+    };
+    Region *Regions;
+    size_t NumRegions;
+    uint8_t *Start() { return Regions[0].Start; }
+    uint8_t *Stop()  { return Regions[NumRegions - 1].Stop; }
+    size_t Size()   { return Stop() - Start(); }
+    size_t  Idx(uint8_t *P) {
+      assert(P >= Start() && P < Stop());
+      return P - Start();
+    }
+  };
+
+  Module Modules[4096];
+  size_t NumModules;  // linker-initialized.
   size_t NumInline8bitCounters;
 
+  template <class Callback>
+  void IterateCounterRegions(Callback CB) {
+    for (size_t m = 0; m < NumModules; m++)
+      for (size_t r = 0; r < Modules[m].NumRegions; r++)
+        CB(Modules[m].Regions[r]);
+  }
+
+
   struct PCTableEntry {
     uintptr_t PC, PCFlags;
   };
@@ -140,7 +168,7 @@ private:
   Set<uintptr_t> ObservedPCs;
   std::unordered_map<uintptr_t, uintptr_t> ObservedFuncs;  // PC => Counter.
 
-  std::pair<size_t, size_t> FocusFunction = {-1, -1};  // Module and PC IDs.
+  uint8_t *FocusFunctionCounterPtr = nullptr;
 
   ValueBitMap ValueProfileMap;
   uintptr_t InitialStack;
@@ -149,7 +177,7 @@ private:
 template <class Callback>
 // void Callback(size_t FirstFeature, size_t Idx, uint8_t Value);
 ATTRIBUTE_NO_SANITIZE_ALL
-void ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End,
+size_t ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End,
                         size_t FirstFeature, Callback Handle8bitCounter) {
   typedef uintptr_t LargeType;
   const size_t Step = sizeof(LargeType) / sizeof(uint8_t);
@@ -171,6 +199,7 @@ void ForEachNonZeroByte(const uint8_t *B
   for (; P < End; P++)
     if (uint8_t V = *P)
       Handle8bitCounter(FirstFeature, P - Begin, V);
+  return End - Begin;
 }
 
 // Given a non-zero Counter returns a number in the range [0,7].
@@ -213,17 +242,18 @@ void TracePC::CollectFeatures(Callback H
 
   size_t FirstFeature = 0;
 
-  if (NumInline8bitCounters) {
-    for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
-      ForEachNonZeroByte(ModuleCounters[i].Start, ModuleCounters[i].Stop,
-                         FirstFeature, Handle8bitCounter);
-      FirstFeature += 8 * (ModuleCounters[i].Stop - ModuleCounters[i].Start);
+  for (size_t i = 0; i < NumModules; i++) {
+    for (size_t r = 0; r < Modules[i].NumRegions; r++) {
+      if (!Modules[i].Regions[r].Enabled) continue;
+      FirstFeature += 8 * ForEachNonZeroByte(Modules[i].Regions[r].Start,
+                                             Modules[i].Regions[r].Stop,
+                                             FirstFeature, Handle8bitCounter);
     }
   }
 
-  ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), FirstFeature,
-                     Handle8bitCounter);
-  FirstFeature += (ExtraCountersEnd() - ExtraCountersBegin()) * 8;
+  FirstFeature +=
+      8 * ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(),
+                             FirstFeature, Handle8bitCounter);
 
   if (UseValueProfileMask) {
     ValueProfileMap.ForEach([&](size_t Idx) {

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h?rev=352603&r1=352602&r2=352603&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerUtil.h Tue Jan 29 22:15:52 2019
@@ -87,6 +87,20 @@ size_t SimpleFastHash(const uint8_t *Dat
 
 inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; }
 
+inline size_t PageSize() { return 4096; }
+inline uint8_t *RoundUpByPage(uint8_t *P) {
+  uintptr_t X = reinterpret_cast<uintptr_t>(P);
+  size_t Mask = PageSize() - 1;
+  X = (X + Mask) & ~Mask;
+  return reinterpret_cast<uint8_t *>(X);
+}
+inline uint8_t *RoundDownByPage(uint8_t *P) {
+  uintptr_t X = reinterpret_cast<uintptr_t>(P);
+  size_t Mask = PageSize() - 1;
+  X = X & ~Mask;
+  return reinterpret_cast<uint8_t *>(X);
+}
+
 }  // namespace fuzzer
 
 #endif  // LLVM_FUZZER_UTIL_H

Added: compiler-rt/trunk/test/fuzzer/large.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/large.test?rev=352603&view=auto
==============================================================================
--- compiler-rt/trunk/test/fuzzer/large.test (added)
+++ compiler-rt/trunk/test/fuzzer/large.test Tue Jan 29 22:15:52 2019
@@ -0,0 +1,2 @@
+RUN: %cpp_compiler %S/LargeTest.cpp -o %t-LargeTest
+RUN: %run %t-LargeTest -runs=10000




More information about the llvm-commits mailing list