• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifdef _WIN32
15 #include <windows.h>
16 
17 #include <dbghelp.h>
18 #include <stdlib.h>
19 
20 #include <new>  // FIXME: temporarily needed for placement new in AsanLock.
21 
22 #include "asan_interceptors.h"
23 #include "asan_internal.h"
24 #include "asan_lock.h"
25 #include "asan_thread.h"
26 #include "sanitizer_common/sanitizer_libc.h"
27 
28 namespace __asan {
29 
30 // ---------------------- Stacktraces, symbols, etc. ---------------- {{{1
31 static AsanLock dbghelp_lock(LINKER_INITIALIZED);
32 static bool dbghelp_initialized = false;
33 #pragma comment(lib, "dbghelp.lib")
34 
GetStackTrace(StackTrace * stack,uptr max_s,uptr pc,uptr bp)35 void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
36   stack->max_size = max_s;
37   void *tmp[kStackTraceMax];
38 
39   // FIXME: CaptureStackBackTrace might be too slow for us.
40   // FIXME: Compare with StackWalk64.
41   // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
42   uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
43   uptr offset = 0;
44   // Skip the RTL frames by searching for the PC in the stacktrace.
45   // FIXME: this doesn't work well for the malloc/free stacks yet.
46   for (uptr i = 0; i < cs_ret; i++) {
47     if (pc != (uptr)tmp[i])
48       continue;
49     offset = i;
50     break;
51   }
52 
53   stack->size = cs_ret - offset;
54   for (uptr i = 0; i < stack->size; i++)
55     stack->trace[i] = (uptr)tmp[i + offset];
56 }
57 
WinSymbolize(const void * addr,char * out_buffer,int buffer_size)58 bool WinSymbolize(const void *addr, char *out_buffer, int buffer_size) {
59   ScopedLock lock(&dbghelp_lock);
60   if (!dbghelp_initialized) {
61     SymSetOptions(SYMOPT_DEFERRED_LOADS |
62                   SYMOPT_UNDNAME |
63                   SYMOPT_LOAD_LINES);
64     CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE));
65     // FIXME: We don't call SymCleanup() on exit yet - should we?
66     dbghelp_initialized = true;
67   }
68 
69   // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
70   char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
71   PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
72   symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
73   symbol->MaxNameLen = MAX_SYM_NAME;
74   DWORD64 offset = 0;
75   BOOL got_objname = SymFromAddr(GetCurrentProcess(),
76                                  (DWORD64)addr, &offset, symbol);
77   if (!got_objname)
78     return false;
79 
80   DWORD  unused;
81   IMAGEHLP_LINE64 info;
82   info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
83   BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(),
84                                            (DWORD64)addr, &unused, &info);
85   int written = 0;
86   out_buffer[0] = '\0';
87   // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too.
88   if (got_fileline) {
89     written += internal_snprintf(out_buffer + written, buffer_size - written,
90                         " %s %s:%d", symbol->Name,
91                         info.FileName, info.LineNumber);
92   } else {
93     written += internal_snprintf(out_buffer + written, buffer_size - written,
94                         " %s+0x%p", symbol->Name, offset);
95   }
96   return true;
97 }
98 
99 // ---------------------- AsanLock ---------------- {{{1
100 enum LockState {
101   LOCK_UNINITIALIZED = 0,
102   LOCK_READY = -1,
103 };
104 
AsanLock(LinkerInitialized li)105 AsanLock::AsanLock(LinkerInitialized li) {
106   // FIXME: see comments in AsanLock::Lock() for the details.
107   CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED);
108 
109   CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
110   InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
111   owner_ = LOCK_READY;
112 }
113 
Lock()114 void AsanLock::Lock() {
115   if (owner_ == LOCK_UNINITIALIZED) {
116     // FIXME: hm, global AsanLock objects are not initialized?!?
117     // This might be a side effect of the clang+cl+link Frankenbuild...
118     new(this) AsanLock((LinkerInitialized)(LINKER_INITIALIZED + 1));
119 
120     // FIXME: If it turns out the linker doesn't invoke our
121     // constructors, we should probably manually Lock/Unlock all the global
122     // locks while we're starting in one thread to avoid double-init races.
123   }
124   EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
125   CHECK(owner_ == LOCK_READY);
126   owner_ = GetThreadSelf();
127 }
128 
Unlock()129 void AsanLock::Unlock() {
130   CHECK(owner_ == GetThreadSelf());
131   owner_ = LOCK_READY;
132   LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
133 }
134 
135 // ---------------------- TSD ---------------- {{{1
136 static bool tsd_key_inited = false;
137 
138 static __declspec(thread) void *fake_tsd = 0;
139 
AsanTSDInit(void (* destructor)(void * tsd))140 void AsanTSDInit(void (*destructor)(void *tsd)) {
141   // FIXME: we're ignoring the destructor for now.
142   tsd_key_inited = true;
143 }
144 
AsanTSDGet()145 void *AsanTSDGet() {
146   CHECK(tsd_key_inited);
147   return fake_tsd;
148 }
149 
AsanTSDSet(void * tsd)150 void AsanTSDSet(void *tsd) {
151   CHECK(tsd_key_inited);
152   fake_tsd = tsd;
153 }
154 
155 // ---------------------- Various stuff ---------------- {{{1
MaybeReexec()156 void MaybeReexec() {
157   // No need to re-exec on Windows.
158 }
159 
AsanDoesNotSupportStaticLinkage()160 void *AsanDoesNotSupportStaticLinkage() {
161 #if defined(_DEBUG)
162 #error Please build the runtime with a non-debug CRT: /MD or /MT
163 #endif
164   return 0;
165 }
166 
SetAlternateSignalStack()167 void SetAlternateSignalStack() {
168   // FIXME: Decide what to do on Windows.
169 }
170 
UnsetAlternateSignalStack()171 void UnsetAlternateSignalStack() {
172   // FIXME: Decide what to do on Windows.
173 }
174 
InstallSignalHandlers()175 void InstallSignalHandlers() {
176   // FIXME: Decide what to do on Windows.
177 }
178 
AsanPlatformThreadInit()179 void AsanPlatformThreadInit() {
180   // Nothing here for now.
181 }
182 
183 }  // namespace __asan
184 
185 #endif  // _WIN32
186