Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |