mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-24 15:12:36 +00:00
[libfuzzer] Refactoring coverage state-management code.
It is now less state-dependent and will allow easier comparing of coverages of different units. Differential Revision: http://reviews.llvm.org/D20085 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269140 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3ddae02e7c
commit
0d68393b0f
@ -25,6 +25,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "FuzzerInterface.h"
|
#include "FuzzerInterface.h"
|
||||||
|
#include "FuzzerTracePC.h"
|
||||||
|
|
||||||
namespace fuzzer {
|
namespace fuzzer {
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
@ -112,13 +113,6 @@ int GetPid();
|
|||||||
int SignalToMainThread();
|
int SignalToMainThread();
|
||||||
void SleepSeconds(int Seconds);
|
void SleepSeconds(int Seconds);
|
||||||
|
|
||||||
// Clears the current PC Map.
|
|
||||||
void PcMapResetCurrent();
|
|
||||||
// Merges the current PC Map into the combined one, and clears the former.
|
|
||||||
void PcMapMergeCurrentToCombined();
|
|
||||||
// Returns the size of the combined PC Map.
|
|
||||||
size_t PcMapCombinedSize();
|
|
||||||
|
|
||||||
class Random {
|
class Random {
|
||||||
public:
|
public:
|
||||||
Random(unsigned int seed) : R(seed) {}
|
Random(unsigned int seed) : R(seed) {}
|
||||||
@ -309,6 +303,35 @@ public:
|
|||||||
bool PrintFinalStats = false;
|
bool PrintFinalStats = false;
|
||||||
bool DetectLeaks = true;
|
bool DetectLeaks = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Aggregates all available coverage measurements.
|
||||||
|
struct Coverage {
|
||||||
|
Coverage() { Reset(); }
|
||||||
|
|
||||||
|
void Reset() {
|
||||||
|
BlockCoverage = 0;
|
||||||
|
CallerCalleeCoverage = 0;
|
||||||
|
PcMapBits = 0;
|
||||||
|
CounterBitmapBits = 0;
|
||||||
|
PcBufferLen = 0;
|
||||||
|
CounterBitmap.clear();
|
||||||
|
PCMap.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DebugString() const;
|
||||||
|
|
||||||
|
size_t BlockCoverage;
|
||||||
|
size_t CallerCalleeCoverage;
|
||||||
|
|
||||||
|
size_t PcBufferLen;
|
||||||
|
// Precalculated number of bits in CounterBitmap.
|
||||||
|
size_t CounterBitmapBits;
|
||||||
|
std::vector<uint8_t> CounterBitmap;
|
||||||
|
// Precalculated number of bits in PCMap.
|
||||||
|
size_t PcMapBits;
|
||||||
|
PcCoverageMap PCMap;
|
||||||
|
};
|
||||||
|
|
||||||
Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options);
|
Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options);
|
||||||
void AddToCorpus(const Unit &U) {
|
void AddToCorpus(const Unit &U) {
|
||||||
Corpus.push_back(U);
|
Corpus.push_back(U);
|
||||||
@ -378,11 +401,8 @@ private:
|
|||||||
// Must be called whenever the corpus or unit weights are changed.
|
// Must be called whenever the corpus or unit weights are changed.
|
||||||
void UpdateCorpusDistribution();
|
void UpdateCorpusDistribution();
|
||||||
|
|
||||||
size_t RecordBlockCoverage();
|
|
||||||
size_t RecordCallerCalleeCoverage();
|
|
||||||
void PrepareCoverageBeforeRun();
|
|
||||||
bool CheckCoverageAfterRun();
|
|
||||||
void ResetCoverage();
|
void ResetCoverage();
|
||||||
|
bool UpdateMaxCoverage();
|
||||||
|
|
||||||
// Trace-based fuzzing: we run a unit with some kind of tracing
|
// Trace-based fuzzing: we run a unit with some kind of tracing
|
||||||
// enabled and record potentially useful mutations. Then
|
// enabled and record potentially useful mutations. Then
|
||||||
@ -410,16 +430,6 @@ private:
|
|||||||
|
|
||||||
std::vector<Unit> Corpus;
|
std::vector<Unit> Corpus;
|
||||||
std::unordered_set<std::string> UnitHashesAddedToCorpus;
|
std::unordered_set<std::string> UnitHashesAddedToCorpus;
|
||||||
|
|
||||||
// For UseCounters
|
|
||||||
std::vector<uint8_t> CounterBitmap;
|
|
||||||
size_t TotalBits() { // Slow. Call it only for printing stats.
|
|
||||||
size_t Res = 0;
|
|
||||||
for (auto x : CounterBitmap)
|
|
||||||
Res += __builtin_popcount(x);
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t> MutateInPlaceHere;
|
std::vector<uint8_t> MutateInPlaceHere;
|
||||||
|
|
||||||
std::piecewise_constant_distribution<double> CorpusDistribution;
|
std::piecewise_constant_distribution<double> CorpusDistribution;
|
||||||
@ -430,10 +440,9 @@ private:
|
|||||||
system_clock::time_point UnitStartTime;
|
system_clock::time_point UnitStartTime;
|
||||||
long TimeOfLongestUnitInSeconds = 0;
|
long TimeOfLongestUnitInSeconds = 0;
|
||||||
long EpochOfLastReadOfOutputCorpus = 0;
|
long EpochOfLastReadOfOutputCorpus = 0;
|
||||||
size_t LastRecordedBlockCoverage = 0;
|
|
||||||
size_t LastRecordedPcMapSize = 0;
|
// Maximum recorded coverage.
|
||||||
size_t LastRecordedCallerCalleeCoverage = 0;
|
Coverage MaxCoverage;
|
||||||
size_t LastCoveragePcBufferLen = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace fuzzer
|
}; // namespace fuzzer
|
||||||
|
@ -81,12 +81,83 @@ size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
|
|||||||
return F->GetMD().Mutate(Data, Size, MaxSize);
|
return F->GetMD().Mutate(Data, Size, MaxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CoverageController {
|
||||||
|
static void Reset() {
|
||||||
|
CHECK_WEAK_API_FUNCTION(__sanitizer_reset_coverage);
|
||||||
|
__sanitizer_reset_coverage();
|
||||||
|
PcMapResetCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ResetCounters(const Fuzzer::FuzzingOptions &Options) {
|
||||||
|
if (Options.UseCounters) {
|
||||||
|
__sanitizer_update_counter_bitset_and_clear_counters(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Prepare(const Fuzzer::FuzzingOptions &Options,
|
||||||
|
Fuzzer::Coverage *C) {
|
||||||
|
if (Options.UseCounters) {
|
||||||
|
size_t NumCounters = __sanitizer_get_number_of_counters();
|
||||||
|
C->CounterBitmap.resize(NumCounters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Records data to a maximum coverage tracker. Returns true if additional
|
||||||
|
// coverage was discovered.
|
||||||
|
static bool RecordMax(const Fuzzer::FuzzingOptions &Options,
|
||||||
|
Fuzzer::Coverage *C) {
|
||||||
|
bool Res = false;
|
||||||
|
|
||||||
|
uint64_t NewBlockCoverage = __sanitizer_get_total_unique_coverage();
|
||||||
|
if (NewBlockCoverage > C->BlockCoverage) {
|
||||||
|
Res = true;
|
||||||
|
C->BlockCoverage = NewBlockCoverage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Options.UseIndirCalls &&
|
||||||
|
__sanitizer_get_total_unique_caller_callee_pairs) {
|
||||||
|
uint64_t NewCallerCalleeCoverage =
|
||||||
|
__sanitizer_get_total_unique_caller_callee_pairs();
|
||||||
|
if (NewCallerCalleeCoverage > C->CallerCalleeCoverage) {
|
||||||
|
Res = true;
|
||||||
|
C->CallerCalleeCoverage = NewCallerCalleeCoverage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Options.UseCounters) {
|
||||||
|
uint64_t CounterDelta =
|
||||||
|
__sanitizer_update_counter_bitset_and_clear_counters(
|
||||||
|
C->CounterBitmap.data());
|
||||||
|
if (CounterDelta > 0) {
|
||||||
|
Res = true;
|
||||||
|
C->CounterBitmapBits += CounterDelta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t NewPcMapBits = PcMapMergeInto(&C->PCMap);
|
||||||
|
if (NewPcMapBits > C->PcMapBits) {
|
||||||
|
Res = true;
|
||||||
|
C->PcMapBits = NewPcMapBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t *CoverageBuf;
|
||||||
|
uint64_t NewPcBufferLen = __sanitizer_get_coverage_pc_buffer(&CoverageBuf);
|
||||||
|
if (NewPcBufferLen > C->PcBufferLen) {
|
||||||
|
Res = true;
|
||||||
|
C->PcBufferLen = NewPcBufferLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
|
Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
|
||||||
: CB(CB), MD(MD), Options(Options) {
|
: CB(CB), MD(MD), Options(Options) {
|
||||||
SetDeathCallback();
|
SetDeathCallback();
|
||||||
InitializeTraceState();
|
InitializeTraceState();
|
||||||
assert(!F);
|
assert(!F);
|
||||||
F = this;
|
F = this;
|
||||||
|
ResetCoverage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::SetDeathCallback() {
|
void Fuzzer::SetDeathCallback() {
|
||||||
@ -208,22 +279,21 @@ void Fuzzer::PrintStats(const char *Where, const char *End) {
|
|||||||
Printf("runs,block_cov,bits,cc_cov,corpus,execs_per_sec,tbms,reason\n");
|
Printf("runs,block_cov,bits,cc_cov,corpus,execs_per_sec,tbms,reason\n");
|
||||||
}
|
}
|
||||||
Printf("%zd,%zd,%zd,%zd,%zd,%zd,%s\n", TotalNumberOfRuns,
|
Printf("%zd,%zd,%zd,%zd,%zd,%zd,%s\n", TotalNumberOfRuns,
|
||||||
LastRecordedBlockCoverage, TotalBits(),
|
MaxCoverage.BlockCoverage, MaxCoverage.CounterBitmapBits,
|
||||||
LastRecordedCallerCalleeCoverage, Corpus.size(), ExecPerSec,
|
MaxCoverage.CallerCalleeCoverage, Corpus.size(), ExecPerSec, Where);
|
||||||
Where);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Options.Verbosity)
|
if (!Options.Verbosity)
|
||||||
return;
|
return;
|
||||||
Printf("#%zd\t%s", TotalNumberOfRuns, Where);
|
Printf("#%zd\t%s", TotalNumberOfRuns, Where);
|
||||||
if (LastRecordedBlockCoverage)
|
if (MaxCoverage.BlockCoverage)
|
||||||
Printf(" cov: %zd", LastRecordedBlockCoverage);
|
Printf(" cov: %zd", MaxCoverage.BlockCoverage);
|
||||||
if (LastRecordedPcMapSize)
|
if (MaxCoverage.PcMapBits)
|
||||||
Printf(" path: %zd", LastRecordedPcMapSize);
|
Printf(" path: %zd", MaxCoverage.PcMapBits);
|
||||||
if (auto TB = TotalBits())
|
if (auto TB = MaxCoverage.CounterBitmapBits)
|
||||||
Printf(" bits: %zd", TB);
|
Printf(" bits: %zd", TB);
|
||||||
if (LastRecordedCallerCalleeCoverage)
|
if (MaxCoverage.CallerCalleeCoverage)
|
||||||
Printf(" indir: %zd", LastRecordedCallerCalleeCoverage);
|
Printf(" indir: %zd", MaxCoverage.CallerCalleeCoverage);
|
||||||
Printf(" units: %zd exec/s: %zd", Corpus.size(), ExecPerSec);
|
Printf(" units: %zd exec/s: %zd", Corpus.size(), ExecPerSec);
|
||||||
Printf("%s", End);
|
Printf("%s", End);
|
||||||
}
|
}
|
||||||
@ -298,7 +368,7 @@ void Fuzzer::ShuffleAndMinimize() {
|
|||||||
if (RunOne(U)) {
|
if (RunOne(U)) {
|
||||||
NewCorpus.push_back(U);
|
NewCorpus.push_back(U);
|
||||||
if (Options.Verbosity >= 2)
|
if (Options.Verbosity >= 2)
|
||||||
Printf("NEW0: %zd L %zd\n", LastRecordedBlockCoverage, U.size());
|
Printf("NEW0: %zd L %zd\n", MaxCoverage.BlockCoverage, U.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Corpus = NewCorpus;
|
Corpus = NewCorpus;
|
||||||
@ -309,12 +379,29 @@ void Fuzzer::ShuffleAndMinimize() {
|
|||||||
CheckForMemoryLeaks();
|
CheckForMemoryLeaks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Fuzzer::UpdateMaxCoverage() {
|
||||||
|
uintptr_t PrevBufferLen = MaxCoverage.PcBufferLen;
|
||||||
|
bool Res = CoverageController::RecordMax(Options, &MaxCoverage);
|
||||||
|
|
||||||
|
if (Options.PrintNewCovPcs && PrevBufferLen != MaxCoverage.PcBufferLen) {
|
||||||
|
uintptr_t *CoverageBuf;
|
||||||
|
__sanitizer_get_coverage_pc_buffer(&CoverageBuf);
|
||||||
|
assert(CoverageBuf);
|
||||||
|
for (size_t I = PrevBufferLen; I < MaxCoverage.PcBufferLen; ++I) {
|
||||||
|
Printf("%p\n", CoverageBuf[I]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
bool Fuzzer::RunOne(const uint8_t *Data, size_t Size) {
|
bool Fuzzer::RunOne(const uint8_t *Data, size_t Size) {
|
||||||
TotalNumberOfRuns++;
|
TotalNumberOfRuns++;
|
||||||
|
|
||||||
PrepareCoverageBeforeRun();
|
// TODO(aizatsky): this Reset call seems to be not needed.
|
||||||
|
CoverageController::ResetCounters(Options);
|
||||||
ExecuteCallback(Data, Size);
|
ExecuteCallback(Data, Size);
|
||||||
bool Res = CheckCoverageAfterRun();
|
bool Res = UpdateMaxCoverage();
|
||||||
|
|
||||||
auto UnitStopTime = system_clock::now();
|
auto UnitStopTime = system_clock::now();
|
||||||
auto TimeOfUnit =
|
auto TimeOfUnit =
|
||||||
@ -378,61 +465,14 @@ void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
|
|||||||
assert(Res == 0);
|
assert(Res == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Fuzzer::RecordBlockCoverage() {
|
std::string Fuzzer::Coverage::DebugString() const {
|
||||||
CHECK_WEAK_API_FUNCTION(__sanitizer_get_total_unique_coverage);
|
std::string Result =
|
||||||
uintptr_t PrevCoverage = LastRecordedBlockCoverage;
|
std::string("Coverage{") + "BlockCoverage=" +
|
||||||
LastRecordedBlockCoverage = __sanitizer_get_total_unique_coverage();
|
std::to_string(BlockCoverage) + " CallerCalleeCoverage=" +
|
||||||
|
std::to_string(CallerCalleeCoverage) + " CounterBitmapBits=" +
|
||||||
if (PrevCoverage == LastRecordedBlockCoverage || !Options.PrintNewCovPcs)
|
std::to_string(CounterBitmapBits) + " PcMapBits=" +
|
||||||
return LastRecordedBlockCoverage;
|
std::to_string(PcMapBits) + "}";
|
||||||
|
return Result;
|
||||||
uintptr_t PrevBufferLen = LastCoveragePcBufferLen;
|
|
||||||
uintptr_t *CoverageBuf;
|
|
||||||
LastCoveragePcBufferLen = __sanitizer_get_coverage_pc_buffer(&CoverageBuf);
|
|
||||||
assert(CoverageBuf);
|
|
||||||
for (size_t i = PrevBufferLen; i < LastCoveragePcBufferLen; ++i) {
|
|
||||||
Printf("%p\n", CoverageBuf[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LastRecordedBlockCoverage;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Fuzzer::RecordCallerCalleeCoverage() {
|
|
||||||
if (!Options.UseIndirCalls)
|
|
||||||
return 0;
|
|
||||||
if (!__sanitizer_get_total_unique_caller_callee_pairs)
|
|
||||||
return 0;
|
|
||||||
return LastRecordedCallerCalleeCoverage =
|
|
||||||
__sanitizer_get_total_unique_caller_callee_pairs();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fuzzer::PrepareCoverageBeforeRun() {
|
|
||||||
if (Options.UseCounters) {
|
|
||||||
size_t NumCounters = __sanitizer_get_number_of_counters();
|
|
||||||
CounterBitmap.resize(NumCounters);
|
|
||||||
__sanitizer_update_counter_bitset_and_clear_counters(0);
|
|
||||||
}
|
|
||||||
RecordBlockCoverage();
|
|
||||||
RecordCallerCalleeCoverage();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Fuzzer::CheckCoverageAfterRun() {
|
|
||||||
size_t OldCoverage = LastRecordedBlockCoverage;
|
|
||||||
size_t NewCoverage = RecordBlockCoverage();
|
|
||||||
size_t OldCallerCalleeCoverage = LastRecordedCallerCalleeCoverage;
|
|
||||||
size_t NewCallerCalleeCoverage = RecordCallerCalleeCoverage();
|
|
||||||
size_t NumNewBits = 0;
|
|
||||||
size_t OldPcMapSize = LastRecordedPcMapSize;
|
|
||||||
PcMapMergeCurrentToCombined();
|
|
||||||
size_t NewPcMapSize = PcMapCombinedSize();
|
|
||||||
LastRecordedPcMapSize = NewPcMapSize;
|
|
||||||
if (NewPcMapSize > OldPcMapSize)
|
|
||||||
return true;
|
|
||||||
if (Options.UseCounters)
|
|
||||||
NumNewBits = __sanitizer_update_counter_bitset_and_clear_counters(
|
|
||||||
CounterBitmap.data());
|
|
||||||
return NewCoverage > OldCoverage ||
|
|
||||||
NewCallerCalleeCoverage > OldCallerCalleeCoverage || NumNewBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::WriteToOutputCorpus(const Unit &U) {
|
void Fuzzer::WriteToOutputCorpus(const Unit &U) {
|
||||||
@ -639,9 +679,9 @@ size_t Fuzzer::ChooseUnitIdxToMutate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::ResetCoverage() {
|
void Fuzzer::ResetCoverage() {
|
||||||
CHECK_WEAK_API_FUNCTION(__sanitizer_reset_coverage);
|
CoverageController::Reset();
|
||||||
__sanitizer_reset_coverage();
|
MaxCoverage.Reset();
|
||||||
CounterBitmap.clear();
|
CoverageController::Prepare(Options, &MaxCoverage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Experimental search heuristic: drilling.
|
// Experimental search heuristic: drilling.
|
||||||
|
@ -15,39 +15,43 @@
|
|||||||
#include "FuzzerInternal.h"
|
#include "FuzzerInternal.h"
|
||||||
|
|
||||||
namespace fuzzer {
|
namespace fuzzer {
|
||||||
static const size_t kMapSizeInBits = 65371; // Prime.
|
|
||||||
static const size_t kMapSizeInBitsAligned = 65536; // 2^16
|
void PcCoverageMap::Reset() { memset(Map, 0, sizeof(Map)); }
|
||||||
static const size_t kBitsInWord =(sizeof(uintptr_t) * 8);
|
|
||||||
static const size_t kMapSizeInWords = kMapSizeInBitsAligned / kBitsInWord;
|
void PcCoverageMap::Update(uintptr_t Addr) {
|
||||||
static uintptr_t CurrentMap[kMapSizeInWords] __attribute__((aligned(512)));
|
uintptr_t Idx = Addr % kMapSizeInBits;
|
||||||
static uintptr_t CombinedMap[kMapSizeInWords] __attribute__((aligned(512)));
|
uintptr_t WordIdx = Idx / kBitsInWord;
|
||||||
static size_t CombinedMapSize;
|
uintptr_t BitIdx = Idx % kBitsInWord;
|
||||||
|
Map[WordIdx] |= 1UL << BitIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PcCoverageMap::MergeFrom(const PcCoverageMap &Other) {
|
||||||
|
uintptr_t Res = 0;
|
||||||
|
for (size_t i = 0; i < kMapSizeInWords; i++)
|
||||||
|
Res += __builtin_popcountl(Map[i] |= Other.Map[i]);
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PcCoverageMap CurrentMap;
|
||||||
static thread_local uintptr_t Prev;
|
static thread_local uintptr_t Prev;
|
||||||
|
|
||||||
void PcMapResetCurrent() {
|
void PcMapResetCurrent() {
|
||||||
if (Prev) {
|
if (Prev) {
|
||||||
Prev = 0;
|
Prev = 0;
|
||||||
memset(CurrentMap, 0, sizeof(CurrentMap));
|
CurrentMap.Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcMapMergeCurrentToCombined() {
|
size_t PcMapMergeInto(PcCoverageMap *Map) {
|
||||||
if (!Prev) return;
|
if (!Prev)
|
||||||
uintptr_t Res = 0;
|
return 0;
|
||||||
for (size_t i = 0; i < kMapSizeInWords; i++)
|
return Map->MergeFrom(CurrentMap);
|
||||||
Res += __builtin_popcountl(CombinedMap[i] |= CurrentMap[i]);
|
|
||||||
CombinedMapSize = Res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PcMapCombinedSize() { return CombinedMapSize; }
|
|
||||||
|
|
||||||
static void HandlePC(uint32_t PC) {
|
static void HandlePC(uint32_t PC) {
|
||||||
// We take 12 bits of PC and mix it with the previous PCs.
|
// We take 12 bits of PC and mix it with the previous PCs.
|
||||||
uintptr_t Next = (Prev << 5) ^ (PC & 4095);
|
uintptr_t Next = (Prev << 5) ^ (PC & 4095);
|
||||||
uintptr_t Idx = Next % kMapSizeInBits;
|
CurrentMap.Update(Next);
|
||||||
uintptr_t WordIdx = Idx / kBitsInWord;
|
|
||||||
uintptr_t BitIdx = Idx % kBitsInWord;
|
|
||||||
CurrentMap[WordIdx] |= 1UL << BitIdx;
|
|
||||||
Prev = Next;
|
Prev = Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
37
lib/Fuzzer/FuzzerTracePC.h
Normal file
37
lib/Fuzzer/FuzzerTracePC.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//===- FuzzerTracePC.h - INTERNAL - Path tracer. --------*- C++ -* ===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Trace PCs.
|
||||||
|
// This module implements __sanitizer_cov_trace_pc, a callback required
|
||||||
|
// for -fsanitize-coverage=trace-pc instrumentation.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_FUZZER_TRACE_PC_H
|
||||||
|
#define LLVM_FUZZER_TRACE_PC_H
|
||||||
|
|
||||||
|
namespace fuzzer {
|
||||||
|
struct PcCoverageMap {
|
||||||
|
static const size_t kMapSizeInBits = 65371; // Prime.
|
||||||
|
static const size_t kMapSizeInBitsAligned = 65536; // 2^16
|
||||||
|
static const size_t kBitsInWord = (sizeof(uintptr_t) * 8);
|
||||||
|
static const size_t kMapSizeInWords = kMapSizeInBitsAligned / kBitsInWord;
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
inline void Update(uintptr_t Addr);
|
||||||
|
size_t MergeFrom(const PcCoverageMap &Other);
|
||||||
|
|
||||||
|
uintptr_t Map[kMapSizeInWords] __attribute__((aligned(512)));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clears the current PC Map.
|
||||||
|
void PcMapResetCurrent();
|
||||||
|
// Merges the current PC Map into the combined one, and clears the former.
|
||||||
|
size_t PcMapMergeInto(PcCoverageMap *Map);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user