| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/stack_trace.h" | 5 #include "base/debug/stack_trace.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 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 } | 215 } |
| 216 | 216 |
| 217 #if defined(COMPILER_MSVC) | 217 #if defined(COMPILER_MSVC) |
| 218 #pragma optimize("", on) | 218 #pragma optimize("", on) |
| 219 #endif | 219 #endif |
| 220 | 220 |
| 221 StackTrace::StackTrace(EXCEPTION_POINTERS* exception_pointers) { | 221 StackTrace::StackTrace(EXCEPTION_POINTERS* exception_pointers) { |
| 222 InitTrace(exception_pointers->ContextRecord); | 222 InitTrace(exception_pointers->ContextRecord); |
| 223 } | 223 } |
| 224 | 224 |
| 225 StackTrace::StackTrace(CONTEXT* context) { | 225 StackTrace::StackTrace(const CONTEXT* context) { |
| 226 InitTrace(context); | 226 InitTrace(context); |
| 227 } | 227 } |
| 228 | 228 |
| 229 void StackTrace::InitTrace(CONTEXT* context_record) { | 229 void StackTrace::InitTrace(const CONTEXT* context_record) { |
| 230 // StackWalk64 modifies the register context in place, so we have to copy it |
| 231 // so that downstream exception handlers get the right context. The incoming |
| 232 // context may have had more register state (YMM, etc) than we need to unwind |
| 233 // the stack. Typically StackWalk64 only needs integer and control registers. |
| 234 CONTEXT context_copy; |
| 235 memcpy(&context_copy, context_record, sizeof(context_copy)); |
| 236 context_copy.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; |
| 237 |
| 230 // When walking an exception stack, we need to use StackWalk64(). | 238 // When walking an exception stack, we need to use StackWalk64(). |
| 231 count_ = 0; | 239 count_ = 0; |
| 232 // Initialize stack walking. | 240 // Initialize stack walking. |
| 233 STACKFRAME64 stack_frame; | 241 STACKFRAME64 stack_frame; |
| 234 memset(&stack_frame, 0, sizeof(stack_frame)); | 242 memset(&stack_frame, 0, sizeof(stack_frame)); |
| 235 #if defined(_WIN64) | 243 #if defined(_WIN64) |
| 236 int machine_type = IMAGE_FILE_MACHINE_AMD64; | 244 int machine_type = IMAGE_FILE_MACHINE_AMD64; |
| 237 stack_frame.AddrPC.Offset = context_record->Rip; | 245 stack_frame.AddrPC.Offset = context_record->Rip; |
| 238 stack_frame.AddrFrame.Offset = context_record->Rbp; | 246 stack_frame.AddrFrame.Offset = context_record->Rbp; |
| 239 stack_frame.AddrStack.Offset = context_record->Rsp; | 247 stack_frame.AddrStack.Offset = context_record->Rsp; |
| 240 #else | 248 #else |
| 241 int machine_type = IMAGE_FILE_MACHINE_I386; | 249 int machine_type = IMAGE_FILE_MACHINE_I386; |
| 242 stack_frame.AddrPC.Offset = context_record->Eip; | 250 stack_frame.AddrPC.Offset = context_record->Eip; |
| 243 stack_frame.AddrFrame.Offset = context_record->Ebp; | 251 stack_frame.AddrFrame.Offset = context_record->Ebp; |
| 244 stack_frame.AddrStack.Offset = context_record->Esp; | 252 stack_frame.AddrStack.Offset = context_record->Esp; |
| 245 #endif | 253 #endif |
| 246 stack_frame.AddrPC.Mode = AddrModeFlat; | 254 stack_frame.AddrPC.Mode = AddrModeFlat; |
| 247 stack_frame.AddrFrame.Mode = AddrModeFlat; | 255 stack_frame.AddrFrame.Mode = AddrModeFlat; |
| 248 stack_frame.AddrStack.Mode = AddrModeFlat; | 256 stack_frame.AddrStack.Mode = AddrModeFlat; |
| 249 while (StackWalk64(machine_type, | 257 while (StackWalk64(machine_type, |
| 250 GetCurrentProcess(), | 258 GetCurrentProcess(), |
| 251 GetCurrentThread(), | 259 GetCurrentThread(), |
| 252 &stack_frame, | 260 &stack_frame, |
| 253 context_record, | 261 &context_copy, |
| 254 NULL, | 262 NULL, |
| 255 &SymFunctionTableAccess64, | 263 &SymFunctionTableAccess64, |
| 256 &SymGetModuleBase64, | 264 &SymGetModuleBase64, |
| 257 NULL) && | 265 NULL) && |
| 258 count_ < arraysize(trace_)) { | 266 count_ < arraysize(trace_)) { |
| 259 trace_[count_++] = reinterpret_cast<void*>(stack_frame.AddrPC.Offset); | 267 trace_[count_++] = reinterpret_cast<void*>(stack_frame.AddrPC.Offset); |
| 260 } | 268 } |
| 261 | 269 |
| 262 for (size_t i = count_; i < arraysize(trace_); ++i) | 270 for (size_t i = count_; i < arraysize(trace_); ++i) |
| 263 trace_[i] = NULL; | 271 trace_[i] = NULL; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 276 (*os) << "\t" << trace_[i] << "\n"; | 284 (*os) << "\t" << trace_[i] << "\n"; |
| 277 } | 285 } |
| 278 } else { | 286 } else { |
| 279 (*os) << "Backtrace:\n"; | 287 (*os) << "Backtrace:\n"; |
| 280 context->OutputTraceToStream(trace_, count_, os); | 288 context->OutputTraceToStream(trace_, count_, os); |
| 281 } | 289 } |
| 282 } | 290 } |
| 283 | 291 |
| 284 } // namespace debug | 292 } // namespace debug |
| 285 } // namespace base | 293 } // namespace base |
| OLD | NEW |