Home | History | Annotate | Download | only in asan
      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 
     15 #include "sanitizer_common/sanitizer_platform.h"
     16 #if SANITIZER_WINDOWS
     17 #include <windows.h>
     18 
     19 #include <dbghelp.h>
     20 #include <stdlib.h>
     21 
     22 #include "asan_interceptors.h"
     23 #include "asan_internal.h"
     24 #include "asan_thread.h"
     25 #include "sanitizer_common/sanitizer_libc.h"
     26 #include "sanitizer_common/sanitizer_mutex.h"
     27 
     28 namespace __asan {
     29 
     30 // ---------------------- Stacktraces, symbols, etc. ---------------- {{{1
     31 static BlockingMutex dbghelp_lock(LINKER_INITIALIZED);
     32 static bool dbghelp_initialized = false;
     33 #pragma comment(lib, "dbghelp.lib")
     34 
     35 // ---------------------- TSD ---------------- {{{1
     36 static bool tsd_key_inited = false;
     37 
     38 static __declspec(thread) void *fake_tsd = 0;
     39 
     40 void AsanTSDInit(void (*destructor)(void *tsd)) {
     41   // FIXME: we're ignoring the destructor for now.
     42   tsd_key_inited = true;
     43 }
     44 
     45 void *AsanTSDGet() {
     46   CHECK(tsd_key_inited);
     47   return fake_tsd;
     48 }
     49 
     50 void AsanTSDSet(void *tsd) {
     51   CHECK(tsd_key_inited);
     52   fake_tsd = tsd;
     53 }
     54 
     55 // ---------------------- Various stuff ---------------- {{{1
     56 void MaybeReexec() {
     57   // No need to re-exec on Windows.
     58 }
     59 
     60 void *AsanDoesNotSupportStaticLinkage() {
     61 #if defined(_DEBUG)
     62 #error Please build the runtime with a non-debug CRT: /MD or /MT
     63 #endif
     64   return 0;
     65 }
     66 
     67 void SetAlternateSignalStack() {
     68   // FIXME: Decide what to do on Windows.
     69 }
     70 
     71 void UnsetAlternateSignalStack() {
     72   // FIXME: Decide what to do on Windows.
     73 }
     74 
     75 void InstallSignalHandlers() {
     76   // FIXME: Decide what to do on Windows.
     77 }
     78 
     79 void AsanPlatformThreadInit() {
     80   // Nothing here for now.
     81 }
     82 
     83 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
     84   UNIMPLEMENTED();
     85 }
     86 
     87 }  // namespace __asan
     88 
     89 // ---------------------- Interface ---------------- {{{1
     90 using namespace __asan;  // NOLINT
     91 
     92 extern "C" {
     93 SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
     94 bool __asan_symbolize(const void *addr, char *out_buffer, int buffer_size) {
     95   BlockingMutexLock lock(&dbghelp_lock);
     96   if (!dbghelp_initialized) {
     97     SymSetOptions(SYMOPT_DEFERRED_LOADS |
     98                   SYMOPT_UNDNAME |
     99                   SYMOPT_LOAD_LINES);
    100     CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE));
    101     // FIXME: We don't call SymCleanup() on exit yet - should we?
    102     dbghelp_initialized = true;
    103   }
    104 
    105   // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
    106   char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
    107   PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
    108   symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    109   symbol->MaxNameLen = MAX_SYM_NAME;
    110   DWORD64 offset = 0;
    111   BOOL got_objname = SymFromAddr(GetCurrentProcess(),
    112                                  (DWORD64)addr, &offset, symbol);
    113   if (!got_objname)
    114     return false;
    115 
    116   DWORD  unused;
    117   IMAGEHLP_LINE64 info;
    118   info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    119   BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(),
    120                                            (DWORD64)addr, &unused, &info);
    121   int written = 0;
    122   out_buffer[0] = '\0';
    123   // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too.
    124   if (got_fileline) {
    125     written += internal_snprintf(out_buffer + written, buffer_size - written,
    126                         " %s %s:%d", symbol->Name,
    127                         info.FileName, info.LineNumber);
    128   } else {
    129     written += internal_snprintf(out_buffer + written, buffer_size - written,
    130                         " %s+0x%p", symbol->Name, offset);
    131   }
    132   return true;
    133 }
    134 }  // extern "C"
    135 
    136 
    137 #endif  // _WIN32
    138