blob: 31f374687e964e46bc0d8ddde4a35a4cabe6a827 [file] [log] [blame]
Alexey Samsonov6e893b62012-08-14 13:00:32 +00001//===-- sanitizer_symbolizer_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 shared between AddressSanitizer and ThreadSanitizer
11// run-time libraries.
12// Windows-specific implementation of symbolizer parts.
13//===----------------------------------------------------------------------===//
Evgeniy Stepanov24e13722013-03-19 14:33:38 +000014
15#include "sanitizer_platform.h"
Evgeniy Stepanov30e110e2013-03-19 14:54:17 +000016#if SANITIZER_WINDOWS
Stephen Hines2d1fdb22014-05-28 23:58:16 -070017#include <windows.h>
18#include <dbghelp.h>
19#pragma comment(lib, "dbghelp.lib")
20
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070021#include "sanitizer_symbolizer_win.h"
22#include "sanitizer_symbolizer_internal.h"
Alexey Samsonov6e893b62012-08-14 13:00:32 +000023
24namespace __sanitizer {
25
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070026namespace {
Stephen Hines2d1fdb22014-05-28 23:58:16 -070027
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070028bool is_dbghelp_initialized = false;
Stephen Hines2d1fdb22014-05-28 23:58:16 -070029
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070030bool TrySymInitialize() {
31 SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
32 return SymInitialize(GetCurrentProcess(), 0, TRUE);
33 // FIXME: We don't call SymCleanup() on exit yet - should we?
34}
Stephen Hines2d1fdb22014-05-28 23:58:16 -070035
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070036// Initializes DbgHelp library, if it's not yet initialized. Calls to this
37// function should be synchronized with respect to other calls to DbgHelp API
38// (e.g. from WinSymbolizerTool).
39void InitializeDbgHelpIfNeeded() {
40 if (is_dbghelp_initialized)
41 return;
42 if (!TrySymInitialize()) {
43 // OK, maybe the client app has called SymInitialize already.
44 // That's a bit unfortunate for us as all the DbgHelp functions are
45 // single-threaded and we can't coordinate with the app.
46 // FIXME: Can we stop the other threads at this point?
47 // Anyways, we have to reconfigure stuff to make sure that SymInitialize
48 // has all the appropriate options set.
49 // Cross our fingers and reinitialize DbgHelp.
50 Report("*** WARNING: Failed to initialize DbgHelp! ***\n");
51 Report("*** Most likely this means that the app is already ***\n");
52 Report("*** using DbgHelp, possibly with incompatible flags. ***\n");
53 Report("*** Due to technical reasons, symbolization might crash ***\n");
54 Report("*** or produce wrong results. ***\n");
55 SymCleanup(GetCurrentProcess());
56 TrySymInitialize();
Stephen Hines2d1fdb22014-05-28 23:58:16 -070057 }
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070058 is_dbghelp_initialized = true;
Stephen Hines2d1fdb22014-05-28 23:58:16 -070059
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070060 // When an executable is run from a location different from the one where it
61 // was originally built, we may not see the nearby PDB files.
62 // To work around this, let's append the directory of the main module
63 // to the symbol search path. All the failures below are not fatal.
64 const size_t kSymPathSize = 2048;
65 static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH];
66 if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) {
67 Report("*** WARNING: Failed to SymGetSearchPathW ***\n");
68 return;
69 }
70 size_t sz = wcslen(path_buffer);
71 if (sz) {
72 CHECK_EQ(0, wcscat_s(path_buffer, L";"));
73 sz++;
74 }
75 DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH);
76 if (res == 0 || res == MAX_PATH) {
77 Report("*** WARNING: Failed to getting the EXE directory ***\n");
78 return;
79 }
80 // Write the zero character in place of the last backslash to get the
81 // directory of the main module at the end of path_buffer.
82 wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\');
83 CHECK_NE(last_bslash, 0);
84 *last_bslash = L'\0';
85 if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) {
86 Report("*** WARNING: Failed to SymSetSearchPathW\n");
87 return;
88 }
89}
90
91} // namespace
92
93bool WinSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *frame) {
94 InitializeDbgHelpIfNeeded();
95
96 // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
97 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
98 PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
99 symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
100 symbol->MaxNameLen = MAX_SYM_NAME;
101 DWORD64 offset = 0;
102 BOOL got_objname = SymFromAddr(GetCurrentProcess(),
103 (DWORD64)addr, &offset, symbol);
104 if (!got_objname)
105 return false;
106
107 DWORD unused;
108 IMAGEHLP_LINE64 line_info;
109 line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
110 BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
111 &unused, &line_info);
112 frame->info.function = internal_strdup(symbol->Name);
113 frame->info.function_offset = (uptr)offset;
114 if (got_fileline) {
115 frame->info.file = internal_strdup(line_info.FileName);
116 frame->info.line = line_info.LineNumber;
117 }
118 return true;
119}
120
121const char *WinSymbolizerTool::Demangle(const char *name) {
122 CHECK(is_dbghelp_initialized);
123 static char demangle_buffer[1000];
124 if (name[0] == '\01' &&
125 UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
126 UNDNAME_NAME_ONLY))
127 return demangle_buffer;
128 else
129 return name;
130}
131
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700132const char *Symbolizer::PlatformDemangle(const char *name) {
133 return name;
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -0700134}
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700135
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700136void Symbolizer::PlatformPrepareForSandboxing() {
137 // Do nothing.
138}
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700139
Stephen Hines6d186232014-11-26 17:56:19 -0800140Symbolizer *Symbolizer::PlatformInit() {
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -0700141 IntrusiveList<SymbolizerTool> list;
142 list.clear();
143 list.push_back(new(symbolizer_allocator_) WinSymbolizerTool());
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700144 return new(symbolizer_allocator_) Symbolizer(list);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700145}
Richard Smithab637432012-12-20 05:00:13 +0000146
Alexey Samsonov6e893b62012-08-14 13:00:32 +0000147} // namespace __sanitizer
148
149#endif // _WIN32