From 5a965a68f349b80dd2a933ebf46c5ce1976caa47 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Fri, 23 Sep 2016 00:46:18 +0000 Subject: [PATCH] [libFuzzer] move value profiling logic into TracePC git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282219 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Fuzzer/FuzzerDriver.cpp | 4 +--- lib/Fuzzer/FuzzerInternal.h | 4 ---- lib/Fuzzer/FuzzerLoop.cpp | 3 ++- lib/Fuzzer/FuzzerOptions.h | 2 +- lib/Fuzzer/FuzzerTracePC.h | 7 +++++++ lib/Fuzzer/FuzzerTraceState.cpp | 33 ++++++++++----------------------- 6 files changed, 21 insertions(+), 32 deletions(-) diff --git a/lib/Fuzzer/FuzzerDriver.cpp b/lib/Fuzzer/FuzzerDriver.cpp index 24f2bed2e7e..f077d902d12 100644 --- a/lib/Fuzzer/FuzzerDriver.cpp +++ b/lib/Fuzzer/FuzzerDriver.cpp @@ -397,6 +397,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { Options.UseIndirCalls = Flags.use_indir_calls; Options.UseMemcmp = Flags.use_memcmp; Options.UseMemmem = Flags.use_memmem; + Options.UseValueProfile = Flags.use_value_profile; Options.ShuffleAtStartUp = Flags.shuffle; Options.PreferSmall = Flags.prefer_small; Options.Reload = Flags.reload; @@ -428,9 +429,6 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { Options.PrintCoverage = Flags.print_coverage; Options.PruneCorpus = Flags.prune_corpus; - if (Flags.use_value_profile) - EnableValueProfile(); - unsigned Seed = Flags.seed; // Initialize Seed. if (Seed == 0) diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index 12a160d2296..7574e22347f 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -29,10 +29,6 @@ namespace fuzzer { using namespace std::chrono; -// See FuzzerTraceState.cpp -void EnableValueProfile(); -bool VPMapMergeFromCurrent(ValueBitMap &M); - class Fuzzer { public: diff --git a/lib/Fuzzer/FuzzerLoop.cpp b/lib/Fuzzer/FuzzerLoop.cpp index 781266a4d98..1d714cadd48 100644 --- a/lib/Fuzzer/FuzzerLoop.cpp +++ b/lib/Fuzzer/FuzzerLoop.cpp @@ -115,7 +115,7 @@ bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) { if (TPC.UpdateCounterMap(&C->TPCMap)) Res = true; - if (VPMapMergeFromCurrent(C->VPMap)) + if (TPC.UpdateValueProfileMap(&C->VPMap)) Res = true; if (EF->__sanitizer_get_coverage_pc_buffer_pos) { @@ -168,6 +168,7 @@ Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks) EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook); TPC.SetUseCounters(Options.UseCounters); + TPC.SetUseValueProfile(Options.UseValueProfile); if (Options.PrintNewCovPcs) { PcBufferLen = 1 << 24; diff --git a/lib/Fuzzer/FuzzerOptions.h b/lib/Fuzzer/FuzzerOptions.h index 2c0970647e1..cb3679d6a85 100644 --- a/lib/Fuzzer/FuzzerOptions.h +++ b/lib/Fuzzer/FuzzerOptions.h @@ -30,7 +30,7 @@ struct FuzzingOptions { bool UseIndirCalls = true; bool UseMemcmp = true; bool UseMemmem = true; - bool UseFullCoverageSet = false; + bool UseValueProfile = false; bool Reload = true; bool ShuffleAtStartUp = true; bool PreferSmall = true; diff --git a/lib/Fuzzer/FuzzerTracePC.h b/lib/Fuzzer/FuzzerTracePC.h index 079f734c742..f3da724c269 100644 --- a/lib/Fuzzer/FuzzerTracePC.h +++ b/lib/Fuzzer/FuzzerTracePC.h @@ -22,11 +22,16 @@ class TracePC { void HandleTrace(uintptr_t *guard, uintptr_t PC); void HandleInit(uintptr_t *start, uintptr_t *stop); void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee); + void HandleValueProfile(size_t Value) { ValueProfileMap.AddValue(Value); } size_t GetTotalCoverage() { return TotalCoverage; } void SetUseCounters(bool UC) { UseCounters = UC; } + void SetUseValueProfile(bool VP) { UseValueProfile = VP; } bool UpdateCounterMap(ValueBitMap *MaxCounterMap) { return UseCounters && MaxCounterMap->MergeFrom(CounterMap); } + bool UpdateValueProfileMap(ValueBitMap *MaxValueProfileMap) { + return UseValueProfile && MaxValueProfileMap->MergeFrom(ValueProfileMap); + } void FinalizeTrace(); size_t GetNewPCIDs(uintptr_t **NewPCIDsPtr) { @@ -51,6 +56,7 @@ class TracePC { private: bool UseCounters = false; + bool UseValueProfile = false; size_t TotalCoverage = 0; static const size_t kMaxNewPCIDs = 64; @@ -77,6 +83,7 @@ private: uintptr_t PCs[kNumPCs]; ValueBitMap CounterMap; + ValueBitMap ValueProfileMap; ValueBitMap TotalCoverageMap; }; diff --git a/lib/Fuzzer/FuzzerTraceState.cpp b/lib/Fuzzer/FuzzerTraceState.cpp index 902a1896d2c..97d5935008b 100644 --- a/lib/Fuzzer/FuzzerTraceState.cpp +++ b/lib/Fuzzer/FuzzerTraceState.cpp @@ -75,6 +75,7 @@ #include "FuzzerDictionary.h" #include "FuzzerMutate.h" #include "FuzzerRandom.h" +#include "FuzzerTracePC.h" #include #include @@ -175,7 +176,6 @@ struct TraceBasedMutation { // Declared as static globals for faster checks inside the hooks. static bool RecordingMemcmp = false; static bool RecordingMemmem = false; -static bool RecordingValueProfile = false; static bool DoingMyOwnMemmem = false; struct ScopedDoingMyOwnMemmem { @@ -532,21 +532,13 @@ static size_t InternalStrnlen(const char *S, size_t MaxLen) { // Value profile. // We keep track of various values that affect control flow. -// These values are inserted into a bit-set-based hash map (ValueBitMap VP). +// These values are inserted into a bit-set-based hash map. // Every new bit in the map is treated as a new coverage. // // For memcmp/strcmp/etc the interesting value is the length of the common // prefix of the parameters. // For cmp instructions the interesting value is a XOR of the parameters. // The interesting value is mixed up with the PC and is then added to the map. -static ValueBitMap VP; - -void EnableValueProfile() { RecordingValueProfile = true; } - -bool VPMapMergeFromCurrent(ValueBitMap &M) { - if (!RecordingValueProfile) return 0; - return M.MergeFrom(VP); -} static void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, size_t n) { @@ -562,7 +554,7 @@ static void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, size_t Idx = I; // if (I < Len) // Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1; - VP.AddValue((PC & 4095) | (Idx << 12)); + TPC.HandleValueProfile((PC & 4095) | (Idx << 12)); } static void AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2, @@ -579,7 +571,7 @@ static void AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2, size_t Idx = I; // if (I < Len && A1[I]) // Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1; - VP.AddValue((PC & 4095) | (Idx << 12)); + TPC.HandleValueProfile((PC & 4095) | (Idx << 12)); } ATTRIBUTE_TARGET_POPCNT @@ -589,7 +581,7 @@ static void AddValueForCmp(void *PCptr, uint64_t Arg1, uint64_t Arg2) { uintptr_t PC = reinterpret_cast(PCptr); uint64_t ArgDistance = __builtin_popcountl(Arg1 ^ Arg2) - 1; // [0,63] uintptr_t Idx = (PC & 4095) | (ArgDistance << 12); - VP.AddValue(Idx); + TPC.HandleValueProfile(Idx); } static void AddValueForSingleVal(void *PCptr, uintptr_t Val) { @@ -597,14 +589,13 @@ static void AddValueForSingleVal(void *PCptr, uintptr_t Val) { uintptr_t PC = reinterpret_cast(PCptr); uint64_t ArgDistance = __builtin_popcountl(Val) - 1; // [0,63] uintptr_t Idx = (PC & 4095) | (ArgDistance << 12); - VP.AddValue(Idx); + TPC.HandleValueProfile(Idx); } } // namespace fuzzer using fuzzer::TS; using fuzzer::RecordingMemcmp; -using fuzzer::RecordingValueProfile; extern "C" { void __dfsw___sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1, @@ -670,8 +661,7 @@ void dfsan_weak_hook_strcmp(void *caller_pc, const char *s1, const char *s2, #if LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1, const void *s2, size_t n, int result) { - if (RecordingValueProfile) - fuzzer::AddValueForMemcmp(caller_pc, s1, s2, n); + fuzzer::AddValueForMemcmp(caller_pc, s1, s2, n); if (!RecordingMemcmp) return; if (result == 0) return; // No reason to mutate. if (n <= 1) return; // Not interesting. @@ -681,8 +671,7 @@ void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1, void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2, size_t n, int result) { - if (RecordingValueProfile) - fuzzer::AddValueForStrcmp(caller_pc, s1, s2, n); + fuzzer::AddValueForStrcmp(caller_pc, s1, s2, n); if (!RecordingMemcmp) return; if (result == 0) return; // No reason to mutate. size_t Len1 = fuzzer::InternalStrnlen(s1, n); @@ -696,8 +685,7 @@ void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1, void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1, const char *s2, int result) { - if (RecordingValueProfile) - fuzzer::AddValueForStrcmp(caller_pc, s1, s2, 64); + fuzzer::AddValueForStrcmp(caller_pc, s1, s2, 64); if (!RecordingMemcmp) return; if (result == 0) return; // No reason to mutate. size_t Len1 = strlen(s1); @@ -736,8 +724,7 @@ void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, __attribute__((visibility("default"))) void __sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1, uint64_t Arg2) { - if (RecordingValueProfile) - fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2); + fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2); } __attribute__((visibility("default"))) -- 2.50.1