forked from OSchip/llvm-project
[libFuzzer] initial implementation of path coverage based on -fsanitize-coverage=trace-pc. This does not scale well yet, but already cracks FullCoverageSetTest in seconds
llvm-svn: 262073
This commit is contained in:
parent
297ce4ece9
commit
da63c1d09a
|
@ -12,6 +12,7 @@ if( LLVM_USE_SANITIZE_COVERAGE )
|
|||
FuzzerMutate.cpp
|
||||
FuzzerSanitizerOptions.cpp
|
||||
FuzzerSHA1.cpp
|
||||
FuzzerTracePC.cpp
|
||||
FuzzerUtil.cpp
|
||||
)
|
||||
add_library(LLVMFuzzerNoMain STATIC
|
||||
|
|
|
@ -99,6 +99,13 @@ bool IsASCII(const Unit &U);
|
|||
int NumberOfCpuCores();
|
||||
int GetPid();
|
||||
|
||||
// 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 {
|
||||
public:
|
||||
Random(unsigned int seed) : R(seed) {}
|
||||
|
@ -390,6 +397,7 @@ private:
|
|||
long TimeOfLongestUnitInSeconds = 0;
|
||||
long EpochOfLastReadOfOutputCorpus = 0;
|
||||
size_t LastRecordedBlockCoverage = 0;
|
||||
size_t LastRecordedPcMapSize = 0;
|
||||
size_t LastRecordedCallerCalleeCoverage = 0;
|
||||
size_t LastCoveragePcBufferLen = 0;
|
||||
};
|
||||
|
|
|
@ -151,6 +151,8 @@ void Fuzzer::PrintStats(const char *Where, const char *End) {
|
|||
Printf("#%zd\t%s", TotalNumberOfRuns, Where);
|
||||
if (LastRecordedBlockCoverage)
|
||||
Printf(" cov: %zd", LastRecordedBlockCoverage);
|
||||
if (LastRecordedPcMapSize)
|
||||
Printf(" path: %zd", LastRecordedPcMapSize);
|
||||
if (auto TB = TotalBits())
|
||||
Printf(" bits: %zd", TB);
|
||||
if (LastRecordedCallerCalleeCoverage)
|
||||
|
@ -316,6 +318,12 @@ bool Fuzzer::CheckCoverageAfterRun() {
|
|||
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());
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
//===- FuzzerTracePC.cpp - PC tracing--------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Experimental and not yet tuned for performance.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "FuzzerInternal.h"
|
||||
|
||||
namespace fuzzer {
|
||||
static const size_t kMapSize = 65371; // Prime.
|
||||
static uint8_t CurMap[kMapSize];
|
||||
static uint8_t CombinedMap[kMapSize];
|
||||
static size_t CombinedMapSize;
|
||||
static thread_local uintptr_t Prev;
|
||||
|
||||
void PcMapResetCurrent() {
|
||||
if (Prev) {
|
||||
Prev = 0;
|
||||
memset(CurMap, 0, sizeof(CurMap));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: speed this up.
|
||||
void PcMapMergeCurrentToCombined() {
|
||||
if (!Prev) return;
|
||||
uintptr_t Res = 0;
|
||||
for (size_t i = 0; i < kMapSize; i++) {
|
||||
uint8_t p = (CombinedMap[i] |= CurMap[i]);
|
||||
CurMap[i] = 0;
|
||||
Res += p != 0;
|
||||
}
|
||||
CombinedMapSize = Res;
|
||||
}
|
||||
|
||||
size_t PcMapCombinedSize() { return CombinedMapSize; }
|
||||
|
||||
static void HandlePC(uintptr_t PC) {
|
||||
// We take 12 bits of PC and mix it with the previous PCs.
|
||||
uintptr_t Idx = (Prev << 5) ^ (PC & 4095);
|
||||
CurMap[Idx % kMapSize] = 1;
|
||||
Prev = Idx;
|
||||
}
|
||||
|
||||
} // namespace fuzzer
|
||||
|
||||
extern "C" void __sanitizer_cov_trace_pc() {
|
||||
fuzzer::HandlePC(reinterpret_cast<uintptr_t>(__builtin_return_address(0)));
|
||||
}
|
||||
//uintptr_t __sanitizer_get_total_unique_coverage() { return 0; }
|
||||
//uintptr_t __sanitizer_get_number_of_counters() { return 0; }
|
|
@ -47,6 +47,11 @@ set(TraceBBTests
|
|||
SimpleTest
|
||||
)
|
||||
|
||||
set(TracePCTests
|
||||
FourIndependentBranchesTest
|
||||
FullCoverageSetTest
|
||||
)
|
||||
|
||||
set(TestBinaries)
|
||||
|
||||
foreach(Test ${Tests})
|
||||
|
@ -113,6 +118,12 @@ foreach(Test ${TraceBBTests})
|
|||
set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}-TraceBB)
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(trace-pc)
|
||||
|
||||
foreach(Test ${TracePCTests})
|
||||
set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}-TracePC)
|
||||
endforeach()
|
||||
|
||||
set_target_properties(${TestBinaries}
|
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
CHECK: BINGO
|
||||
RUN: not LLVMFuzzer-FourIndependentBranchesTest-TracePC -seed=1 -runs=1000000 2>&1 | FileCheck %s
|
|
@ -0,0 +1,14 @@
|
|||
# These tests are not instrumented with coverage.
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE
|
||||
"${LIBFUZZER_FLAGS_BASE} -O0 -fno-sanitize-coverage=8bit-counters -fsanitize-coverage=trace-pc")
|
||||
|
||||
foreach(Test ${TracePCTests})
|
||||
add_executable(LLVMFuzzer-${Test}-TracePC
|
||||
../${Test}.cpp
|
||||
)
|
||||
target_link_libraries(LLVMFuzzer-${Test}-TracePC
|
||||
LLVMFuzzer
|
||||
)
|
||||
endforeach()
|
||||
|
Loading…
Reference in New Issue