asan_win.cc revision 69f2174b3bdee7fe6c6911778147fc7e35d57693
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#ifdef _WIN32 15#include <windows.h> 16 17#include <dbghelp.h> 18#include <stdlib.h> 19 20#include <new> // FIXME: temporarily needed for placement new in AsanLock. 21 22#include "asan_interceptors.h" 23#include "asan_internal.h" 24#include "asan_lock.h" 25#include "asan_thread.h" 26#include "sanitizer_common/sanitizer_libc.h" 27 28namespace __asan { 29 30// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1 31static AsanLock 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) { 36 stack->max_size = max_s; 37 void *tmp[kStackTraceMax]; 38 39 // FIXME: CaptureStackBackTrace might be too slow for us. 40 // FIXME: Compare with StackWalk64. 41 // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 42 uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0); 43 uptr offset = 0; 44 // Skip the RTL frames by searching for the PC in the stacktrace. 45 // FIXME: this doesn't work well for the malloc/free stacks yet. 46 for (uptr i = 0; i < cs_ret; i++) { 47 if (pc != (uptr)tmp[i]) 48 continue; 49 offset = i; 50 break; 51 } 52 53 stack->size = cs_ret - offset; 54 for (uptr i = 0; i < stack->size; i++) 55 stack->trace[i] = (uptr)tmp[i + offset]; 56} 57 58bool WinSymbolize(const void *addr, char *out_buffer, int buffer_size) { 59 ScopedLock lock(&dbghelp_lock); 60 if (!dbghelp_initialized) { 61 SymSetOptions(SYMOPT_DEFERRED_LOADS | 62 SYMOPT_UNDNAME | 63 SYMOPT_LOAD_LINES); 64 CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE)); 65 // FIXME: We don't call SymCleanup() on exit yet - should we? 66 dbghelp_initialized = true; 67 } 68 69 // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx 70 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; 71 PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; 72 symbol->SizeOfStruct = sizeof(SYMBOL_INFO); 73 symbol->MaxNameLen = MAX_SYM_NAME; 74 DWORD64 offset = 0; 75 BOOL got_objname = SymFromAddr(GetCurrentProcess(), 76 (DWORD64)addr, &offset, symbol); 77 if (!got_objname) 78 return false; 79 80 DWORD unused; 81 IMAGEHLP_LINE64 info; 82 info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); 83 BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), 84 (DWORD64)addr, &unused, &info); 85 int written = 0; 86 out_buffer[0] = '\0'; 87 // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too. 88 if (got_fileline) { 89 written += internal_snprintf(out_buffer + written, buffer_size - written, 90 " %s %s:%d", symbol->Name, 91 info.FileName, info.LineNumber); 92 } else { 93 written += internal_snprintf(out_buffer + written, buffer_size - written, 94 " %s+0x%p", symbol->Name, offset); 95 } 96 return true; 97} 98 99// ---------------------- AsanLock ---------------- {{{1 100enum LockState { 101 LOCK_UNINITIALIZED = 0, 102 LOCK_READY = -1, 103}; 104 105AsanLock::AsanLock(LinkerInitialized li) { 106 // FIXME: see comments in AsanLock::Lock() for the details. 107 CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED); 108 109 CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 110 InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 111 owner_ = LOCK_READY; 112} 113 114void AsanLock::Lock() { 115 if (owner_ == LOCK_UNINITIALIZED) { 116 // FIXME: hm, global AsanLock objects are not initialized?!? 117 // This might be a side effect of the clang+cl+link Frankenbuild... 118 new(this) AsanLock((LinkerInitialized)(LINKER_INITIALIZED + 1)); 119 120 // FIXME: If it turns out the linker doesn't invoke our 121 // constructors, we should probably manually Lock/Unlock all the global 122 // locks while we're starting in one thread to avoid double-init races. 123 } 124 EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 125 CHECK(owner_ == LOCK_READY); 126 owner_ = GetThreadSelf(); 127} 128 129void AsanLock::Unlock() { 130 CHECK(owner_ == GetThreadSelf()); 131 owner_ = LOCK_READY; 132 LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 133} 134 135// ---------------------- TSD ---------------- {{{1 136static bool tsd_key_inited = false; 137 138static __declspec(thread) void *fake_tsd = 0; 139 140void AsanTSDInit(void (*destructor)(void *tsd)) { 141 // FIXME: we're ignoring the destructor for now. 142 tsd_key_inited = true; 143} 144 145void *AsanTSDGet() { 146 CHECK(tsd_key_inited); 147 return fake_tsd; 148} 149 150void AsanTSDSet(void *tsd) { 151 CHECK(tsd_key_inited); 152 fake_tsd = tsd; 153} 154 155// ---------------------- Various stuff ---------------- {{{1 156void MaybeReexec() { 157 // No need to re-exec on Windows. 158} 159 160void *AsanDoesNotSupportStaticLinkage() { 161#if defined(_DEBUG) 162#error Please build the runtime with a non-debug CRT: /MD or /MT 163#endif 164 return 0; 165} 166 167void SetAlternateSignalStack() { 168 // FIXME: Decide what to do on Windows. 169} 170 171void UnsetAlternateSignalStack() { 172 // FIXME: Decide what to do on Windows. 173} 174 175void InstallSignalHandlers() { 176 // FIXME: Decide what to do on Windows. 177} 178 179void AsanPlatformThreadInit() { 180 // Nothing here for now. 181} 182 183} // namespace __asan 184 185#endif // _WIN32 186