[ASan/Win] Catch NULL derefs and page faults
[blocksruntime.git] / lib / asan / asan_win.cc
blob162393c6477c37c73760c1b276446468267a22b5
1 //===-- asan_win.cc -------------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
12 // Windows-specific details.
13 //===----------------------------------------------------------------------===//
15 #include "sanitizer_common/sanitizer_platform.h"
16 #if SANITIZER_WINDOWS
17 #include <windows.h>
19 #include <dbghelp.h>
20 #include <stdlib.h>
22 #include "asan_interceptors.h"
23 #include "asan_internal.h"
24 #include "asan_report.h"
25 #include "asan_thread.h"
26 #include "sanitizer_common/sanitizer_libc.h"
27 #include "sanitizer_common/sanitizer_mutex.h"
29 extern "C" {
30 SANITIZER_INTERFACE_ATTRIBUTE
31 int __asan_should_detect_stack_use_after_return() {
32 __asan_init();
33 return __asan_option_detect_stack_use_after_return;
37 namespace __asan {
39 // ---------------------- TSD ---------------- {{{1
40 static bool tsd_key_inited = false;
42 static __declspec(thread) void *fake_tsd = 0;
44 void AsanTSDInit(void (*destructor)(void *tsd)) {
45 // FIXME: we're ignoring the destructor for now.
46 tsd_key_inited = true;
49 void *AsanTSDGet() {
50 CHECK(tsd_key_inited);
51 return fake_tsd;
54 void AsanTSDSet(void *tsd) {
55 CHECK(tsd_key_inited);
56 fake_tsd = tsd;
59 void PlatformTSDDtor(void *tsd) {
60 AsanThread::TSDDtor(tsd);
62 // ---------------------- Various stuff ---------------- {{{1
63 void MaybeReexec() {
64 // No need to re-exec on Windows.
67 void *AsanDoesNotSupportStaticLinkage() {
68 #if defined(_DEBUG)
69 #error Please build the runtime with a non-debug CRT: /MD or /MT
70 #endif
71 return 0;
74 void AsanCheckDynamicRTPrereqs() { UNIMPLEMENTED(); }
76 void AsanCheckIncompatibleRT() {}
78 void AsanPlatformThreadInit() {
79 // Nothing here for now.
82 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
83 UNIMPLEMENTED();
86 void AsanOnSIGSEGV(int, void *siginfo, void *context) {
87 UNIMPLEMENTED();
90 static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
92 long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
93 EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
94 CONTEXT *context = info->ContextRecord;
95 uptr pc = (uptr)exception_record->ExceptionAddress;
96 #ifdef _WIN64
97 uptr bp = (uptr)context->Rbp, sp = (uptr)context->Rsp;
98 #else
99 uptr bp = (uptr)context->Ebp, sp = (uptr)context->Esp;
100 #endif
102 if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
103 exception_record->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) {
104 const char *description =
105 (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
106 ? "access-violation"
107 : "in-page-error";
108 uptr access_addr = exception_record->ExceptionInformation[1];
109 ReportSIGSEGV(description, pc, sp, bp, context, access_addr);
112 // FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
114 return default_seh_handler(info);
117 int SetSEHFilter() {
118 default_seh_handler = SetUnhandledExceptionFilter(SEHHandler);
119 return 0;
122 // Put a pointer to SetSEHFilter at the end of the global list
123 // of C initializers, after the default handler is set by the CRT.
124 // See crt0dat.c in the CRT sources for the details.
125 #pragma section(".CRT$XIZ", long, read) // NOLINT
126 __declspec(allocate(".CRT$XIZ")) int (*__intercept_seh)() = SetSEHFilter;
128 } // namespace __asan
130 #endif // _WIN32