Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: base/debug_util_win.cc

Issue 201050: Print stack trace on exception in unit tests on Windows.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/debug_util_posix.cc ('k') | base/test_suite.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug_util.h" 5 #include "base/debug_util.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <dbghelp.h> 8 #include <dbghelp.h>
9 9
10 #include <iostream> 10 #include <iostream>
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 } 98 }
99 99
100 // For the given trace, attempts to resolve the symbols, and output a trace 100 // For the given trace, attempts to resolve the symbols, and output a trace
101 // to the ostream os. The format for each line of the backtrace is: 101 // to the ostream os. The format for each line of the backtrace is:
102 // 102 //
103 // <tab>SymbolName[0xAddress+Offset] (FileName:LineNo) 103 // <tab>SymbolName[0xAddress+Offset] (FileName:LineNo)
104 // 104 //
105 // This function should only be called if Init() has been called. We do not 105 // This function should only be called if Init() has been called. We do not
106 // LOG(FATAL) here because this code is called might be triggered by a 106 // LOG(FATAL) here because this code is called might be triggered by a
107 // LOG(FATAL) itself. 107 // LOG(FATAL) itself.
108 void OutputTraceToStream(const std::vector<void*>& trace, std::ostream* os) { 108 void OutputTraceToStream(const void* const* trace,
109 int count,
110 std::ostream* os) {
109 AutoLock lock(lock_); 111 AutoLock lock(lock_);
110 112
111 for (size_t i = 0; (i < trace.size()) && os->good(); ++i) { 113 for (size_t i = 0; (i < count) && os->good(); ++i) {
awong 2009/09/08 20:44:03 size_t -> int
112 const int kMaxNameLength = 256; 114 const int kMaxNameLength = 256;
113 DWORD_PTR frame = reinterpret_cast<DWORD_PTR>(trace[i]); 115 DWORD_PTR frame = reinterpret_cast<DWORD_PTR>(trace[i]);
114 116
115 // Code adapted from MSDN example: 117 // Code adapted from MSDN example:
116 // http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx 118 // http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
117 ULONG64 buffer[ 119 ULONG64 buffer[
118 (sizeof(SYMBOL_INFO) + 120 (sizeof(SYMBOL_INFO) +
119 kMaxNameLength * sizeof(wchar_t) + 121 kMaxNameLength * sizeof(wchar_t) +
120 sizeof(ULONG64) - 1) / 122 sizeof(ULONG64) - 1) /
121 sizeof(ULONG64)]; 123 sizeof(ULONG64)];
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 bool DebugUtil::BeingDebugged() { 215 bool DebugUtil::BeingDebugged() {
214 return ::IsDebuggerPresent() != 0; 216 return ::IsDebuggerPresent() != 0;
215 } 217 }
216 218
217 // static 219 // static
218 void DebugUtil::BreakDebugger() { 220 void DebugUtil::BreakDebugger() {
219 __debugbreak(); 221 __debugbreak();
220 } 222 }
221 223
222 StackTrace::StackTrace() { 224 StackTrace::StackTrace() {
223 // From http://msdn.microsoft.com/en-us/library/bb204633(VS.85).aspx, 225 // When walking our own stack, use CaptureStackBackTrace().
224 // the sum of FramesToSkip and FramesToCapture must be less than 63, 226 count_ = CaptureStackBackTrace(0, arraysize(trace_), trace_, NULL);
225 // so set it to 62. 227 }
226 const int kMaxCallers = 62;
227 228
228 void* callers[kMaxCallers]; 229 StackTrace::StackTrace(EXCEPTION_POINTERS* exception_pointers) {
229 // TODO(ajwong): Migrate this to StackWalk64. 230 // When walking an exception stack, we need to use StackWalk64().
230 int count = CaptureStackBackTrace(0, kMaxCallers, callers, NULL); 231 count_ = 0;
231 if (count > 0) { 232 // Initialize stack walking.
232 trace_.resize(count); 233 STACKFRAME64 stack_frame;
233 memcpy(&trace_[0], callers, sizeof(callers[0]) * count); 234 memset(&stack_frame, 0, sizeof(stack_frame));
234 } else { 235 #if defined(_WIN64)
235 trace_.resize(0); 236 int machine_type = IMAGE_FILE_MACHINE_AMD64;
237 stack_frame.AddrPC.Offset = exception_pointers->ContextRecord->Rip;
238 stack_frame.AddrFrame.Offset = exception_pointers->ContextRecord->Rbp;
239 stack_frame.AddrStack.Offset = exception_pointers->ContextRecord->Rsp;
240 #else
241 int machine_type = IMAGE_FILE_MACHINE_I386;
242 stack_frame.AddrPC.Offset = exception_pointers->ContextRecord->Eip;
243 stack_frame.AddrFrame.Offset = exception_pointers->ContextRecord->Ebp;
244 stack_frame.AddrStack.Offset = exception_pointers->ContextRecord->Esp;
245 #endif
246 stack_frame.AddrPC.Mode = AddrModeFlat;
247 stack_frame.AddrFrame.Mode = AddrModeFlat;
248 stack_frame.AddrStack.Mode = AddrModeFlat;
249 while (StackWalk64(machine_type,
250 GetCurrentProcess(),
251 GetCurrentThread(),
252 &stack_frame,
253 exception_pointers->ContextRecord,
254 NULL,
255 &SymFunctionTableAccess64,
256 &SymGetModuleBase64,
257 NULL) &&
258 count_ < arraysize(trace_)) {
259 trace_[count_++] = reinterpret_cast<void*>(stack_frame.AddrPC.Offset);
236 } 260 }
237 } 261 }
238 262
239 void StackTrace::PrintBacktrace() { 263 void StackTrace::PrintBacktrace() {
240 OutputToStream(&std::cerr); 264 OutputToStream(&std::cerr);
241 } 265 }
242 266
243 void StackTrace::OutputToStream(std::ostream* os) { 267 void StackTrace::OutputToStream(std::ostream* os) {
244 SymbolContext* context = SymbolContext::Get(); 268 SymbolContext* context = SymbolContext::Get();
245 DWORD error = context->init_error(); 269 DWORD error = context->init_error();
246 if (error != ERROR_SUCCESS) { 270 if (error != ERROR_SUCCESS) {
247 (*os) << "Error initializing symbols (" << error 271 (*os) << "Error initializing symbols (" << error
248 << "). Dumping unresolved backtrace:\n"; 272 << "). Dumping unresolved backtrace:\n";
249 for (size_t i = 0; (i < trace_.size()) && os->good(); ++i) { 273 for (size_t i = 0; (i < count_) && os->good(); ++i) {
250 (*os) << "\t" << trace_[i] << "\n"; 274 (*os) << "\t" << trace_[i] << "\n";
251 } 275 }
252 } else { 276 } else {
253 (*os) << "Backtrace:\n"; 277 (*os) << "Backtrace:\n";
254 context->OutputTraceToStream(trace_, os); 278 context->OutputTraceToStream(trace_, count_, os);
255 } 279 }
256 } 280 }
OLDNEW
« no previous file with comments | « base/debug_util_posix.cc ('k') | base/test_suite.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698