asan_win.cc revision 1ca535700966cf5019dcc6684a62a734a7b96974
16f56ab789cb470620554d624c37f488285b3b04eDan Albert//===-- asan_win.cc -------------------------------------------------------===// 26f56ab789cb470620554d624c37f488285b3b04eDan Albert// 36f56ab789cb470620554d624c37f488285b3b04eDan Albert// The LLVM Compiler Infrastructure 46f56ab789cb470620554d624c37f488285b3b04eDan Albert// 56f56ab789cb470620554d624c37f488285b3b04eDan Albert// This file is distributed under the University of Illinois Open Source 66f56ab789cb470620554d624c37f488285b3b04eDan Albert// License. See LICENSE.TXT for details. 76f56ab789cb470620554d624c37f488285b3b04eDan Albert// 86f56ab789cb470620554d624c37f488285b3b04eDan Albert//===----------------------------------------------------------------------===// 96f56ab789cb470620554d624c37f488285b3b04eDan Albert// 106f56ab789cb470620554d624c37f488285b3b04eDan Albert// This file is a part of AddressSanitizer, an address sanity checker. 116f56ab789cb470620554d624c37f488285b3b04eDan Albert// 126f56ab789cb470620554d624c37f488285b3b04eDan Albert// Windows-specific details. 136f56ab789cb470620554d624c37f488285b3b04eDan Albert//===----------------------------------------------------------------------===// 146f56ab789cb470620554d624c37f488285b3b04eDan Albert#ifdef _WIN32 156f56ab789cb470620554d624c37f488285b3b04eDan Albert#include <windows.h> 166f56ab789cb470620554d624c37f488285b3b04eDan Albert 176f56ab789cb470620554d624c37f488285b3b04eDan Albert#include <dbghelp.h> 186f56ab789cb470620554d624c37f488285b3b04eDan Albert#include <stdlib.h> 196f56ab789cb470620554d624c37f488285b3b04eDan Albert 206f56ab789cb470620554d624c37f488285b3b04eDan Albert#include <new> // FIXME: temporarily needed for placement new in AsanLock. 216f56ab789cb470620554d624c37f488285b3b04eDan Albert 226f56ab789cb470620554d624c37f488285b3b04eDan Albert#include "asan_interceptors.h" 236f56ab789cb470620554d624c37f488285b3b04eDan Albert#include "asan_internal.h" 246f56ab789cb470620554d624c37f488285b3b04eDan Albert#include "asan_lock.h" 256f56ab789cb470620554d624c37f488285b3b04eDan Albert#include "asan_thread.h" 266f56ab789cb470620554d624c37f488285b3b04eDan Albert#include "sanitizer_common/sanitizer_libc.h" 276f56ab789cb470620554d624c37f488285b3b04eDan Albert 286f56ab789cb470620554d624c37f488285b3b04eDan Albertnamespace __asan { 296f56ab789cb470620554d624c37f488285b3b04eDan Albert 306f56ab789cb470620554d624c37f488285b3b04eDan Albert// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1 316f56ab789cb470620554d624c37f488285b3b04eDan Albertstatic AsanLock dbghelp_lock(LINKER_INITIALIZED); 326f56ab789cb470620554d624c37f488285b3b04eDan Albertstatic bool dbghelp_initialized = false; 336f56ab789cb470620554d624c37f488285b3b04eDan Albert#pragma comment(lib, "dbghelp.lib") 346f56ab789cb470620554d624c37f488285b3b04eDan Albert 356f56ab789cb470620554d624c37f488285b3b04eDan Albertvoid GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) { 366f56ab789cb470620554d624c37f488285b3b04eDan Albert stack->max_size = max_s; 376f56ab789cb470620554d624c37f488285b3b04eDan Albert void *tmp[kStackTraceMax]; 386f56ab789cb470620554d624c37f488285b3b04eDan Albert 396f56ab789cb470620554d624c37f488285b3b04eDan Albert // FIXME: CaptureStackBackTrace might be too slow for us. 406f56ab789cb470620554d624c37f488285b3b04eDan Albert // FIXME: Compare with StackWalk64. 416f56ab789cb470620554d624c37f488285b3b04eDan Albert // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 426f56ab789cb470620554d624c37f488285b3b04eDan Albert uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0); 436f56ab789cb470620554d624c37f488285b3b04eDan Albert uptr offset = 0; 446f56ab789cb470620554d624c37f488285b3b04eDan Albert // Skip the RTL frames by searching for the PC in the stacktrace. 456f56ab789cb470620554d624c37f488285b3b04eDan Albert // FIXME: this doesn't work well for the malloc/free stacks yet. 466f56ab789cb470620554d624c37f488285b3b04eDan Albert for (uptr i = 0; i < cs_ret; i++) { 476f56ab789cb470620554d624c37f488285b3b04eDan Albert if (pc != (uptr)tmp[i]) 486f56ab789cb470620554d624c37f488285b3b04eDan Albert continue; 496f56ab789cb470620554d624c37f488285b3b04eDan Albert offset = i; 506f56ab789cb470620554d624c37f488285b3b04eDan Albert break; 516f56ab789cb470620554d624c37f488285b3b04eDan Albert } 526f56ab789cb470620554d624c37f488285b3b04eDan Albert 536f56ab789cb470620554d624c37f488285b3b04eDan Albert stack->size = cs_ret - offset; 546f56ab789cb470620554d624c37f488285b3b04eDan Albert for (uptr i = 0; i < stack->size; i++) 556f56ab789cb470620554d624c37f488285b3b04eDan Albert stack->trace[i] = (uptr)tmp[i + offset]; 566f56ab789cb470620554d624c37f488285b3b04eDan Albert} 576f56ab789cb470620554d624c37f488285b3b04eDan Albert 586f56ab789cb470620554d624c37f488285b3b04eDan Albert// ---------------------- AsanLock ---------------- {{{1 596f56ab789cb470620554d624c37f488285b3b04eDan Albertenum LockState { 606f56ab789cb470620554d624c37f488285b3b04eDan Albert LOCK_UNINITIALIZED = 0, 616f56ab789cb470620554d624c37f488285b3b04eDan Albert LOCK_READY = -1, 626f56ab789cb470620554d624c37f488285b3b04eDan Albert}; 636f56ab789cb470620554d624c37f488285b3b04eDan Albert 646f56ab789cb470620554d624c37f488285b3b04eDan AlbertAsanLock::AsanLock(LinkerInitialized li) { 656f56ab789cb470620554d624c37f488285b3b04eDan Albert // FIXME: see comments in AsanLock::Lock() for the details. 666f56ab789cb470620554d624c37f488285b3b04eDan Albert CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED); 676f56ab789cb470620554d624c37f488285b3b04eDan Albert 686f56ab789cb470620554d624c37f488285b3b04eDan Albert CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 696f56ab789cb470620554d624c37f488285b3b04eDan Albert InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 706f56ab789cb470620554d624c37f488285b3b04eDan Albert owner_ = LOCK_READY; 716f56ab789cb470620554d624c37f488285b3b04eDan Albert} 726f56ab789cb470620554d624c37f488285b3b04eDan Albert 736f56ab789cb470620554d624c37f488285b3b04eDan Albertvoid AsanLock::Lock() { 746f56ab789cb470620554d624c37f488285b3b04eDan Albert if (owner_ == LOCK_UNINITIALIZED) { 756f56ab789cb470620554d624c37f488285b3b04eDan Albert // FIXME: hm, global AsanLock objects are not initialized?!? 766f56ab789cb470620554d624c37f488285b3b04eDan Albert // This might be a side effect of the clang+cl+link Frankenbuild... 776f56ab789cb470620554d624c37f488285b3b04eDan Albert new(this) AsanLock((LinkerInitialized)(LINKER_INITIALIZED + 1)); 786f56ab789cb470620554d624c37f488285b3b04eDan Albert 796f56ab789cb470620554d624c37f488285b3b04eDan Albert // FIXME: If it turns out the linker doesn't invoke our 806f56ab789cb470620554d624c37f488285b3b04eDan Albert // constructors, we should probably manually Lock/Unlock all the global 816f56ab789cb470620554d624c37f488285b3b04eDan Albert // locks while we're starting in one thread to avoid double-init races. 826f56ab789cb470620554d624c37f488285b3b04eDan Albert } 836f56ab789cb470620554d624c37f488285b3b04eDan Albert EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 846f56ab789cb470620554d624c37f488285b3b04eDan Albert CHECK(owner_ == LOCK_READY); 856f56ab789cb470620554d624c37f488285b3b04eDan Albert owner_ = GetThreadSelf(); 866f56ab789cb470620554d624c37f488285b3b04eDan Albert} 876f56ab789cb470620554d624c37f488285b3b04eDan Albert 886f56ab789cb470620554d624c37f488285b3b04eDan Albertvoid AsanLock::Unlock() { 896f56ab789cb470620554d624c37f488285b3b04eDan Albert CHECK(owner_ == GetThreadSelf()); 906f56ab789cb470620554d624c37f488285b3b04eDan Albert owner_ = LOCK_READY; 916f56ab789cb470620554d624c37f488285b3b04eDan Albert LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 92} 93 94// ---------------------- TSD ---------------- {{{1 95static bool tsd_key_inited = false; 96 97static __declspec(thread) void *fake_tsd = 0; 98 99void AsanTSDInit(void (*destructor)(void *tsd)) { 100 // FIXME: we're ignoring the destructor for now. 101 tsd_key_inited = true; 102} 103 104void *AsanTSDGet() { 105 CHECK(tsd_key_inited); 106 return fake_tsd; 107} 108 109void AsanTSDSet(void *tsd) { 110 CHECK(tsd_key_inited); 111 fake_tsd = tsd; 112} 113 114// ---------------------- Various stuff ---------------- {{{1 115void MaybeReexec() { 116 // No need to re-exec on Windows. 117} 118 119void *AsanDoesNotSupportStaticLinkage() { 120#if defined(_DEBUG) 121#error Please build the runtime with a non-debug CRT: /MD or /MT 122#endif 123 return 0; 124} 125 126void SetAlternateSignalStack() { 127 // FIXME: Decide what to do on Windows. 128} 129 130void UnsetAlternateSignalStack() { 131 // FIXME: Decide what to do on Windows. 132} 133 134void InstallSignalHandlers() { 135 // FIXME: Decide what to do on Windows. 136} 137 138void AsanPlatformThreadInit() { 139 // Nothing here for now. 140} 141 142} // namespace __asan 143 144// ---------------------- Interface ---------------- {{{1 145using namespace __asan; // NOLINT 146 147bool __asan_symbolize(const void *addr, char *out_buffer, int buffer_size) { 148 ScopedLock lock(&dbghelp_lock); 149 if (!dbghelp_initialized) { 150 SymSetOptions(SYMOPT_DEFERRED_LOADS | 151 SYMOPT_UNDNAME | 152 SYMOPT_LOAD_LINES); 153 CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE)); 154 // FIXME: We don't call SymCleanup() on exit yet - should we? 155 dbghelp_initialized = true; 156 } 157 158 // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx 159 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; 160 PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; 161 symbol->SizeOfStruct = sizeof(SYMBOL_INFO); 162 symbol->MaxNameLen = MAX_SYM_NAME; 163 DWORD64 offset = 0; 164 BOOL got_objname = SymFromAddr(GetCurrentProcess(), 165 (DWORD64)addr, &offset, symbol); 166 if (!got_objname) 167 return false; 168 169 DWORD unused; 170 IMAGEHLP_LINE64 info; 171 info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); 172 BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), 173 (DWORD64)addr, &unused, &info); 174 int written = 0; 175 out_buffer[0] = '\0'; 176 // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too. 177 if (got_fileline) { 178 written += internal_snprintf(out_buffer + written, buffer_size - written, 179 " %s %s:%d", symbol->Name, 180 info.FileName, info.LineNumber); 181 } else { 182 written += internal_snprintf(out_buffer + written, buffer_size - written, 183 " %s+0x%p", symbol->Name, offset); 184 } 185 return true; 186} 187 188 189 190#endif // _WIN32 191