diff --git a/compiler-rt/lib/fuzzer/FuzzerExtraCounters.cpp b/compiler-rt/lib/fuzzer/FuzzerExtraCounters.cpp --- a/compiler-rt/lib/fuzzer/FuzzerExtraCounters.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerExtraCounters.cpp @@ -31,6 +31,71 @@ } // namespace fuzzer +#elif LIBFUZZER_WINDOWS + +namespace fuzzer { + +// +// The __start___libfuzzer_extra_counters variable is size 16 to account for +// 16-byte alignment on amd64 and 8-byte alignment on x86. This means the next +// variable in this section (either __libfuzzer_extra_counters or +// __stop___libfuzzer_extra_counters) will be located at +// (__start___libfuzzer_extra_counters + +// sizeof(__start___libfuzzer_extra_counters)). +// +// The section name, __libfuzzer_extra_counterr ends with "rr", so it is one +// less than __libfuzzer_extra_counters ("rs") alphabetically. We want the start +// symbol to be placed in the section just before the user supplied counters (if +// present). +// +#pragma section(".data$__libfuzzer_extra_counterr") +__declspec(allocate(".data$__libfuzzer_extra_counterr")) + uint8_t __start___libfuzzer_extra_counters[16] = {0}; + +// +// Example of what the user-supplied counters should look like. First, the +// pragma to create the section name. It will fall alphabetically between +// ".data$__libfuzzer_extra_counterr" and ".data$__libfuzzer_extra_countert". +// Next, the declspec to allocate the variable inside the specified section. +// Finally, some array, struct, whatever that is used to track the counter data. +// The size of this variable is dynamically computed by finding the difference +// of __stop___libfuzzer_extra_counters and __start___libfuzzer_extra_counters. +// + +// +// #pragma section(".data$__libfuzzer_extra_counters") +// __declspec(allocate(".data$__libfuzzer_extra_counters")) +// uint8_t any_name_variable[64 * 1024]; +// + +// +// Here, the section name, __libfuzzer_extra_countert ends with "rt", so it +// is one more than __libfuzzer_extra_counters ("rs") alphabetically. We want +// the stop symbol to be placed in the section just after the user supplied +// counters (if present). +// +#pragma section(".data$__libfuzzer_extra_countert") +__declspec(allocate(".data$__libfuzzer_extra_countert")) + uint8_t __stop___libfuzzer_extra_counters = 0; + +uint8_t *ExtraCountersBegin() { + return __start___libfuzzer_extra_counters + + sizeof(__start___libfuzzer_extra_counters); +} + +uint8_t *ExtraCountersEnd() { return &__stop___libfuzzer_extra_counters; } + +ATTRIBUTE_NO_SANITIZE_ALL +void ClearExtraCounters() { // hand-written memset, don't asan-ify. + uintptr_t *Beg = reinterpret_cast(ExtraCountersBegin()); + uintptr_t *End = reinterpret_cast(ExtraCountersEnd()); + for (; Beg < End; Beg++) { + *Beg = 0; + } +} + +} // namespace fuzzer + #else // TODO: implement for other platforms. namespace fuzzer { diff --git a/compiler-rt/test/fuzzer/TableLookupTest.cpp b/compiler-rt/test/fuzzer/TableLookupTest.cpp --- a/compiler-rt/test/fuzzer/TableLookupTest.cpp +++ b/compiler-rt/test/fuzzer/TableLookupTest.cpp @@ -25,6 +25,10 @@ #ifdef __linux__ __attribute__((section("__libfuzzer_extra_counters"))) #endif +#ifdef _WIN32 +#pragma section(".data$__libfuzzer_extra_counters") +__declspec(allocate(".data$__libfuzzer_extra_counters")) +#endif static uint8_t Counters[N]; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { diff --git a/compiler-rt/test/fuzzer/extra-counters.test b/compiler-rt/test/fuzzer/extra-counters.test --- a/compiler-rt/test/fuzzer/extra-counters.test +++ b/compiler-rt/test/fuzzer/extra-counters.test @@ -1,5 +1,3 @@ -REQUIRES: linux - RUN: %cpp_compiler %S/TableLookupTest.cpp -o %t-TableLookupTest RUN: not %run %t-TableLookupTest -print_final_stats=1 2>&1 | FileCheck %s CHECK: INFO: {{[0-9]+}} Extra Counters