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)