1//===-- asan_win.cc -------------------------------------------------------===// 2// 3// This file is distributed under the University of Illinois Open Source 4// License. See LICENSE.TXT for details. 5// 6//===----------------------------------------------------------------------===// 7// 8// This file is a part of AddressSanitizer, an address sanity checker. 9// 10// Windows-specific details. 11//===----------------------------------------------------------------------===// 12 13#include "sanitizer_common/sanitizer_platform.h" 14#if SANITIZER_WINDOWS 15#include <windows.h> 16 17#include <dbghelp.h> 18#include <stdlib.h> 19 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" 26 27extern "C" { 28 SANITIZER_INTERFACE_ATTRIBUTE 29 int __asan_should_detect_stack_use_after_return() { 30 __asan_init(); 31 return __asan_option_detect_stack_use_after_return; 32 } 33} 34 35namespace __asan { 36 37// ---------------------- TSD ---------------- {{{1 38static bool tsd_key_inited = false; 39 40static __declspec(thread) void *fake_tsd = 0; 41 42void AsanTSDInit(void (*destructor)(void *tsd)) { 43 // FIXME: we're ignoring the destructor for now. 44 tsd_key_inited = true; 45} 46 47void *AsanTSDGet() { 48 CHECK(tsd_key_inited); 49 return fake_tsd; 50} 51 52void AsanTSDSet(void *tsd) { 53 CHECK(tsd_key_inited); 54 fake_tsd = tsd; 55} 56 57void PlatformTSDDtor(void *tsd) { 58 AsanThread::TSDDtor(tsd); 59} 60// ---------------------- Various stuff ---------------- {{{1 61void MaybeReexec() { 62 // No need to re-exec on Windows. 63} 64 65void *AsanDoesNotSupportStaticLinkage() { 66#if defined(_DEBUG) 67#error Please build the runtime with a non-debug CRT: /MD or /MT 68#endif 69 return 0; 70} 71 72void AsanCheckDynamicRTPrereqs() {} 73 74void AsanCheckIncompatibleRT() {} 75 76void AsanPlatformThreadInit() { 77 // Nothing here for now. 78} 79 80void ReadContextStack(void *context, uptr *stack, uptr *ssize) { 81 UNIMPLEMENTED(); 82} 83 84void AsanOnSIGSEGV(int, void *siginfo, void *context) { 85 UNIMPLEMENTED(); 86} 87 88static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler; 89 90static 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; 94#ifdef _WIN64 95 uptr bp = (uptr)context->Rbp, sp = (uptr)context->Rsp; 96#else 97 uptr bp = (uptr)context->Ebp, sp = (uptr)context->Esp; 98#endif 99 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) 104 ? "access-violation" 105 : "in-page-error"; 106 uptr access_addr = exception_record->ExceptionInformation[1]; 107 ReportSIGSEGV(description, pc, sp, bp, context, access_addr); 108 } 109 110 // FIXME: Handle EXCEPTION_STACK_OVERFLOW here. 111 112 return default_seh_handler(info); 113} 114 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) 120// 121// Things get even more complicated with the dynamic runtime, as it finishes its 122// initialization before the .exe module CRT begins to initialize. 123// 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. 126// 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. 131extern "C" SANITIZER_INTERFACE_ATTRIBUTE 132int __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; 138 return 0; 139} 140 141#if !ASAN_DYNAMIC 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 145static __declspec(allocate(".CRT$XIZ")) 146 int (*__intercept_seh)() = __asan_set_seh_filter; 147#endif 148 149} // namespace __asan 150 151#endif // _WIN32 152