13e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov//===-- asan_win.cc -------------------------------------------------------===// 23e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// 33e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// The LLVM Compiler Infrastructure 43e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// 53e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// This file is distributed under the University of Illinois Open Source 63e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// License. See LICENSE.TXT for details. 73e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// 83e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov//===----------------------------------------------------------------------===// 93e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// 103e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// This file is a part of AddressSanitizer, an address sanity checker. 113e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// 123e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// Windows-specific details. 133e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov//===----------------------------------------------------------------------===// 143e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#ifdef _WIN32 153e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#include <windows.h> 163e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 173e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#include <dbghelp.h> 18b823e3c5f7891dbbde1eb288237f5f3d5ed64d85Alexey Samsonov#include <stdlib.h> 193e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 203e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#include <new> // FIXME: temporarily needed for placement new in AsanLock. 213e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 223e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#include "asan_interceptors.h" 233e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#include "asan_internal.h" 243e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#include "asan_lock.h" 253e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#include "asan_thread.h" 26de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 273e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 283e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovnamespace __asan { 293e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 303e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1 313e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovstatic AsanLock dbghelp_lock(LINKER_INITIALIZED); 323e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovstatic bool dbghelp_initialized = false; 333e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#pragma comment(lib, "dbghelp.lib") 343e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 3569f2174b3bdee7fe6c6911778147fc7e35d57693Kostya Serebryanyvoid GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) { 3669f2174b3bdee7fe6c6911778147fc7e35d57693Kostya Serebryany stack->max_size = max_s; 373e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov void *tmp[kStackTraceMax]; 383e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 393e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: CaptureStackBackTrace might be too slow for us. 403e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: Compare with StackWalk64. 413e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 4269f2174b3bdee7fe6c6911778147fc7e35d57693Kostya Serebryany uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0); 4369f2174b3bdee7fe6c6911778147fc7e35d57693Kostya Serebryany uptr offset = 0; 443e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // Skip the RTL frames by searching for the PC in the stacktrace. 453e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: this doesn't work well for the malloc/free stacks yet. 4645c8d1b28305b8660597bca3645e3ad700d76160Kostya Serebryany for (uptr i = 0; i < cs_ret; i++) { 473f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if (pc != (uptr)tmp[i]) 483e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov continue; 493e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov offset = i; 503e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov break; 513e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov } 523e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 5369f2174b3bdee7fe6c6911778147fc7e35d57693Kostya Serebryany stack->size = cs_ret - offset; 5469f2174b3bdee7fe6c6911778147fc7e35d57693Kostya Serebryany for (uptr i = 0; i < stack->size; i++) 5569f2174b3bdee7fe6c6911778147fc7e35d57693Kostya Serebryany stack->trace[i] = (uptr)tmp[i + offset]; 563e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 573e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 58c93d3e2bdfb1ad9cce26a6e8d66764ed97a6d6b4Alexey Samsonovbool WinSymbolize(const void *addr, char *out_buffer, int buffer_size) { 593e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov ScopedLock lock(&dbghelp_lock); 603e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov if (!dbghelp_initialized) { 613e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov SymSetOptions(SYMOPT_DEFERRED_LOADS | 623e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov SYMOPT_UNDNAME | 633e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov SYMOPT_LOAD_LINES); 643f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE)); 653e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: We don't call SymCleanup() on exit yet - should we? 663e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov dbghelp_initialized = true; 673e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov } 683e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 693e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx 703e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; 713e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; 723e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov symbol->SizeOfStruct = sizeof(SYMBOL_INFO); 733e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov symbol->MaxNameLen = MAX_SYM_NAME; 743e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov DWORD64 offset = 0; 753e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov BOOL got_objname = SymFromAddr(GetCurrentProcess(), 763e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov (DWORD64)addr, &offset, symbol); 773e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov if (!got_objname) 783e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov return false; 793e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 803e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov DWORD unused; 813e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov IMAGEHLP_LINE64 info; 823e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); 833e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), 843e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov (DWORD64)addr, &unused, &info); 853e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov int written = 0; 863e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov out_buffer[0] = '\0'; 873e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too. 883e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov if (got_fileline) { 89de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov written += internal_snprintf(out_buffer + written, buffer_size - written, 903e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov " %s %s:%d", symbol->Name, 913e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov info.FileName, info.LineNumber); 923e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov } else { 93de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov written += internal_snprintf(out_buffer + written, buffer_size - written, 943e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov " %s+0x%p", symbol->Name, offset); 953e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov } 963e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov return true; 973e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 983e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 993e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// ---------------------- AsanLock ---------------- {{{1 1003e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovenum LockState { 1013e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov LOCK_UNINITIALIZED = 0, 1023e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov LOCK_READY = -1, 1033e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov}; 1043e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1053e81fe43798c096d1d3565596f0717b9919de4fbTimur IskhodzhanovAsanLock::AsanLock(LinkerInitialized li) { 1063e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: see comments in AsanLock::Lock() for the details. 1073e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED); 1083e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1093e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 1103e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 1113e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov owner_ = LOCK_READY; 1123e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 1133e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1143e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovvoid AsanLock::Lock() { 1153e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov if (owner_ == LOCK_UNINITIALIZED) { 1163e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: hm, global AsanLock objects are not initialized?!? 1173e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // This might be a side effect of the clang+cl+link Frankenbuild... 1183e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov new(this) AsanLock((LinkerInitialized)(LINKER_INITIALIZED + 1)); 1193e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1203e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: If it turns out the linker doesn't invoke our 1213e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // constructors, we should probably manually Lock/Unlock all the global 1223e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // locks while we're starting in one thread to avoid double-init races. 1233e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov } 1243e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 1253e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov CHECK(owner_ == LOCK_READY); 1263e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov owner_ = GetThreadSelf(); 1273e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 1283e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1293e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovvoid AsanLock::Unlock() { 1303e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov CHECK(owner_ == GetThreadSelf()); 1313e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov owner_ = LOCK_READY; 1323e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 1333e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 1343e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1353e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// ---------------------- TSD ---------------- {{{1 1363e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovstatic bool tsd_key_inited = false; 1373e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1383f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic __declspec(thread) void *fake_tsd = 0; 1393e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1403e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovvoid AsanTSDInit(void (*destructor)(void *tsd)) { 1413e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: we're ignoring the destructor for now. 1423e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov tsd_key_inited = true; 1433e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 1443e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1453e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovvoid *AsanTSDGet() { 1463e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov CHECK(tsd_key_inited); 1473e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov return fake_tsd; 1483e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 1493e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1503e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovvoid AsanTSDSet(void *tsd) { 1513e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov CHECK(tsd_key_inited); 1523e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov fake_tsd = tsd; 1533e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 1543e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1553e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov// ---------------------- Various stuff ---------------- {{{1 156eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenkovoid MaybeReexec() { 157eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko // No need to re-exec on Windows. 158eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko} 159eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko 1603e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovvoid *AsanDoesNotSupportStaticLinkage() { 1612716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov#if defined(_DEBUG) 1622716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov#error Please build the runtime with a non-debug CRT: /MD or /MT 16307bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif 1643f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 1653e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 1663e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 167f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenkovoid SetAlternateSignalStack() { 168f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko // FIXME: Decide what to do on Windows. 169f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko} 170f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko 171f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenkovoid UnsetAlternateSignalStack() { 172f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko // FIXME: Decide what to do on Windows. 173f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko} 174f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko 1753e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanovvoid InstallSignalHandlers() { 1763e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov // FIXME: Decide what to do on Windows. 1773e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} 1783e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 17975b19ebf25af204cf209d108997272822241d6daAlexander Potapenkovoid AsanPlatformThreadInit() { 18075b19ebf25af204cf209d108997272822241d6daAlexander Potapenko // Nothing here for now. 18175b19ebf25af204cf209d108997272822241d6daAlexander Potapenko} 18275b19ebf25af204cf209d108997272822241d6daAlexander Potapenko 1833e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} // namespace __asan 1843e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 1853e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#endif // _WIN32 186