diff options
Diffstat (limited to 'base/debug/stack_trace_win.cc')
-rw-r--r-- | base/debug/stack_trace_win.cc | 127 |
1 files changed, 62 insertions, 65 deletions
diff --git a/base/debug/stack_trace_win.cc b/base/debug/stack_trace_win.cc index ceccef5..55d5562 100644 --- a/base/debug/stack_trace_win.cc +++ b/base/debug/stack_trace_win.cc @@ -26,9 +26,6 @@ namespace { // exception. Only used in unit tests. LPTOP_LEVEL_EXCEPTION_FILTER g_previous_filter = NULL; -bool g_initialized_symbols = false; -DWORD g_init_error = ERROR_SUCCESS; - // Prints the exception call stack. // This is the unit tests exception filter. long WINAPI StackDumpExceptionFilter(EXCEPTION_POINTERS* info) { @@ -45,55 +42,6 @@ FilePath GetExePath() { return FilePath(system_buffer); } -bool InitializeSymbols() { - if (g_initialized_symbols) - return g_init_error == ERROR_SUCCESS; - g_initialized_symbols = true; - // Defer symbol load until they're needed, use undecorated names, and get line - // numbers. - SymSetOptions(SYMOPT_DEFERRED_LOADS | - SYMOPT_UNDNAME | - SYMOPT_LOAD_LINES); - if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) { - g_init_error = GetLastError(); - // TODO(awong): Handle error: SymInitialize can fail with - // ERROR_INVALID_PARAMETER. - // When it fails, we should not call debugbreak since it kills the current - // process (prevents future tests from running or kills the browser - // process). - DLOG(ERROR) << "SymInitialize failed: " << g_init_error; - return false; - } - - // When transferring the binaries e.g. between bots, path put - // into the executable will get off. To still retrieve symbols correctly, - // add the directory of the executable to symbol search path. - // All following errors are non-fatal. - const size_t kSymbolsArraySize = 1024; - scoped_ptr<wchar_t[]> symbols_path(new wchar_t[kSymbolsArraySize]); - - // Note: The below function takes buffer size as number of characters, - // not number of bytes! - if (!SymGetSearchPathW(GetCurrentProcess(), - symbols_path.get(), - kSymbolsArraySize)) { - DLOG(WARNING) << "SymGetSearchPath failed: " << g_init_error; - g_init_error = GetLastError(); - return false; - } - - std::wstring new_path(std::wstring(symbols_path.get()) + - L";" + GetExePath().DirName().value()); - if (!SymSetSearchPathW(GetCurrentProcess(), new_path.c_str())) { - g_init_error = GetLastError(); - DLOG(WARNING) << "SymSetSearchPath failed." << g_init_error; - return false; - } - - g_init_error = ERROR_SUCCESS; - return true; -} - // SymbolContext is a threadsafe singleton that wraps the DbgHelp Sym* family // of functions. The Sym* family of functions may only be invoked by one // thread at a time. SymbolContext code may access a symbol server over the @@ -118,6 +66,11 @@ class SymbolContext { Singleton<SymbolContext, LeakySingletonTraits<SymbolContext> >::get(); } + // Returns the error code of a failed initialization. + DWORD init_error() const { + return init_error_; + } + // For the given trace, attempts to resolve the symbols, and output a trace // to the ostream os. The format for each line of the backtrace is: // @@ -179,10 +132,51 @@ class SymbolContext { private: friend struct DefaultSingletonTraits<SymbolContext>; - SymbolContext() { - InitializeSymbols(); + SymbolContext() : init_error_(ERROR_SUCCESS) { + // Initializes the symbols for the process. + // Defer symbol load until they're needed, use undecorated names, and + // get line numbers. + SymSetOptions(SYMOPT_DEFERRED_LOADS | + SYMOPT_UNDNAME | + SYMOPT_LOAD_LINES); + if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) { + init_error_ = GetLastError(); + // TODO(awong): Handle error: SymInitialize can fail with + // ERROR_INVALID_PARAMETER. + // When it fails, we should not call debugbreak since it kills the current + // process (prevents future tests from running or kills the browser + // process). + DLOG(ERROR) << "SymInitialize failed: " << init_error_; + return; + } + + init_error_ = ERROR_SUCCESS; + + // When transferring the binaries e.g. between bots, path put + // into the executable will get off. To still retrieve symbols correctly, + // add the directory of the executable to symbol search path. + // All following errors are non-fatal. + const size_t kSymbolsArraySize = 1024; + scoped_ptr<wchar_t[]> symbols_path(new wchar_t[kSymbolsArraySize]); + + // Note: The below function takes buffer size as number of characters, + // not number of bytes! + if (!SymGetSearchPathW(GetCurrentProcess(), + symbols_path.get(), + kSymbolsArraySize)) { + DLOG(WARNING) << "SymGetSearchPath failed: "; + return; + } + + std::wstring new_path(std::wstring(symbols_path.get()) + + L";" + GetExePath().DirName().value()); + if (!SymSetSearchPathW(GetCurrentProcess(), new_path.c_str())) { + DLOG(WARNING) << "SymSetSearchPath failed."; + return; + } } + DWORD init_error_; base::Lock lock_; DISALLOW_COPY_AND_ASSIGN(SymbolContext); }; @@ -194,11 +188,7 @@ bool EnableInProcessStackDumping() { // signal() handling in process_util_posix.cc. g_previous_filter = SetUnhandledExceptionFilter(&StackDumpExceptionFilter); RouteStdioToConsole(); - - // Need to initialize symbols early in the process or else this fails on - // swarming (since symbols are in different directory than in the exes) and - // also release x64. - return InitializeSymbols(); + return true; } // Disable optimizations for the StackTrace::StackTrace function. It is @@ -219,12 +209,18 @@ StackTrace::StackTrace() { #pragma optimize("", on) #endif -StackTrace::StackTrace(EXCEPTION_POINTERS* exception_pointers) { - InitTrace(exception_pointers->ContextRecord); +StackTrace::StackTrace(const EXCEPTION_POINTERS* exception_pointers) { + // StackWalk64() may modify context record passed to it, so we will + // use a copy. + CONTEXT context_record = *exception_pointers->ContextRecord; + InitTrace(&context_record); } -StackTrace::StackTrace(CONTEXT* context) { - InitTrace(context); +StackTrace::StackTrace(const CONTEXT* context) { + // StackWalk64() may modify context record passed to it, so we will + // use a copy. + CONTEXT context_record = *context; + InitTrace(&context_record); } void StackTrace::InitTrace(CONTEXT* context_record) { @@ -270,8 +266,9 @@ void StackTrace::Print() const { void StackTrace::OutputToStream(std::ostream* os) const { SymbolContext* context = SymbolContext::GetInstance(); - if (g_init_error != ERROR_SUCCESS) { - (*os) << "Error initializing symbols (" << g_init_error + DWORD error = context->init_error(); + if (error != ERROR_SUCCESS) { + (*os) << "Error initializing symbols (" << error << "). Dumping unresolved backtrace:\n"; for (size_t i = 0; (i < count_) && os->good(); ++i) { (*os) << "\t" << trace_[i] << "\n"; |