Index: compiler-rt/lib/fuzzer/FuzzerDefs.h =================================================================== --- compiler-rt/lib/fuzzer/FuzzerDefs.h +++ compiler-rt/lib/fuzzer/FuzzerDefs.h @@ -128,16 +128,25 @@ #endif #if LIBFUZZER_WINDOWS +#include +#include + #define ATTRIBUTE_INTERFACE __declspec(dllexport) // This is used for __sancov_lowest_stack which is needed for // -fsanitize-coverage=stack-depth. That feature is not yet available on // Windows, so make the symbol static to avoid linking errors. #define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \ __attribute__((tls_model("initial-exec"))) thread_local static + +// __builtin_return_address() cannot be compiled with MSVC. Use the equivalent +// from +#define GET_CALLER_PC() reinterpret_cast(_ReturnAddress()) + #else #define ATTRIBUTE_INTERFACE __attribute__((visibility("default"))) #define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \ ATTRIBUTE_INTERFACE __attribute__((tls_model("initial-exec"))) thread_local +#define GET_CALLER_PC() reinterpret_cast(__builtin_return_address(0)) #endif namespace fuzzer { @@ -184,9 +193,35 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); inline uint8_t Bswap(uint8_t x) { return x; } +#if LIBFUZZER_WINDOWS +// Use alternatives to __builtin functions from and on +// Windows since the builtins are not supported by MSVC. +inline uint16_t Bswap(uint16_t x) { return _byteswap_ushort(x); } +inline uint32_t Bswap(uint32_t x) { return _byteswap_ulong(x); } +inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); } + +// The functions below were mostly copied from +// compiler-rt/lib/builtins/int_lib.h which defines the __builtin functions used +// outside of Windows. +inline uint32_t Clzll(uint64_t X) { + unsigned long LeadZeroIdx = 0; + // Does not work on x86 which is unsupported by LibFuzzer on Windows anyway. + if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx; + return 64; +} + +inline uint32_t Clz(uint32_t X) { + unsigned long LeadZeroIdx = 0; + if (_BitScanReverse(&LeadZeroIdx, X)) return 31 - LeadZeroIdx; + return 32; +} + +inline int Popcountll(unsigned long long X) { return __popcnt64(X); } +#else inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); } inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); } inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); } +#endif uint8_t *ExtraCountersBegin(); uint8_t *ExtraCountersEnd(); Index: compiler-rt/lib/fuzzer/FuzzerTracePC.cpp =================================================================== --- compiler-rt/lib/fuzzer/FuzzerTracePC.cpp +++ compiler-rt/lib/fuzzer/FuzzerTracePC.cpp @@ -446,9 +446,8 @@ TORC4.Insert(ArgXor, Arg1, Arg2); else if (sizeof(T) == 8) TORC8.Insert(ArgXor, Arg1, Arg2); - uint64_t HammingDistance = __builtin_popcountll(ArgXor); // [0,64] - uint64_t AbsoluteDistance = - (Arg1 == Arg2 ? 0 : __builtin_clzll(Arg1 - Arg2) + 1); + uint64_t HammingDistance = Popcountll(ArgXor); // [0,64] + uint64_t AbsoluteDistance = (Arg1 == Arg2 ? 0 : Clzll(Arg1 - Arg2) + 1); ValueProfileMap.AddValue(PC * 128 + HammingDistance); ValueProfileMap.AddValue(PC * 128 + 64 + AbsoluteDistance); } @@ -491,7 +490,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); uint32_t Idx = *Guard; __sancov_trace_pc_pcs[Idx] = PC; __sancov_trace_pc_guard_8bit_counters[Idx]++; @@ -502,7 +501,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL void __sanitizer_cov_trace_pc() { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); uintptr_t Idx = PC & (((uintptr_t)1 << fuzzer::TracePC::kTracePcBits) - 1); __sancov_trace_pc_pcs[Idx] = PC; __sancov_trace_pc_guard_8bit_counters[Idx]++; @@ -527,7 +526,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCallerCallee(PC, Callee); } @@ -535,7 +534,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -546,7 +545,7 @@ // the behaviour of __sanitizer_cov_trace_cmp[1248] ones. This, however, // should be changed later to make full use of instrumentation. void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -554,7 +553,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -562,7 +561,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -570,7 +569,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -578,7 +577,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -586,7 +585,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -594,7 +593,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -608,7 +607,7 @@ // Skip the most common and the most boring case. if (Vals[N - 1] < 256 && Val < 256) return; - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); size_t i; uint64_t Token = 0; for (i = 0; i < N; i++) { @@ -629,7 +628,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_div4(uint32_t Val) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Val, (uint32_t)0); } @@ -637,7 +636,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_div8(uint64_t Val) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Val, (uint64_t)0); } @@ -645,7 +644,7 @@ ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_gep(uintptr_t Idx) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); + uintptr_t PC = GET_CALLER_PC(); fuzzer::TPC.HandleCmp(PC, Idx, (uintptr_t)0); } Index: compiler-rt/lib/fuzzer/FuzzerUtil.h =================================================================== --- compiler-rt/lib/fuzzer/FuzzerUtil.h +++ compiler-rt/lib/fuzzer/FuzzerUtil.h @@ -84,7 +84,7 @@ size_t SimpleFastHash(const uint8_t *Data, size_t Size); -inline uint32_t Log(uint32_t X) { return 32 - __builtin_clz(X) - 1; } +inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; } } // namespace fuzzer