1 //===-- asan_win.cc -------------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
10 // Windows-specific details.
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_common/sanitizer_platform.h"
20 #include "asan_interceptors.h"
21 #include "asan_internal.h"
22 #include "asan_report.h"
23 #include "asan_thread.h"
24 #include "sanitizer_common/sanitizer_libc.h"
25 #include "sanitizer_common/sanitizer_mutex.h"
28 SANITIZER_INTERFACE_ATTRIBUTE
29 int __asan_should_detect_stack_use_after_return() {
31 return __asan_option_detect_stack_use_after_return
;
37 // ---------------------- TSD ---------------- {{{1
38 static bool tsd_key_inited
= false;
40 static __declspec(thread
) void *fake_tsd
= 0;
42 void AsanTSDInit(void (*destructor
)(void *tsd
)) {
43 // FIXME: we're ignoring the destructor for now.
44 tsd_key_inited
= true;
48 CHECK(tsd_key_inited
);
52 void AsanTSDSet(void *tsd
) {
53 CHECK(tsd_key_inited
);
57 void PlatformTSDDtor(void *tsd
) {
58 AsanThread::TSDDtor(tsd
);
60 // ---------------------- Various stuff ---------------- {{{1
62 // No need to re-exec on Windows.
65 void *AsanDoesNotSupportStaticLinkage() {
67 #error Please build the runtime with a non-debug CRT: /MD or /MT
72 void AsanCheckDynamicRTPrereqs() {}
74 void AsanCheckIncompatibleRT() {}
76 void AsanPlatformThreadInit() {
77 // Nothing here for now.
80 void ReadContextStack(void *context
, uptr
*stack
, uptr
*ssize
) {
84 void AsanOnSIGSEGV(int, void *siginfo
, void *context
) {
88 static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler
;
90 static long WINAPI
SEHHandler(EXCEPTION_POINTERS
*info
) {
91 EXCEPTION_RECORD
*exception_record
= info
->ExceptionRecord
;
92 CONTEXT
*context
= info
->ContextRecord
;
93 uptr pc
= (uptr
)exception_record
->ExceptionAddress
;
95 uptr bp
= (uptr
)context
->Rbp
, sp
= (uptr
)context
->Rsp
;
97 uptr bp
= (uptr
)context
->Ebp
, sp
= (uptr
)context
->Esp
;
100 if (exception_record
->ExceptionCode
== EXCEPTION_ACCESS_VIOLATION
||
101 exception_record
->ExceptionCode
== EXCEPTION_IN_PAGE_ERROR
) {
102 const char *description
=
103 (exception_record
->ExceptionCode
== EXCEPTION_ACCESS_VIOLATION
)
106 uptr access_addr
= exception_record
->ExceptionInformation
[1];
107 ReportSIGSEGV(description
, pc
, sp
, bp
, context
, access_addr
);
110 // FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
112 return default_seh_handler(info
);
115 // We want to install our own exception handler (EH) to print helpful reports
116 // on access violations and whatnot. Unfortunately, the CRT initializers assume
117 // they are run before any user code and drop any previously-installed EHs on
118 // the floor, so we can't install our handler inside __asan_init.
119 // (See crt0dat.c in the CRT sources for the details)
121 // Things get even more complicated with the dynamic runtime, as it finishes its
122 // initialization before the .exe module CRT begins to initialize.
124 // For the static runtime (-MT), it's enough to put a callback to
125 // __asan_set_seh_filter in the last section for C initializers.
127 // For the dynamic runtime (-MD), we want link the same
128 // asan_dynamic_runtime_thunk.lib to all the modules, thus __asan_set_seh_filter
129 // will be called for each instrumented module. This ensures that at least one
130 // __asan_set_seh_filter call happens after the .exe module CRT is initialized.
131 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
132 int __asan_set_seh_filter() {
133 // We should only store the previous handler if it's not our own handler in
134 // order to avoid loops in the EH chain.
135 auto prev_seh_handler
= SetUnhandledExceptionFilter(SEHHandler
);
136 if (prev_seh_handler
!= &SEHHandler
)
137 default_seh_handler
= prev_seh_handler
;
142 // Put a pointer to __asan_set_seh_filter at the end of the global list
143 // of C initializers, after the default EH is set by the CRT.
144 #pragma section(".CRT$XIZ", long, read) // NOLINT
145 static __declspec(allocate(".CRT$XIZ"))
146 int (*__intercept_seh
)() = __asan_set_seh_filter
;
149 } // namespace __asan