diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp @@ -956,22 +956,27 @@ uptr SignalContext::GetAddress() const { EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo; - return exception_record->ExceptionInformation[1]; + if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) + return exception_record->ExceptionInformation[1]; + return (uptr)exception_record->ExceptionAddress; } bool SignalContext::IsMemoryAccess() const { - return GetWriteFlag() != SignalContext::UNKNOWN; + return ((EXCEPTION_RECORD *)siginfo)->ExceptionCode == + EXCEPTION_ACCESS_VIOLATION; } -bool SignalContext::IsTrueFaultingAddress() const { - // FIXME: Provide real implementation for this. See Linux and Mac variants. - return IsMemoryAccess(); -} +bool SignalContext::IsTrueFaultingAddress() const { return true; } SignalContext::WriteFlag SignalContext::GetWriteFlag() const { EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo; + + // The write flag is only available for access violation exceptions. + if (exception_record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) + return SignalContext::UNKNOWN; + // The contents of this array are documented at - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx + // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record // The first element indicates read as 0, write as 1, or execute as 8. The // second element is the faulting address. switch (exception_record->ExceptionInformation[0]) { diff --git a/compiler-rt/test/asan/TestCases/Windows/breakpoint.cpp b/compiler-rt/test/asan/TestCases/Windows/breakpoint.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/breakpoint.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cl_asan -Od %s -Fe%t +// RUN: %env_asan_opts=handle_sigill=1 not %run %t 2>&1 | FileCheck %s + +// Test the error output from a breakpoint. Assertion-like macros often end in +// int3 on Windows. + +#include + +int main() { + puts("before breakpoint"); + fflush(stdout); + __debugbreak(); + return 0; +} +// CHECK: before breakpoint +// CHECK: ERROR: AddressSanitizer: breakpoint on unknown address [[ADDR:0x[^ ]*]] +// CHECK-SAME: (pc [[ADDR]] {{.*}}) +// CHECK-NEXT: #0 {{.*}} in main {{.*}}breakpoint.cpp:{{.*}} diff --git a/compiler-rt/test/asan/TestCases/Windows/illegal_instruction.cpp b/compiler-rt/test/asan/TestCases/Windows/illegal_instruction.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/illegal_instruction.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cl_asan -Od %s -Fe%t +// RUN: %env_asan_opts=handle_sigill=1 not %run %t 2>&1 | FileCheck %s + +// Test the error output from an illegal instruction. + +#include + +int main() { + puts("before ud2a"); + fflush(stdout); + __builtin_trap(); + return 0; +} +// CHECK: before ud2a +// CHECK: ERROR: AddressSanitizer: illegal-instruction on unknown address [[ADDR:0x[^ ]*]] +// CHECK-SAME: (pc [[ADDR]] {{.*}}) +// CHECK-NEXT: #0 {{.*}} in main {{.*}}illegal_instruction.cpp:{{.*}} diff --git a/compiler-rt/test/asan/TestCases/Windows/integer_divide_by_zero.cpp b/compiler-rt/test/asan/TestCases/Windows/integer_divide_by_zero.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/integer_divide_by_zero.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cl_asan -Od %s -Fe%t +// RUN: %env_asan_opts=handle_sigfpe=1 not %run %t 2>&1 | FileCheck %s + +// Test the error output from dividing by zero. + +#include + +int main() { + puts("before ud2a"); + fflush(stdout); + volatile int numerator = 1; + volatile int divisor = 0; + return numerator / divisor; +} +// CHECK: before ud2a +// CHECK: ERROR: AddressSanitizer: int-divide-by-zero on unknown address [[ADDR:0x[^ ]*]] +// CHECK-SAME: (pc [[ADDR]] {{.*}}) +// CHECK-NEXT: #0 {{.*}} in main {{.*}}integer_divide_by_zero.cpp:{{.*}} diff --git a/compiler-rt/test/asan/TestCases/Windows/sse_misalignment.cpp b/compiler-rt/test/asan/TestCases/Windows/sse_misalignment.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/sse_misalignment.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cl_asan -Od %s -Fe%t +// RUN: %env_asan_opts=handle_sigfpe=1 not %run %t 2>&1 | FileCheck %s + +// Test the error output from misaligned SSE2 memory access. This is a READ +// memory access. Windows appears to always provide an address of -1 for these +// types of faults, and there doesn't seem to be a way to distinguish them from +// other types of access violations without disassembling. + +#include +#include + +__m128i test() { + char buffer[17] = {}; + __m128i a = _mm_load_si128((__m128i *)buffer); + __m128i b = _mm_load_si128((__m128i *)(&buffer[0] + 1)); + return _mm_or_si128(a, b); +} + +int main() { + puts("before alignment fault"); + fflush(stdout); + volatile __m128i v = test(); + return 0; +} +// CHECK: before alignment fault +// CHECK: ERROR: AddressSanitizer: access-violation on unknown address {{0x[fF]*}} +// CHECK-NEXT: The signal is caused by a READ memory access. +// CHECK-NEXT: #0 {{.*}} in test(void) {{.*}}misalignment.cpp:{{.*}}