mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-10 22:46:20 +00:00
[libFuzzer] move value profiling logic into TracePC
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282219 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
67446361c2
commit
5a965a68f3
@ -397,6 +397,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
|
|||||||
Options.UseIndirCalls = Flags.use_indir_calls;
|
Options.UseIndirCalls = Flags.use_indir_calls;
|
||||||
Options.UseMemcmp = Flags.use_memcmp;
|
Options.UseMemcmp = Flags.use_memcmp;
|
||||||
Options.UseMemmem = Flags.use_memmem;
|
Options.UseMemmem = Flags.use_memmem;
|
||||||
|
Options.UseValueProfile = Flags.use_value_profile;
|
||||||
Options.ShuffleAtStartUp = Flags.shuffle;
|
Options.ShuffleAtStartUp = Flags.shuffle;
|
||||||
Options.PreferSmall = Flags.prefer_small;
|
Options.PreferSmall = Flags.prefer_small;
|
||||||
Options.Reload = Flags.reload;
|
Options.Reload = Flags.reload;
|
||||||
@ -428,9 +429,6 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
|
|||||||
Options.PrintCoverage = Flags.print_coverage;
|
Options.PrintCoverage = Flags.print_coverage;
|
||||||
Options.PruneCorpus = Flags.prune_corpus;
|
Options.PruneCorpus = Flags.prune_corpus;
|
||||||
|
|
||||||
if (Flags.use_value_profile)
|
|
||||||
EnableValueProfile();
|
|
||||||
|
|
||||||
unsigned Seed = Flags.seed;
|
unsigned Seed = Flags.seed;
|
||||||
// Initialize Seed.
|
// Initialize Seed.
|
||||||
if (Seed == 0)
|
if (Seed == 0)
|
||||||
|
@ -29,10 +29,6 @@ namespace fuzzer {
|
|||||||
|
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
// See FuzzerTraceState.cpp
|
|
||||||
void EnableValueProfile();
|
|
||||||
bool VPMapMergeFromCurrent(ValueBitMap &M);
|
|
||||||
|
|
||||||
class Fuzzer {
|
class Fuzzer {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) {
|
|||||||
if (TPC.UpdateCounterMap(&C->TPCMap))
|
if (TPC.UpdateCounterMap(&C->TPCMap))
|
||||||
Res = true;
|
Res = true;
|
||||||
|
|
||||||
if (VPMapMergeFromCurrent(C->VPMap))
|
if (TPC.UpdateValueProfileMap(&C->VPMap))
|
||||||
Res = true;
|
Res = true;
|
||||||
|
|
||||||
if (EF->__sanitizer_get_coverage_pc_buffer_pos) {
|
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)
|
if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks)
|
||||||
EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
|
EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
|
||||||
TPC.SetUseCounters(Options.UseCounters);
|
TPC.SetUseCounters(Options.UseCounters);
|
||||||
|
TPC.SetUseValueProfile(Options.UseValueProfile);
|
||||||
|
|
||||||
if (Options.PrintNewCovPcs) {
|
if (Options.PrintNewCovPcs) {
|
||||||
PcBufferLen = 1 << 24;
|
PcBufferLen = 1 << 24;
|
||||||
|
@ -30,7 +30,7 @@ struct FuzzingOptions {
|
|||||||
bool UseIndirCalls = true;
|
bool UseIndirCalls = true;
|
||||||
bool UseMemcmp = true;
|
bool UseMemcmp = true;
|
||||||
bool UseMemmem = true;
|
bool UseMemmem = true;
|
||||||
bool UseFullCoverageSet = false;
|
bool UseValueProfile = false;
|
||||||
bool Reload = true;
|
bool Reload = true;
|
||||||
bool ShuffleAtStartUp = true;
|
bool ShuffleAtStartUp = true;
|
||||||
bool PreferSmall = true;
|
bool PreferSmall = true;
|
||||||
|
@ -22,11 +22,16 @@ class TracePC {
|
|||||||
void HandleTrace(uintptr_t *guard, uintptr_t PC);
|
void HandleTrace(uintptr_t *guard, uintptr_t PC);
|
||||||
void HandleInit(uintptr_t *start, uintptr_t *stop);
|
void HandleInit(uintptr_t *start, uintptr_t *stop);
|
||||||
void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
|
void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
|
||||||
|
void HandleValueProfile(size_t Value) { ValueProfileMap.AddValue(Value); }
|
||||||
size_t GetTotalCoverage() { return TotalCoverage; }
|
size_t GetTotalCoverage() { return TotalCoverage; }
|
||||||
void SetUseCounters(bool UC) { UseCounters = UC; }
|
void SetUseCounters(bool UC) { UseCounters = UC; }
|
||||||
|
void SetUseValueProfile(bool VP) { UseValueProfile = VP; }
|
||||||
bool UpdateCounterMap(ValueBitMap *MaxCounterMap) {
|
bool UpdateCounterMap(ValueBitMap *MaxCounterMap) {
|
||||||
return UseCounters && MaxCounterMap->MergeFrom(CounterMap);
|
return UseCounters && MaxCounterMap->MergeFrom(CounterMap);
|
||||||
}
|
}
|
||||||
|
bool UpdateValueProfileMap(ValueBitMap *MaxValueProfileMap) {
|
||||||
|
return UseValueProfile && MaxValueProfileMap->MergeFrom(ValueProfileMap);
|
||||||
|
}
|
||||||
void FinalizeTrace();
|
void FinalizeTrace();
|
||||||
|
|
||||||
size_t GetNewPCIDs(uintptr_t **NewPCIDsPtr) {
|
size_t GetNewPCIDs(uintptr_t **NewPCIDsPtr) {
|
||||||
@ -51,6 +56,7 @@ class TracePC {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool UseCounters = false;
|
bool UseCounters = false;
|
||||||
|
bool UseValueProfile = false;
|
||||||
size_t TotalCoverage = 0;
|
size_t TotalCoverage = 0;
|
||||||
|
|
||||||
static const size_t kMaxNewPCIDs = 64;
|
static const size_t kMaxNewPCIDs = 64;
|
||||||
@ -77,6 +83,7 @@ private:
|
|||||||
uintptr_t PCs[kNumPCs];
|
uintptr_t PCs[kNumPCs];
|
||||||
|
|
||||||
ValueBitMap CounterMap;
|
ValueBitMap CounterMap;
|
||||||
|
ValueBitMap ValueProfileMap;
|
||||||
ValueBitMap TotalCoverageMap;
|
ValueBitMap TotalCoverageMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
#include "FuzzerDictionary.h"
|
#include "FuzzerDictionary.h"
|
||||||
#include "FuzzerMutate.h"
|
#include "FuzzerMutate.h"
|
||||||
#include "FuzzerRandom.h"
|
#include "FuzzerRandom.h"
|
||||||
|
#include "FuzzerTracePC.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -175,7 +176,6 @@ struct TraceBasedMutation {
|
|||||||
// Declared as static globals for faster checks inside the hooks.
|
// Declared as static globals for faster checks inside the hooks.
|
||||||
static bool RecordingMemcmp = false;
|
static bool RecordingMemcmp = false;
|
||||||
static bool RecordingMemmem = false;
|
static bool RecordingMemmem = false;
|
||||||
static bool RecordingValueProfile = false;
|
|
||||||
static bool DoingMyOwnMemmem = false;
|
static bool DoingMyOwnMemmem = false;
|
||||||
|
|
||||||
struct ScopedDoingMyOwnMemmem {
|
struct ScopedDoingMyOwnMemmem {
|
||||||
@ -532,21 +532,13 @@ static size_t InternalStrnlen(const char *S, size_t MaxLen) {
|
|||||||
|
|
||||||
// Value profile.
|
// Value profile.
|
||||||
// We keep track of various values that affect control flow.
|
// 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.
|
// 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
|
// For memcmp/strcmp/etc the interesting value is the length of the common
|
||||||
// prefix of the parameters.
|
// prefix of the parameters.
|
||||||
// For cmp instructions the interesting value is a XOR 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.
|
// 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,
|
static void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
|
||||||
size_t n) {
|
size_t n) {
|
||||||
@ -562,7 +554,7 @@ static void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
|
|||||||
size_t Idx = I;
|
size_t Idx = I;
|
||||||
// if (I < Len)
|
// if (I < Len)
|
||||||
// Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1;
|
// 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,
|
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;
|
size_t Idx = I;
|
||||||
// if (I < Len && A1[I])
|
// if (I < Len && A1[I])
|
||||||
// Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1;
|
// Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1;
|
||||||
VP.AddValue((PC & 4095) | (Idx << 12));
|
TPC.HandleValueProfile((PC & 4095) | (Idx << 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
ATTRIBUTE_TARGET_POPCNT
|
ATTRIBUTE_TARGET_POPCNT
|
||||||
@ -589,7 +581,7 @@ static void AddValueForCmp(void *PCptr, uint64_t Arg1, uint64_t Arg2) {
|
|||||||
uintptr_t PC = reinterpret_cast<uintptr_t>(PCptr);
|
uintptr_t PC = reinterpret_cast<uintptr_t>(PCptr);
|
||||||
uint64_t ArgDistance = __builtin_popcountl(Arg1 ^ Arg2) - 1; // [0,63]
|
uint64_t ArgDistance = __builtin_popcountl(Arg1 ^ Arg2) - 1; // [0,63]
|
||||||
uintptr_t Idx = (PC & 4095) | (ArgDistance << 12);
|
uintptr_t Idx = (PC & 4095) | (ArgDistance << 12);
|
||||||
VP.AddValue(Idx);
|
TPC.HandleValueProfile(Idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddValueForSingleVal(void *PCptr, uintptr_t Val) {
|
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<uintptr_t>(PCptr);
|
uintptr_t PC = reinterpret_cast<uintptr_t>(PCptr);
|
||||||
uint64_t ArgDistance = __builtin_popcountl(Val) - 1; // [0,63]
|
uint64_t ArgDistance = __builtin_popcountl(Val) - 1; // [0,63]
|
||||||
uintptr_t Idx = (PC & 4095) | (ArgDistance << 12);
|
uintptr_t Idx = (PC & 4095) | (ArgDistance << 12);
|
||||||
VP.AddValue(Idx);
|
TPC.HandleValueProfile(Idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzer
|
} // namespace fuzzer
|
||||||
|
|
||||||
using fuzzer::TS;
|
using fuzzer::TS;
|
||||||
using fuzzer::RecordingMemcmp;
|
using fuzzer::RecordingMemcmp;
|
||||||
using fuzzer::RecordingValueProfile;
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void __dfsw___sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
|
void __dfsw___sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
|
||||||
@ -670,7 +661,6 @@ void dfsan_weak_hook_strcmp(void *caller_pc, const char *s1, const char *s2,
|
|||||||
#if LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
|
#if LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
|
||||||
void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
|
void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
|
||||||
const void *s2, size_t n, int result) {
|
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 (!RecordingMemcmp) return;
|
||||||
if (result == 0) return; // No reason to mutate.
|
if (result == 0) return; // No reason to mutate.
|
||||||
@ -681,7 +671,6 @@ void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
|
|||||||
|
|
||||||
void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
|
void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
|
||||||
const char *s2, size_t n, int result) {
|
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 (!RecordingMemcmp) return;
|
||||||
if (result == 0) return; // No reason to mutate.
|
if (result == 0) return; // No reason to mutate.
|
||||||
@ -696,7 +685,6 @@ void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
|
|||||||
|
|
||||||
void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
|
void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
|
||||||
const char *s2, int result) {
|
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 (!RecordingMemcmp) return;
|
||||||
if (result == 0) return; // No reason to mutate.
|
if (result == 0) return; // No reason to mutate.
|
||||||
@ -736,7 +724,6 @@ void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1,
|
|||||||
__attribute__((visibility("default")))
|
__attribute__((visibility("default")))
|
||||||
void __sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
|
void __sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
|
||||||
uint64_t Arg2) {
|
uint64_t Arg2) {
|
||||||
if (RecordingValueProfile)
|
|
||||||
fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2);
|
fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user