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 |