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