mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-13 23:18:58 +00:00
[libfuzzer] fixing collected pc addresses for coverage
Summary: The causes google/ossfuzz#84 Reviewers: kcc Subscribers: mgorny Differential Revision: https://reviews.llvm.org/D28827 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292289 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
974466a9b8
commit
56992074d3
@ -47,9 +47,11 @@
|
||||
|
||||
#ifdef __clang__ // avoid gcc warning.
|
||||
# define ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
|
||||
# define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
# define ATTRIBUTE_NO_SANITIZE_MEMORY
|
||||
#endif
|
||||
# define ALWAYS_INLINE
|
||||
#endif // __clang__
|
||||
|
||||
namespace fuzzer {
|
||||
|
||||
|
@ -236,15 +236,11 @@ void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
|
||||
}
|
||||
|
||||
template <class T>
|
||||
ATTRIBUTE_TARGET_POPCNT
|
||||
#ifdef __clang__ // g++ can't handle this __attribute__ here :(
|
||||
__attribute__((always_inline))
|
||||
#endif // __clang__
|
||||
void TracePC::HandleCmp(void *PC, T Arg1, T Arg2) {
|
||||
uintptr_t PCuint = reinterpret_cast<uintptr_t>(PC);
|
||||
ATTRIBUTE_TARGET_POPCNT ALWAYS_INLINE
|
||||
void TracePC::HandleCmp(uintptr_t PC, T Arg1, T Arg2) {
|
||||
uint64_t ArgXor = Arg1 ^ Arg2;
|
||||
uint64_t ArgDistance = __builtin_popcountl(ArgXor) + 1; // [1,65]
|
||||
uintptr_t Idx = ((PCuint & 4095) + 1) * ArgDistance;
|
||||
uintptr_t Idx = ((PC & 4095) + 1) * ArgDistance;
|
||||
if (sizeof(T) == 4)
|
||||
TORC4.Insert(ArgXor, Arg1, Arg2);
|
||||
else if (sizeof(T) == 8)
|
||||
@ -252,12 +248,18 @@ void TracePC::HandleCmp(void *PC, T Arg1, T Arg2) {
|
||||
HandleValueProfile(Idx);
|
||||
}
|
||||
|
||||
inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(void* pc) {
|
||||
// TODO: this implementation is x86 only.
|
||||
// see sanitizer_common GetPreviousInstructionPc for full implementation.
|
||||
return reinterpret_cast<uintptr_t>(pc) - 1;
|
||||
}
|
||||
|
||||
} // namespace fuzzer
|
||||
|
||||
extern "C" {
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) {
|
||||
uintptr_t PC = (uintptr_t)__builtin_return_address(0);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
fuzzer::TPC.HandleTrace(Guard, PC);
|
||||
}
|
||||
|
||||
@ -268,25 +270,29 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) {
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
|
||||
uintptr_t PC = (uintptr_t)__builtin_return_address(0);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
fuzzer::TPC.HandleCallerCallee(PC, Callee);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) {
|
||||
fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
|
||||
}
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) {
|
||||
fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
|
||||
}
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) {
|
||||
fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
|
||||
}
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) {
|
||||
fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
@ -297,7 +303,7 @@ void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) {
|
||||
// Skip the most common and the most boring case.
|
||||
if (Vals[N - 1] < 256 && Val < 256)
|
||||
return;
|
||||
char *PC = (char*)__builtin_return_address(0);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
size_t i;
|
||||
uint64_t Token = 0;
|
||||
for (i = 0; i < N; i++) {
|
||||
@ -316,15 +322,18 @@ void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) {
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_div4(uint32_t Val) {
|
||||
fuzzer::TPC.HandleCmp(__builtin_return_address(0), Val, (uint32_t)0);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
fuzzer::TPC.HandleCmp(PC, Val, (uint32_t)0);
|
||||
}
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_div8(uint64_t Val) {
|
||||
fuzzer::TPC.HandleCmp(__builtin_return_address(0), Val, (uint64_t)0);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
fuzzer::TPC.HandleCmp(PC, Val, (uint64_t)0);
|
||||
}
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_gep(uintptr_t Idx) {
|
||||
fuzzer::TPC.HandleCmp(__builtin_return_address(0), Idx, (uintptr_t)0);
|
||||
uintptr_t PC = fuzzer::GetPreviousInstructionPc(__builtin_return_address(0));
|
||||
fuzzer::TPC.HandleCmp(PC, Idx, (uintptr_t)0);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
@ -52,7 +52,7 @@ class TracePC {
|
||||
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; }
|
||||
|
@ -126,7 +126,6 @@ foreach(Test ${Tests})
|
||||
add_libfuzzer_test(${Test} SOURCES ${Test}.cpp)
|
||||
endforeach()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Unit tests
|
||||
###############################################################################
|
||||
@ -213,5 +212,5 @@ configure_lit_site_cfg(
|
||||
|
||||
add_lit_testsuite(check-fuzzer "Running Fuzzer tests"
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS ${TestBinaries} FileCheck not
|
||||
DEPENDS ${TestBinaries} FileCheck sancov not
|
||||
)
|
||||
|
@ -2,12 +2,14 @@ RUN: DIR=%t_workdir
|
||||
RUN: BUILD_DIR=$(pwd)
|
||||
RUN: rm -rf $DIR && mkdir -p $DIR && cd $DIR
|
||||
RUN: not $BUILD_DIR/LLVMFuzzer-NullDerefTest -dump_coverage=1 2>&1 | FileCheck %s
|
||||
RUN: sancov -covered-functions *.sancov $BUILD_DIR/LLVMFuzzer-NullDerefTest | FileCheck %s --check-prefix=SANCOV
|
||||
RUN: $BUILD_DIR/LLVMFuzzer-DSOTest -dump_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO
|
||||
RUN: not $BUILD_DIR/LLVMFuzzer-NullDerefTest -dump_coverage=0 2>&1 | FileCheck %s --check-prefix=NOCOV
|
||||
RUN: rm -rf $DIR
|
||||
|
||||
|
||||
CHECK: SanitizerCoverage: ./LLVMFuzzer-NullDerefTest.{{.*}}.sancov {{.*}} PCs written
|
||||
SANCOV: LLVMFuzzerTestOneInput
|
||||
|
||||
DSO: SanitizerCoverage: ./LLVMFuzzer-DSOTest.{{.*}}.sancov {{.*}} PCs written
|
||||
DSO-DAG: SanitizerCoverage: ./libLLVMFuzzer-DSO1.{{.*}}.sancov {{.*}} PCs written
|
||||
|
Loading…
Reference in New Issue
Block a user