asan_win.cc revision 57db4bae483e7268dd7fc5bc42b0e55564014048
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- asan_win.cc -------------------------------------------------------===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is a part of AddressSanitizer, an address sanity checker.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows-specific details.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _WIN32
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dbghelp.h>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_interceptors.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_internal.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_thread.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_common/sanitizer_libc.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_common/sanitizer_mutex.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace __asan {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static BlockingMutex dbghelp_lock(LINKER_INITIALIZED);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool dbghelp_initialized = false;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "dbghelp.lib")
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void)fast;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack->max_size = max_s;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *tmp[kStackTraceMax];
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // FIXME: CaptureStackBackTrace might be too slow for us.
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // FIXME: Compare with StackWalk64.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  uptr offset = 0;
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Skip the RTL frames by searching for the PC in the stacktrace.
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // FIXME: this doesn't work well for the malloc/free stacks yet.
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (uptr i = 0; i < cs_ret; i++) {
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (pc != (uptr)tmp[i])
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      continue;
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    offset = i;
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    break;
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stack->size = cs_ret - offset;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (uptr i = 0; i < stack->size; i++)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stack->trace[i] = (uptr)tmp[i + offset];
55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// ---------------------- TSD ---------------- {{{1
58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic bool tsd_key_inited = false;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static __declspec(thread) void *fake_tsd = 0;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AsanTSDInit(void (*destructor)(void *tsd)) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIXME: we're ignoring the destructor for now.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tsd_key_inited = true;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *AsanTSDGet() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(tsd_key_inited);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fake_tsd;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AsanTSDSet(void *tsd) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(tsd_key_inited);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fake_tsd = tsd;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------- Various stuff ---------------- {{{1
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MaybeReexec() {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No need to re-exec on Windows.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *AsanDoesNotSupportStaticLinkage() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_DEBUG)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Please build the runtime with a non-debug CRT: /MD or /MT
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SetAlternateSignalStack() {
908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // FIXME: Decide what to do on Windows.
918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void UnsetAlternateSignalStack() {
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // FIXME: Decide what to do on Windows.
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void InstallSignalHandlers() {
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // FIXME: Decide what to do on Windows.
99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AsanPlatformThreadInit() {
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Nothing here for now.
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNIMPLEMENTED();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace __asan
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------- Interface ---------------- {{{1
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace __asan;  // NOLINT
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool __asan_symbolize(const void *addr, char *out_buffer, int buffer_size) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockingMutexLock lock(&dbghelp_lock);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dbghelp_initialized) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SymSetOptions(SYMOPT_DEFERRED_LOADS |
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  SYMOPT_UNDNAME |
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  SYMOPT_LOAD_LINES);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // FIXME: We don't call SymCleanup() on exit yet - should we?
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbghelp_initialized = true;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  symbol->MaxNameLen = MAX_SYM_NAME;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD64 offset = 0;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL got_objname = SymFromAddr(GetCurrentProcess(),
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 (DWORD64)addr, &offset, symbol);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!got_objname)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD  unused;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IMAGEHLP_LINE64 info;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(),
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           (DWORD64)addr, &unused, &info);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int written = 0;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out_buffer[0] = '\0';
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (got_fileline) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    written += internal_snprintf(out_buffer + written, buffer_size - written,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        " %s %s:%d", symbol->Name,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        info.FileName, info.LineNumber);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    written += internal_snprintf(out_buffer + written, buffer_size - written,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        " %s+0x%p", symbol->Name, offset);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // extern "C"
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // _WIN32
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)