1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00

[libFuzzer] start using trace-pc-guard as an alternative source of coverage

llvm-svn: 281435
This commit is contained in:
Kostya Serebryany 2016-09-14 02:13:06 +00:00
parent 562a9d7d62
commit 41b41f51a8
6 changed files with 32 additions and 52 deletions

View File

@ -137,9 +137,6 @@ int NumberOfCpuCores();
int GetPid(); int GetPid();
void SleepSeconds(int Seconds); void SleepSeconds(int Seconds);
// See FuzzerTracePC.cpp
size_t PCMapMergeFromCurrent(ValueBitMap &M);
// See FuzzerTraceState.cpp // See FuzzerTraceState.cpp
void EnableValueProfile(); void EnableValueProfile();
size_t VPMapMergeFromCurrent(ValueBitMap &M); size_t VPMapMergeFromCurrent(ValueBitMap &M);
@ -358,6 +355,18 @@ private:
std::vector<Mutator> DefaultMutators; std::vector<Mutator> DefaultMutators;
}; };
// See TracePC.cpp
class TracePC {
public:
void HandleTrace(uint8_t *guard, uintptr_t PC);
void HandleInit(uint8_t *start, uint8_t *stop);
size_t GetTotalCoverage();
private:
size_t TotalCoverage = 0;
};
extern TracePC TPC;
class Fuzzer { class Fuzzer {
public: public:
@ -370,8 +379,6 @@ public:
CallerCalleeCoverage = 0; CallerCalleeCoverage = 0;
CounterBitmapBits = 0; CounterBitmapBits = 0;
CounterBitmap.clear(); CounterBitmap.clear();
PCMap.Reset();
PCMapBits = 0;
VPMap.Reset(); VPMap.Reset();
VPMapBits = 0; VPMapBits = 0;
} }
@ -383,8 +390,6 @@ public:
// Precalculated number of bits in CounterBitmap. // Precalculated number of bits in CounterBitmap.
size_t CounterBitmapBits; size_t CounterBitmapBits;
std::vector<uint8_t> CounterBitmap; std::vector<uint8_t> CounterBitmap;
ValueBitMap PCMap;
size_t PCMapBits;
ValueBitMap VPMap; ValueBitMap VPMap;
size_t VPMapBits; size_t VPMapBits;
}; };

View File

