asan_win.cc revision 24e13723f8477d8c42ab8b2a7f4f69fc089842f1
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. 11// 12// Windows-specific details. 13//===----------------------------------------------------------------------===// 14 15#include "sanitizer_common/sanitizer_platform.h" 16#ifdef _WIN32 17#include <windows.h> 18 19#include <dbghelp.h> 20#include <stdlib.h> 21 22#include "asan_interceptors.h" 23#include "asan_internal.h" 24#include "asan_thread.h" 25#include "sanitizer_common/sanitizer_libc.h" 26#include "sanitizer_common/sanitizer_mutex.h" 27 28namespace __asan { 29 30// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1 31static BlockingMutex dbghelp_lock(LINKER_INITIALIZED); 32static bool dbghelp_initialized = false; 33#pragma comment(lib, "dbghelp.lib") 34 35void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) { 36 (void)fast; 37 stack->max_size = max_s; 38 void *tmp[kStackTraceMax]; 39 40 // FIXME: CaptureStackBackTrace might be too slow for us. 41 // FIXME: Compare with StackWalk64. 42 // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 43 uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0); 44 uptr offset = 0; 45 // Skip the RTL frames by searching for the PC in the stacktrace. 46 // FIXME: this doesn't work well for the malloc/free stacks yet. 47 for (uptr i = 0; i < cs_ret; i++) { 48 if (pc != (uptr)tmp[i]) 49 continue; 50 offset = i; 51 break; 52 } 53 54 stack->size = cs_ret - offset; 55 for (uptr i = 0; i < stack->size; i++) 56 stack->trace[i] = (uptr)tmp[i + offset]; 57} 58 59// ---------------------- TSD ---------------- {{{1 60static bool tsd_key_inited = false; 61 62static __declspec(thread) void *fake_tsd = 0; 63 64void AsanTSDInit(void (*destructor)(void *tsd)) { 65 // FIXME: we're ignoring the destructor for now. 66 tsd_key_inited = true; 67} 68 69void *AsanTSDGet() { 70 CHECK(tsd_key_inited); 71 return fake_tsd; 72} 73 74void AsanTSDSet(void *tsd) { 75 CHECK(tsd_key_inited); 76 fake_tsd = tsd; 77} 78 79// ---------------------- Various stuff ---------------- {{{1 80void MaybeReexec() { 81 // No need to re-exec on Windows. 82} 83 84void *AsanDoesNotSupportStaticLinkage() { 85#if defined(_DEBUG) 86#error Please build the runtime with a non-debug CRT: /MD or /MT 87#endif 88 return 0; 89} 90 91void SetAlternateSignalStack() { 92 // FIXME: Decide what to do on Windows. 93} 94 95void UnsetAlternateSignalStack() { 96 // FIXME: Decide what to do on Windows. 97} 98 99void InstallSignalHandlers() { 100 // FIXME: Decide what to do on Windows. 101} 102 103void AsanPlatformThreadInit() { 104 // Nothing here for now. 105} 106 107void ReadContextStack(void *context, uptr *stack, uptr *ssize) { 108 UNIMPLEMENTED(); 109} 110 111} // namespace __asan 112 113// ---------------------- Interface ---------------- {{{1 114using namespace __asan; // NOLINT 115 116extern "C" { 117SANITIZER_INTERFACE_ATTRIBUTE NOINLINE 118bool __asan_symbolize(const void *addr, char *out_buffer, int buffer_size) { 119 BlockingMutexLock lock(&dbghelp_lock); 120 if (!dbghelp_initialized) { 121 SymSetOptions(SYMOPT_DEFERRED_LOADS | 122 SYMOPT_UNDNAME | 123 SYMOPT_LOAD_LINES); 124 CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE)); 125 // FIXME: We don't call SymCleanup() on exit yet - should we? 126 dbghelp_initialized = true; 127 } 128 129 // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx 130 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; 131 PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; 132 symbol->SizeOfStruct = sizeof(SYMBOL_INFO); 133 symbol->MaxNameLen = MAX_SYM_NAME; 134 DWORD64 offset = 0; 135 BOOL got_objname = SymFromAddr(GetCurrentProcess(), 136 (DWORD64)addr, &offset, symbol); 137 if (!got_objname) 138 return false; 139 140 DWORD unused; 141 IMAGEHLP_LINE64 info; 142 info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); 143 BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), 144 (DWORD64)addr, &unused, &info); 145 int written = 0; 146 out_buffer[0] = '\0'; 147 // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too. 148 if (got_fileline) { 149 written += internal_snprintf(out_buffer + written, buffer_size - written, 150 " %s %s:%d", symbol->Name, 151 info.FileName, info.LineNumber); 152 } else { 153 written += internal_snprintf(out_buffer + written, buffer_size - written, 154 " %s+0x%p", symbol->Name, offset); 155 } 156 return true; 157} 158} // extern "C" 159 160 161#endif // _WIN32 162