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) {
private:
bool UseCounters = false;
+ bool UseValueProfile = false;
size_t TotalCoverage = 0;
static const size_t kMaxNewPCIDs = 64;
uintptr_t PCs[kNumPCs];
ValueBitMap CounterMap;
+ ValueBitMap ValueProfileMap;
ValueBitMap TotalCoverageMap;
};
#include "FuzzerDictionary.h"
#include "FuzzerMutate.h"
#include "FuzzerRandom.h"
+#include "FuzzerTracePC.h"
#include <algorithm>
#include <cstring>
// 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 {
// 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) {
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,
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
uintptr_t PC = reinterpret_cast<uintptr_t>(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) {
uintptr_t PC = reinterpret_cast<uintptr_t>(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,
#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.
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);
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);
__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")))