[libFuzzer] Implement stat::stability_rate based on the percentage of unstable edges.
Summary:
Created a -print_unstable_stats flag.
When -print_unstable_stats=1, we run it 2 more times on interesting inputs poisoning unstable edges in an array.
On program termination, we run PrintUnstableStats() which will print a line with a stability percentage like AFL does.
Patch by Kyungtak Woo (@kevinwkt).
Reviewers: metzman, Dor1s, kcc, morehouse
Reviewed By: metzman, Dor1s, morehouse
Subscribers: delcypher, llvm-commits, #sanitizers, kcc, morehouse, Dor1s
Differential Revision: https://reviews.llvm.org/D49212
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer@337175 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/FuzzerTracePC.cpp b/FuzzerTracePC.cpp
index 4e0ff14..e12e6c5 100644
--- a/FuzzerTracePC.cpp
+++ b/FuzzerTracePC.cpp
@@ -59,6 +59,37 @@
return Res;
}
+// Initializes unstable counters by copying Inline8bitCounters to unstable
+// counters.
+void TracePC::InitializeUnstableCounters() {
+ if (NumInline8bitCounters && NumInline8bitCounters == NumPCsInPCTables) {
+ size_t UnstableIdx = 0;
+ for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
+ uint8_t *Beg = ModuleCounters[i].Start;
+ size_t Size = ModuleCounters[i].Stop - Beg;
+ assert(Size == (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start));
+ for (size_t j = 0; j < Size; j++, UnstableIdx++)
+ if (UnstableCounters[UnstableIdx] != kUnstableCounter)
+ UnstableCounters[UnstableIdx] = Beg[j];
+ }
+ }
+}
+
+// Compares the current counters with counters from previous runs
+// and records differences as unstable edges.
+void TracePC::UpdateUnstableCounters() {
+ if (NumInline8bitCounters && NumInline8bitCounters == NumPCsInPCTables) {
+ size_t UnstableIdx = 0;
+ for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
+ uint8_t *Beg = ModuleCounters[i].Start;
+ size_t Size = ModuleCounters[i].Stop - Beg;
+ assert(Size == (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start));
+ for (size_t j = 0; j < Size; j++, UnstableIdx++)
+ if (Beg[j] != UnstableCounters[UnstableIdx])
+ UnstableCounters[UnstableIdx] = kUnstableCounter;
+ }
+ }
+}
void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) {
if (Start == Stop) return;
@@ -310,6 +341,15 @@
}
}
+void TracePC::PrintUnstableStats() {
+ size_t count = 0;
+ for (size_t i = 0; i < NumInline8bitCounters; i++)
+ if (UnstableCounters[i] == kUnstableCounter)
+ count++;
+ Printf("stat::stability_rate: %.2f\n",
+ 100 - static_cast<float>(count * 100) / NumInline8bitCounters);
+}
+
// Value profile.
// We keep track of various values that affect control flow.
// These values are inserted into a bit-set-based hash map.
@@ -356,9 +396,9 @@
uint64_t ArgDistance = __builtin_popcountll(ArgXor) + 1; // [1,65]
uintptr_t Idx = ((PC & 4095) + 1) * ArgDistance;
if (sizeof(T) == 4)
- TORC4.Insert(ArgXor, Arg1, Arg2);
+ TORC4.Insert(ArgXor, Arg1, Arg2);
else if (sizeof(T) == 8)
- TORC8.Insert(ArgXor, Arg1, Arg2);
+ TORC8.Insert(ArgXor, Arg1, Arg2);
// TODO: remove these flags and instead use all metrics at once.
if (UseValueProfileMask & 1)
ValueProfileMap.AddValue(Idx);
@@ -589,7 +629,7 @@
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
- const char *s2, int result) {
+ const char *s2, int result) {
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
if (result == 0) return; // No reason to mutate.
size_t N = fuzzer::InternalStrnlen2(s1, s2);