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 |