1 //===-- asan_win.cc -------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of AddressSanitizer, an address sanity checker.
12 // Windows-specific details.
13 //===----------------------------------------------------------------------===//
15 #include "sanitizer_common/sanitizer_platform.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"
30 SANITIZER_INTERFACE_ATTRIBUTE
31 int __asan_should_detect_stack_use_after_return() {
33 return __asan_option_detect_stack_use_after_return;
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;
50 CHECK(tsd_key_inited);
54 void AsanTSDSet(void *tsd) {
55 CHECK(tsd_key_inited);
59 void PlatformTSDDtor(void *tsd) {
60 AsanThread::TSDDtor(tsd);
62 // ---------------------- Various stuff ---------------- {{{1
64 // No need to re-exec on Windows.
67 void *AsanDoesNotSupportStaticLinkage() {
69 #error Please build the runtime with a non-debug CRT: /MD or /MT
74 void AsanCheckDynamicRTPrereqs() {}
76 void AsanCheckIncompatibleRT() {}
78 void AsanPlatformThreadInit() {
79 // Nothing here for now.
82 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
86 void AsanOnSIGSEGV(int, void *siginfo, void *context) {
90 static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
92 SignalContext SignalContext::Create(void *siginfo, void *context) {
93 EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD*)siginfo;
94 CONTEXT *context_record = (CONTEXT*)context;
96 uptr pc = (uptr)exception_record->ExceptionAddress;
98 uptr bp = (uptr)context_record->Rbp;
99 uptr sp = (uptr)context_record->Rsp;
101 uptr bp = (uptr)context_record->Ebp;
102 uptr sp = (uptr)context_record->Esp;
104 uptr access_addr = exception_record->ExceptionInformation[1];
106 return SignalContext(context, access_addr, pc, sp, bp);
109 static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
110 EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
111 CONTEXT *context = info->ContextRecord;
113 if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
114 exception_record->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) {
115 const char *description =
116 (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
119 SignalContext sig = SignalContext::Create(exception_record, context);
120 ReportSIGSEGV(description, sig);
123 // FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
125 return default_seh_handler(info);
128 // We want to install our own exception handler (EH) to print helpful reports
129 // on access violations and whatnot. Unfortunately, the CRT initializers assume
130 // they are run before any user code and drop any previously-installed EHs on
131 // the floor, so we can't install our handler inside __asan_init.
132 // (See crt0dat.c in the CRT sources for the details)
134 // Things get even more complicated with the dynamic runtime, as it finishes its
135 // initialization before the .exe module CRT begins to initialize.
137 // For the static runtime (-MT), it's enough to put a callback to
138 // __asan_set_seh_filter in the last section for C initializers.
140 // For the dynamic runtime (-MD), we want link the same
141 // asan_dynamic_runtime_thunk.lib to all the modules, thus __asan_set_seh_filter
142 // will be called for each instrumented module. This ensures that at least one
143 // __asan_set_seh_filter call happens after the .exe module CRT is initialized.
144 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
145 int __asan_set_seh_filter() {
146 // We should only store the previous handler if it's not our own handler in
147 // order to avoid loops in the EH chain.
148 auto prev_seh_handler = SetUnhandledExceptionFilter(SEHHandler);
149 if (prev_seh_handler != &SEHHandler)
150 default_seh_handler = prev_seh_handler;
155 // Put a pointer to __asan_set_seh_filter at the end of the global list
156 // of C initializers, after the default EH is set by the CRT.
157 #pragma section(".CRT$XIZ", long, read) // NOLINT
158 static __declspec(allocate(".CRT$XIZ"))
159 int (*__intercept_seh)() = __asan_set_seh_filter;
162 } // namespace __asan