diff options
Diffstat (limited to 'lib/Fuzzer/FuzzerTracePC.h')
-rw-r--r-- | lib/Fuzzer/FuzzerTracePC.h | 115 |
1 files changed, 59 insertions, 56 deletions
diff --git a/lib/Fuzzer/FuzzerTracePC.h b/lib/Fuzzer/FuzzerTracePC.h index b6b26b6c9af8..6523fa06005c 100644 --- a/lib/Fuzzer/FuzzerTracePC.h +++ b/lib/Fuzzer/FuzzerTracePC.h @@ -13,7 +13,9 @@ #define LLVM_FUZZER_TRACE_PC #include "FuzzerDefs.h" +#include "FuzzerDictionary.h" #include "FuzzerValueBitMap.h" + #include <set> namespace fuzzer { @@ -31,7 +33,8 @@ struct TableOfRecentCompares { struct Pair { T A, B; }; - void Insert(size_t Idx, T Arg1, T Arg2) { + ATTRIBUTE_NO_SANITIZE_ALL + void Insert(size_t Idx, const T &Arg1, const T &Arg2) { Idx = Idx % kSize; Table[Idx].A = Arg1; Table[Idx].B = Arg2; @@ -44,25 +47,23 @@ struct TableOfRecentCompares { class TracePC { public: - static const size_t kFeatureSetSize = ValueBitMap::kNumberOfItems; + static const size_t kNumPCs = 1 << 21; + // How many bits of PC are used from __sanitizer_cov_trace_pc. + static const size_t kTracePcBits = 18; - void HandleTrace(uint32_t *guard, uintptr_t PC); void HandleInit(uint32_t *start, uint32_t *stop); void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee); - void HandleValueProfile(size_t Value) { ValueProfileMap.AddValue(Value); } - template <class T> void HandleCmp(void *PC, T Arg1, T Arg2); + template <class T> void HandleCmp(uintptr_t PC, T Arg1, T Arg2); size_t GetTotalPCCoverage(); void SetUseCounters(bool UC) { UseCounters = UC; } void SetUseValueProfile(bool VP) { UseValueProfile = VP; } void SetPrintNewPCs(bool P) { DoPrintNewPCs = P; } - template <class Callback> size_t CollectFeatures(Callback CB); - bool UpdateValueProfileMap(ValueBitMap *MaxValueProfileMap) { - return UseValueProfile && MaxValueProfileMap->MergeFrom(ValueProfileMap); - } + template <class Callback> void CollectFeatures(Callback CB) const; void ResetMaps() { ValueProfileMap.Reset(); - memset(Counters, 0, sizeof(Counters)); + memset(Counters(), 0, GetNumPCs()); + ClearExtraCounters(); } void UpdateFeatureSet(size_t CurrentElementIdx, size_t CurrentElementSize); @@ -74,22 +75,20 @@ class TracePC { void DumpCoverage(); void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, - size_t n); - void AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2, - size_t n); - - bool UsingTracePcGuard() const {return NumModules; } + size_t n, bool StopAtZero); - static const size_t kTORCSize = 1 << 5; - TableOfRecentCompares<uint32_t, kTORCSize> TORC4; - TableOfRecentCompares<uint64_t, kTORCSize> TORC8; + TableOfRecentCompares<uint32_t, 32> TORC4; + TableOfRecentCompares<uint64_t, 32> TORC8; + TableOfRecentCompares<Word, 32> TORCW; void PrintNewPCs(); void InitializePrintNewPCs(); - size_t GetNumPCs() const { return Min(kNumPCs, NumGuards + 1); } + size_t GetNumPCs() const { + return NumGuards == 0 ? (1 << kTracePcBits) : Min(kNumPCs, NumGuards + 1); + } uintptr_t GetPC(size_t Idx) { assert(Idx < GetNumPCs()); - return PCs[Idx]; + return PCs()[Idx]; } private: @@ -105,51 +104,55 @@ private: size_t NumModules; // linker-initialized. size_t NumGuards; // linker-initialized. - static const size_t kNumCounters = 1 << 14; - alignas(8) uint8_t Counters[kNumCounters]; - - static const size_t kNumPCs = 1 << 24; - uintptr_t PCs[kNumPCs]; + uint8_t *Counters() const; + uintptr_t *PCs() const; std::set<uintptr_t> *PrintedPCs; ValueBitMap ValueProfileMap; }; -template <class Callback> -size_t TracePC::CollectFeatures(Callback CB) { - if (!UsingTracePcGuard()) return 0; - size_t Res = 0; - const size_t Step = 8; - assert(reinterpret_cast<uintptr_t>(Counters) % Step == 0); - size_t N = Min(kNumCounters, NumGuards + 1); - N = (N + Step - 1) & ~(Step - 1); // Round up. - for (size_t Idx = 0; Idx < N; Idx += Step) { - uint64_t Bundle = *reinterpret_cast<uint64_t*>(&Counters[Idx]); - if (!Bundle) continue; - for (size_t i = Idx; i < Idx + Step; i++) { - uint8_t Counter = (Bundle >> ((i - Idx) * 8)) & 0xff; - if (!Counter) continue; - Counters[i] = 0; - unsigned Bit = 0; - /**/ if (Counter >= 128) Bit = 7; - else if (Counter >= 32) Bit = 6; - else if (Counter >= 16) Bit = 5; - else if (Counter >= 8) Bit = 4; - else if (Counter >= 4) Bit = 3; - else if (Counter >= 3) Bit = 2; - else if (Counter >= 2) Bit = 1; - size_t Feature = (i * 8 + Bit); - if (CB(Feature)) - Res++; - } - } +template <class Callback> // void Callback(size_t Idx, uint8_t Value); +ATTRIBUTE_NO_SANITIZE_ALL +void ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End, + size_t FirstFeature, Callback Handle8bitCounter) { + typedef uintptr_t LargeType; + const size_t Step = sizeof(LargeType) / sizeof(uint8_t); + assert(!(reinterpret_cast<uintptr_t>(Begin) % 64)); + for (auto P = Begin; P < End; P += Step) + if (LargeType Bundle = *reinterpret_cast<const LargeType *>(P)) + for (size_t I = 0; I < Step; I++, Bundle >>= 8) + if (uint8_t V = Bundle & 0xff) + Handle8bitCounter(FirstFeature + P - Begin + I, V); +} + +template <class Callback> // bool Callback(size_t Feature) +ATTRIBUTE_NO_SANITIZE_ALL +__attribute__((noinline)) +void TracePC::CollectFeatures(Callback HandleFeature) const { + uint8_t *Counters = this->Counters(); + size_t N = GetNumPCs(); + auto Handle8bitCounter = [&](size_t Idx, uint8_t Counter) { + assert(Counter); + unsigned Bit = 0; + /**/ if (Counter >= 128) Bit = 7; + else if (Counter >= 32) Bit = 6; + else if (Counter >= 16) Bit = 5; + else if (Counter >= 8) Bit = 4; + else if (Counter >= 4) Bit = 3; + else if (Counter >= 3) Bit = 2; + else if (Counter >= 2) Bit = 1; + HandleFeature(Idx * 8 + Bit); + }; + + ForEachNonZeroByte(Counters, Counters + N, 0, Handle8bitCounter); + ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), N * 8, + Handle8bitCounter); + if (UseValueProfile) ValueProfileMap.ForEach([&](size_t Idx) { - if (CB(NumGuards * 8 + Idx)) - Res++; + HandleFeature(N * 8 + Idx); }); - return Res; } extern TracePC TPC; |