16e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov//===-- sanitizer_symbolizer_win.cc ---------------------------------------===// 26e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// 36e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// The LLVM Compiler Infrastructure 46e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// 56e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// This file is distributed under the University of Illinois Open Source 66e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// License. See LICENSE.TXT for details. 76e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// 86e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov//===----------------------------------------------------------------------===// 96e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// 106e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer 116e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// run-time libraries. 126e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov// Windows-specific implementation of symbolizer parts. 136e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov//===----------------------------------------------------------------------===// 1424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov 1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_platform.h" 1630e110edf92303237d471f1cb8e3ad07954fb145Evgeniy Stepanov#if SANITIZER_WINDOWS 172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <windows.h> 182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <dbghelp.h> 192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#pragma comment(lib, "dbghelp.lib") 202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 217c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include "sanitizer_symbolizer_win.h" 227c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include "sanitizer_symbolizer_internal.h" 236e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov 246e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonovnamespace __sanitizer { 256e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov 267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarnamespace { 272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 287c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarbool is_dbghelp_initialized = false; 297c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarbool TrySymInitialize() { 317c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES); 327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return SymInitialize(GetCurrentProcess(), 0, TRUE); 337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // FIXME: We don't call SymCleanup() on exit yet - should we? 347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// Initializes DbgHelp library, if it's not yet initialized. Calls to this 377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// function should be synchronized with respect to other calls to DbgHelp API 387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// (e.g. from WinSymbolizerTool). 397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid InitializeDbgHelpIfNeeded() { 407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (is_dbghelp_initialized) 417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return; 427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (!TrySymInitialize()) { 437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // OK, maybe the client app has called SymInitialize already. 447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // That's a bit unfortunate for us as all the DbgHelp functions are 457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // single-threaded and we can't coordinate with the app. 467c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // FIXME: Can we stop the other threads at this point? 477c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // Anyways, we have to reconfigure stuff to make sure that SymInitialize 487c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // has all the appropriate options set. 497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // Cross our fingers and reinitialize DbgHelp. 507c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar Report("*** WARNING: Failed to initialize DbgHelp! ***\n"); 517c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar Report("*** Most likely this means that the app is already ***\n"); 527c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar Report("*** using DbgHelp, possibly with incompatible flags. ***\n"); 537c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar Report("*** Due to technical reasons, symbolization might crash ***\n"); 547c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar Report("*** or produce wrong results. ***\n"); 557c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar SymCleanup(GetCurrentProcess()); 567c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar TrySymInitialize(); 577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar } 587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar is_dbghelp_initialized = true; 597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // When an executable is run from a location different from the one where it 617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // was originally built, we may not see the nearby PDB files. 627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // To work around this, let's append the directory of the main module 637c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // to the symbol search path. All the failures below are not fatal. 647c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar const size_t kSymPathSize = 2048; 657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH]; 667c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) { 677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar Report("*** WARNING: Failed to SymGetSearchPathW ***\n"); 687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return; 697c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar } 707c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar size_t sz = wcslen(path_buffer); 717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (sz) { 727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar CHECK_EQ(0, wcscat_s(path_buffer, L";")); 737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar sz++; 742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 757c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH); 767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (res == 0 || res == MAX_PATH) { 777c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar Report("*** WARNING: Failed to getting the EXE directory ***\n"); 787c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return; 797c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar } 807c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // Write the zero character in place of the last backslash to get the 817c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // directory of the main module at the end of path_buffer. 827c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\'); 837c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar CHECK_NE(last_bslash, 0); 847c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *last_bslash = L'\0'; 857c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) { 867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar Report("*** WARNING: Failed to SymSetSearchPathW\n"); 877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return; 887c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar } 897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} // namespace 927c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 937c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarbool WinSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *frame) { 947c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar InitializeDbgHelpIfNeeded(); 957c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 967c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx 977c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; 987c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; 997c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar symbol->SizeOfStruct = sizeof(SYMBOL_INFO); 1007c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar symbol->MaxNameLen = MAX_SYM_NAME; 1017c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar DWORD64 offset = 0; 1027c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar BOOL got_objname = SymFromAddr(GetCurrentProcess(), 1037c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar (DWORD64)addr, &offset, symbol); 1047c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (!got_objname) 1057c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return false; 1067c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 1077c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar DWORD unused; 1087c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar IMAGEHLP_LINE64 line_info; 1097c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); 1107c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr, 1117c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar &unused, &line_info); 1127c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar frame->info.function = internal_strdup(symbol->Name); 1137c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar frame->info.function_offset = (uptr)offset; 1147c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (got_fileline) { 1157c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar frame->info.file = internal_strdup(line_info.FileName); 1167c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar frame->info.line = line_info.LineNumber; 1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1187c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return true; 1197c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1217c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *WinSymbolizerTool::Demangle(const char *name) { 1227c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar CHECK(is_dbghelp_initialized); 1237c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar static char demangle_buffer[1000]; 1247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (name[0] == '\01' && 1257c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer), 1267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar UNDNAME_NAME_ONLY)) 1277c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return demangle_buffer; 1287c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar else 1297c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return name; 1307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 132909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainarconst char *Symbolizer::PlatformDemangle(const char *name) { 133909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar return name; 1347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 1356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 136909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainarvoid Symbolizer::PlatformPrepareForSandboxing() { 137909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // Do nothing. 138909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar} 1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1406d1862363c88c183b0ed7740fca876342cf0474bStephen HinesSymbolizer *Symbolizer::PlatformInit() { 1417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar IntrusiveList<SymbolizerTool> list; 1427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar list.clear(); 1437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar list.push_back(new(symbolizer_allocator_) WinSymbolizerTool()); 144909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar return new(symbolizer_allocator_) Symbolizer(list); 1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 146ab6374326389ff649ad857842b45488721c949dbRichard Smith 1476e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov} // namespace __sanitizer 1486e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov 1496e893b61094a3bfb1a9f92fb019dd6fb153076b5Alexey Samsonov#endif // _WIN32 150