From: Kostya Serebryany Date: Thu, 30 Mar 2017 01:27:20 +0000 (+0000) Subject: [libFuzzer] best effort support for -fsanitize-coverage=trace-pc instrumentation... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2d9dd043ff6c00dd54abe4a970046f497f5f704c;p=llvm [libFuzzer] best effort support for -fsanitize-coverage=trace-pc instrumentation. It is less efficient and precise than -fsanitize-coverage=trace-pc-guard, but still works git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299046 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Fuzzer/FuzzerTracePC.cpp b/lib/Fuzzer/FuzzerTracePC.cpp index c73008dccd3..ce0f7a47eee 100644 --- a/lib/Fuzzer/FuzzerTracePC.cpp +++ b/lib/Fuzzer/FuzzerTracePC.cpp @@ -287,6 +287,17 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) { __sancov_trace_pc_guard_8bit_counters[Idx]++; } +// Best-effort support for -fsanitize-coverage=trace-pc, which is available +// in both Clang and GCC. +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +void __sanitizer_cov_trace_pc() { + uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t Idx = PC & (((uintptr_t)1 << fuzzer::TracePC::kTracePcBits) - 1); + __sancov_trace_pc_pcs[Idx] = PC; + __sancov_trace_pc_guard_8bit_counters[Idx]++; +} + ATTRIBUTE_INTERFACE void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) { fuzzer::TPC.HandleInit(Start, Stop); diff --git a/lib/Fuzzer/FuzzerTracePC.h b/lib/Fuzzer/FuzzerTracePC.h index c7b8dfe3c3f..4c8a18f830f 100644 --- a/lib/Fuzzer/FuzzerTracePC.h +++ b/lib/Fuzzer/FuzzerTracePC.h @@ -48,6 +48,8 @@ struct TableOfRecentCompares { class TracePC { public: 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 HandleInit(uint32_t *start, uint32_t *stop); void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee); @@ -81,7 +83,9 @@ class TracePC { 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]; diff --git a/lib/Fuzzer/test/CMakeLists.txt b/lib/Fuzzer/test/CMakeLists.txt index 8d4350514f7..f72bc3909a3 100644 --- a/lib/Fuzzer/test/CMakeLists.txt +++ b/lib/Fuzzer/test/CMakeLists.txt @@ -202,6 +202,7 @@ include_directories(..) # add_subdirectory(uninstrumented) add_subdirectory(no-coverage) +add_subdirectory(trace-pc) add_subdirectory(ubsan) add_library(LLVMFuzzer-DSO1 SHARED DSO1.cpp) diff --git a/lib/Fuzzer/test/trace-pc.test b/lib/Fuzzer/test/trace-pc.test new file mode 100644 index 00000000000..3709677b71b --- /dev/null +++ b/lib/Fuzzer/test/trace-pc.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: LLVMFuzzer-SimpleTest-TracePC -runs=100000 -seed=1 2>&1 | FileCheck %s diff --git a/lib/Fuzzer/test/trace-pc/CMakeLists.txt b/lib/Fuzzer/test/trace-pc/CMakeLists.txt new file mode 100644 index 00000000000..e800f82cc5d --- /dev/null +++ b/lib/Fuzzer/test/trace-pc/CMakeLists.txt @@ -0,0 +1,13 @@ +# These tests are not instrumented with coverage and don't +# have coverage rt in the binary. + +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard -fsanitize-coverage=trace-pc") + +set(TracePCTests + SimpleTest + ) + +foreach(Test ${TracePCTests}) + add_libfuzzer_test(${Test}-TracePC SOURCES ../${Test}.cpp) +endforeach()