1 //===-- asan_win.cc -------------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
10 // Windows-specific details.
11 //===----------------------------------------------------------------------===//
18 #include <new> // FIXME: temporarily needed for placement new in AsanLock.
20 #include "asan_interceptors.h"
21 #include "asan_internal.h"
22 #include "asan_lock.h"
23 #include "asan_thread.h"
24 #include "sanitizer_common/sanitizer_libc.h"
28 // ---------------------- Stacktraces, symbols, etc. ---------------- {{{1
29 static AsanLock
dbghelp_lock(LINKER_INITIALIZED
);
30 static bool dbghelp_initialized
= false;
31 #pragma comment(lib, "dbghelp.lib")
33 void GetStackTrace(StackTrace
*stack
, uptr max_s
, uptr pc
, uptr bp
) {
34 stack
->max_size
= max_s
;
35 void *tmp
[kStackTraceMax
];
37 // FIXME: CaptureStackBackTrace might be too slow for us.
38 // FIXME: Compare with StackWalk64.
39 // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
40 uptr cs_ret
= CaptureStackBackTrace(1, stack
->max_size
, tmp
, 0);
42 // Skip the RTL frames by searching for the PC in the stacktrace.
43 // FIXME: this doesn't work well for the malloc/free stacks yet.
44 for (uptr i
= 0; i
< cs_ret
; i
++) {
45 if (pc
!= (uptr
)tmp
[i
])
51 stack
->size
= cs_ret
- offset
;
52 for (uptr i
= 0; i
< stack
->size
; i
++)
53 stack
->trace
[i
] = (uptr
)tmp
[i
+ offset
];
56 // ---------------------- AsanLock ---------------- {{{1
58 LOCK_UNINITIALIZED
= 0,
62 AsanLock::AsanLock(LinkerInitialized li
) {
63 // FIXME: see comments in AsanLock::Lock() for the details.
64 CHECK(li
== LINKER_INITIALIZED
|| owner_
== LOCK_UNINITIALIZED
);
66 CHECK(sizeof(CRITICAL_SECTION
) <= sizeof(opaque_storage_
));
67 InitializeCriticalSection((LPCRITICAL_SECTION
)opaque_storage_
);
71 void AsanLock::Lock() {
72 if (owner_
== LOCK_UNINITIALIZED
) {
73 // FIXME: hm, global AsanLock objects are not initialized?!?
74 // This might be a side effect of the clang+cl+link Frankenbuild...
75 new(this) AsanLock((LinkerInitialized
)(LINKER_INITIALIZED
+ 1));
77 // FIXME: If it turns out the linker doesn't invoke our
78 // constructors, we should probably manually Lock/Unlock all the global
79 // locks while we're starting in one thread to avoid double-init races.
81 EnterCriticalSection((LPCRITICAL_SECTION
)opaque_storage_
);
82 CHECK(owner_
== LOCK_READY
);
83 owner_
= GetThreadSelf();
86 void AsanLock::Unlock() {
87 CHECK(owner_
== GetThreadSelf());
89 LeaveCriticalSection((LPCRITICAL_SECTION
)opaque_storage_
);
92 // ---------------------- TSD ---------------- {{{1
93 static bool tsd_key_inited
= false;
95 static __declspec(thread
) void *fake_tsd
= 0;
97 void AsanTSDInit(void (*destructor
)(void *tsd
)) {
98 // FIXME: we're ignoring the destructor for now.
99 tsd_key_inited
= true;
103 CHECK(tsd_key_inited
);
107 void AsanTSDSet(void *tsd
) {
108 CHECK(tsd_key_inited
);
112 // ---------------------- Various stuff ---------------- {{{1
114 // No need to re-exec on Windows.
117 void *AsanDoesNotSupportStaticLinkage() {
119 #error Please build the runtime with a non-debug CRT: /MD or /MT
124 void SetAlternateSignalStack() {
125 // FIXME: Decide what to do on Windows.
128 void UnsetAlternateSignalStack() {
129 // FIXME: Decide what to do on Windows.
132 void InstallSignalHandlers() {
133 // FIXME: Decide what to do on Windows.
136 void AsanPlatformThreadInit() {
137 // Nothing here for now.
140 } // namespace __asan
142 // ---------------------- Interface ---------------- {{{1
143 using namespace __asan
; // NOLINT
146 SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
147 bool __asan_symbolize(const void *addr
, char *out_buffer
, int buffer_size
) {
148 ScopedLock
lock(&dbghelp_lock
);
149 if (!dbghelp_initialized
) {
150 SymSetOptions(SYMOPT_DEFERRED_LOADS
|
153 CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE
));
154 // FIXME: We don't call SymCleanup() on exit yet - should we?
155 dbghelp_initialized
= true;
158 // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
159 char buffer
[sizeof(SYMBOL_INFO
) + MAX_SYM_NAME
* sizeof(CHAR
)];
160 PSYMBOL_INFO symbol
= (PSYMBOL_INFO
)buffer
;
161 symbol
->SizeOfStruct
= sizeof(SYMBOL_INFO
);
162 symbol
->MaxNameLen
= MAX_SYM_NAME
;
164 BOOL got_objname
= SymFromAddr(GetCurrentProcess(),
165 (DWORD64
)addr
, &offset
, symbol
);
170 IMAGEHLP_LINE64 info
;
171 info
.SizeOfStruct
= sizeof(IMAGEHLP_LINE64
);
172 BOOL got_fileline
= SymGetLineFromAddr64(GetCurrentProcess(),
173 (DWORD64
)addr
, &unused
, &info
);
175 out_buffer
[0] = '\0';
176 // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too.
178 written
+= internal_snprintf(out_buffer
+ written
, buffer_size
- written
,
179 " %s %s:%d", symbol
->Name
,
180 info
.FileName
, info
.LineNumber
);
182 written
+= internal_snprintf(out_buffer
+ written
, buffer_size
- written
,
183 " %s+0x%p", symbol
->Name
, offset
);