@ -77,7 +77,8 @@ void Fuzzer::PrepareCounters(Fuzzer::Coverage *C) {
bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) { bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) {
bool Res = false; bool Res = false;
uint64_t NewBlockCoverage = EF->__sanitizer_get_total_unique_coverage(); uint64_t NewBlockCoverage =
EF->__sanitizer_get_total_unique_coverage() + TPC.GetTotalCoverage();
if (NewBlockCoverage > C->BlockCoverage) { if (NewBlockCoverage > C->BlockCoverage) {
Res = true; Res = true;
C->BlockCoverage = NewBlockCoverage; C->BlockCoverage = NewBlockCoverage;
@ -103,12 +104,6 @@ bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) {
} }
} }
size_t NewPCMapBits = PCMapMergeFromCurrent(C->PCMap);
if (NewPCMapBits > C->PCMapBits) {
Res = true;
C->PCMapBits = NewPCMapBits;
}
size_t NewVPMapBits = VPMapMergeFromCurrent(C->VPMap); size_t NewVPMapBits = VPMapMergeFromCurrent(C->VPMap);
if (NewVPMapBits > C->VPMapBits) { if (NewVPMapBits > C->VPMapBits) {
Res = true; Res = true;
@ -315,8 +310,6 @@ void Fuzzer::PrintStats(const char *Where, const char *End) {
Printf("#%zd\t%s", TotalNumberOfRuns, Where); Printf("#%zd\t%s", TotalNumberOfRuns, Where);
if (MaxCoverage.BlockCoverage) if (MaxCoverage.BlockCoverage)
Printf(" cov: %zd", MaxCoverage.BlockCoverage); Printf(" cov: %zd", MaxCoverage.BlockCoverage);
if (MaxCoverage.PCMapBits)
Printf(" path: %zd", MaxCoverage.PCMapBits);
if (MaxCoverage.VPMapBits) if (MaxCoverage.VPMapBits)
Printf(" vp: %zd", MaxCoverage.VPMapBits); Printf(" vp: %zd", MaxCoverage.VPMapBits);
if (auto TB = MaxCoverage.CounterBitmapBits) if (auto TB = MaxCoverage.CounterBitmapBits)
@ -508,9 +501,8 @@ std::string Fuzzer::Coverage::DebugString() const {
std::string("Coverage{") + "BlockCoverage=" + std::string("Coverage{") + "BlockCoverage=" +
std::to_string(BlockCoverage) + " CallerCalleeCoverage=" + std::to_string(BlockCoverage) + " CallerCalleeCoverage=" +
std::to_string(CallerCalleeCoverage) + " CounterBitmapBits=" + std::to_string(CallerCalleeCoverage) + " CounterBitmapBits=" +
std::to_string(CounterBitmapBits) + " PCMapBits=" + std::to_string(CounterBitmapBits) +
std::to_string(PCMapBits) + " VPMapBits " + " VPMapBits " + std::to_string(VPMapBits) + "}";
std::to_string(VPMapBits) + "}";
return Result; return Result;
} }

View File

@ -7,8 +7,8 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Trace PCs. // Trace PCs.
// This module implements __sanitizer_cov_trace_pc, a callback required // This module implements __sanitizer_cov_trace_pc_guard[_init],
// for -fsanitize-coverage=trace-pc instrumentation. // the callback required for -fsanitize-coverage=trace-pc-guard instrumentation.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -16,37 +16,27 @@
namespace fuzzer { namespace fuzzer {
static size_t PreviouslyComputedPCHash; TracePC TPC;
static ValueBitMap CurrentPCMap;
// Merges CurrentPCMap into M, returns the number of new bits. void TracePC::HandleTrace(uint8_t *guard, uintptr_t PC) {
size_t PCMapMergeFromCurrent(ValueBitMap &M) { *guard = 0xff;
if (!PreviouslyComputedPCHash) TotalCoverage++;
return 0;
PreviouslyComputedPCHash = 0;
return M.MergeFrom(CurrentPCMap);
} }
void TracePC::HandleInit(uint8_t *start, uint8_t *stop) {
static void HandlePC(uint32_t PC) { Printf("INFO: guards: [%p,%p)\n", start, stop);
// We take 12 bits of PC and mix it with the previous PCs.
uintptr_t Next = (PreviouslyComputedPCHash << 5) ^ (PC & 4095);
CurrentPCMap.AddValue(Next);
PreviouslyComputedPCHash = Next;
} }
size_t TracePC::GetTotalCoverage() { return TotalCoverage; }
} // namespace fuzzer } // namespace fuzzer
extern "C" { extern "C" {
__attribute__((visibility("default"))) __attribute__((visibility("default")))
void __sanitizer_cov_trace_pc() { void __sanitizer_cov_trace_pc_guard(uint8_t *guard) {
fuzzer::HandlePC(static_cast<uint32_t>( uintptr_t PC = (uintptr_t)__builtin_return_address(0);
reinterpret_cast<uintptr_t>(__builtin_return_address(0)))); fuzzer::TPC.HandleTrace(guard, PC);
} }
__attribute__((visibility("default"))) __attribute__((visibility("default")))
void __sanitizer_cov_trace_pc_indir(int *) { void __sanitizer_cov_trace_pc_guard_init(uint8_t *start, uint8_t *stop) {
// Stub to allow linking with code built with
// -fsanitize=indirect-calls,trace-pc.
// This isn't used currently.
} }
} }

View File

@ -1,7 +0,0 @@
CHECK: BINGO
REQUIRES: linux
RUN: not LLVMFuzzer-FourIndependentBranchesTest-TracePC -seed=1 -runs=1000000 2>&1 | FileCheck %s
// FIXME: The test below uses a significant amount of memory on OSX and
// sometimes hits the 2GiB memory limit. This needs to be investigated. For now
// only run the test on Linux.
RUN: not LLVMFuzzer-FullCoverageSetTest-TracePC -seed=1 -runs=10000000 2>&1 | FileCheck %s

View File

@ -2,6 +2,7 @@ CHECK: BINGO
Done1000000: Done 1000000 runs in Done1000000: Done 1000000 runs in
RUN: LLVMFuzzer-SimpleTest 2>&1 | FileCheck %s RUN: LLVMFuzzer-SimpleTest 2>&1 | FileCheck %s
RUN: LLVMFuzzer-SimpleTest-TracePC 2>&1 | FileCheck %s
# only_ascii mode. Will perform some minimal self-validation. # only_ascii mode. Will perform some minimal self-validation.
RUN: LLVMFuzzer-SimpleTest -only_ascii=1 2>&1 RUN: LLVMFuzzer-SimpleTest -only_ascii=1 2>&1

View File

@ -1,11 +1,10 @@
# These tests are not instrumented with coverage. # These tests are not instrumented with coverage.
set(CMAKE_CXX_FLAGS set(CMAKE_CXX_FLAGS
"${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=8bit-counters -fsanitize-coverage=trace-pc") "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=8bit-counters -fsanitize-coverage=trace-pc-guard")
set(TracePCTests set(TracePCTests
FourIndependentBranchesTest SimpleTest
FullCoverageSetTest
) )
foreach(Test ${TracePCTests}) foreach(Test ${TracePCTests})