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