diff options
-rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc | 72 | ||||
-rw-r--r-- | compiler-rt/test/asan/TestCases/Windows/symbols_path.cc | 22 |
2 files changed, 75 insertions, 19 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc index 6bb7d380560..ed96a3a895a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc @@ -30,25 +30,7 @@ class WinSymbolizer : public Symbolizer { SymbolizedStack *frame = SymbolizedStack::New(addr); BlockingMutexLock l(&dbghelp_mu_); - if (!initialized_) { - if (!TrySymInitialize()) { - // OK, maybe the client app has called SymInitialize already. - // That's a bit unfortunate for us as all the DbgHelp functions are - // single-threaded and we can't coordinate with the app. - // FIXME: Can we stop the other threads at this point? - // Anyways, we have to reconfigure stuff to make sure that SymInitialize - // has all the appropriate options set. - // Cross our fingers and reinitialize DbgHelp. - Report("*** WARNING: Failed to initialize DbgHelp! ***\n"); - Report("*** Most likely this means that the app is already ***\n"); - Report("*** using DbgHelp, possibly with incompatible flags. ***\n"); - Report("*** Due to technical reasons, symbolization might crash ***\n"); - Report("*** or produce wrong results. ***\n"); - SymCleanup(GetCurrentProcess()); - TrySymInitialize(); - } - initialized_ = true; - } + InitializeIfNeeded(); // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; @@ -100,6 +82,58 @@ class WinSymbolizer : public Symbolizer { // FIXME: Implement GetModuleNameAndOffsetForPC(). private: + void InitializeIfNeeded() { + if (initialized_) + return; + if (!TrySymInitialize()) { + // OK, maybe the client app has called SymInitialize already. + // That's a bit unfortunate for us as all the DbgHelp functions are + // single-threaded and we can't coordinate with the app. + // FIXME: Can we stop the other threads at this point? + // Anyways, we have to reconfigure stuff to make sure that SymInitialize + // has all the appropriate options set. + // Cross our fingers and reinitialize DbgHelp. + Report("*** WARNING: Failed to initialize DbgHelp! ***\n"); + Report("*** Most likely this means that the app is already ***\n"); + Report("*** using DbgHelp, possibly with incompatible flags. ***\n"); + Report("*** Due to technical reasons, symbolization might crash ***\n"); + Report("*** or produce wrong results. ***\n"); + SymCleanup(GetCurrentProcess()); + TrySymInitialize(); + } + initialized_ = true; + + // When an executable is run from a location different from the one where it + // was originally built, we may not see the nearby PDB files. + // To work around this, let's append the directory of the main module + // to the symbol search path. All the failures below are not fatal. + const size_t kSymPathSize = 2048; + static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH]; + if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) { + Report("*** WARNING: Failed to SymGetSearchPathW ***\n"); + return; + } + size_t sz = wcslen(path_buffer); + if (sz) { + CHECK_EQ(0, wcscat_s(path_buffer, L";")); + sz++; + } + DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH); + if (res == 0 || res == MAX_PATH) { + Report("*** WARNING: Failed to getting the EXE directory ***\n"); + return; + } + // Write the zero character in place of the last backslash to get the + // directory of the main module at the end of path_buffer. + wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\'); + CHECK_NE(last_bslash, 0); + *last_bslash = L'\0'; + if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) { + Report("*** WARNING: Failed to SymSetSearchPathW\n"); + return; + } + } + bool TrySymInitialize() { SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES); return SymInitialize(GetCurrentProcess(), 0, TRUE); diff --git a/compiler-rt/test/asan/TestCases/Windows/symbols_path.cc b/compiler-rt/test/asan/TestCases/Windows/symbols_path.cc new file mode 100644 index 00000000000..3c69f8861d7 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/symbols_path.cc @@ -0,0 +1,22 @@ +// Make sure symbolization works even if the path to the .exe file changes. +// RUN: mkdir %t || true +// RUN: %clang_cl_asan -O0 %s -Fe%t/symbols_path.exe +// RUN: not %run %t/symbols_path.exe 2>&1 | FileCheck %s +// RUN: mkdir %t2 || true +// RUN: mv %t/* %t2 +// RUN: not %run %t2/symbols_path.exe 2>&1 | FileCheck %s + +#include <malloc.h> + +int main() { + char *buffer = (char*)malloc(42); + buffer[-1] = 42; +// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] +// CHECK: WRITE of size 1 at [[ADDR]] thread T0 +// CHECK-NEXT: {{#0 .* main .*symbols_path.cc}}:[[@LINE-3]] +// CHECK: [[ADDR]] is located 1 bytes to the left of 42-byte region +// CHECK: allocated by thread T0 here: +// CHECK-NEXT: {{#0 .* malloc }} +// CHECK-NEXT: {{#1 .* main .*symbols_path.cc}}:[[@LINE-8]] + free(buffer); +} |