aboutsummaryrefslogtreecommitdiff
path: root/lib/Fuzzer/FuzzerTracePC.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Fuzzer/FuzzerTracePC.h')
-rw-r--r--lib/Fuzzer/FuzzerTracePC.h115
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;