diff options
Diffstat (limited to 'src/processor/stackwalker_x86.cc')
-rw-r--r-- | src/processor/stackwalker_x86.cc | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc index ed2b383d..b598c5bd 100644 --- a/src/processor/stackwalker_x86.cc +++ b/src/processor/stackwalker_x86.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. +// Copyright 2010 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. -// * Neither the name of Google Inc. nor the names of its +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -136,11 +135,14 @@ StackFrame* StackwalkerX86::GetContextFrame() { } StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( - const vector<StackFrame*> &frames, + const vector<StackFrame*>& frames, WindowsFrameInfo* last_frame_info, bool stack_scan_allowed) { StackFrame::FrameTrust trust = StackFrame::FRAME_TRUST_NONE; + // The last frame can never be inline. A sequence of inline frames always + // finishes with a conventional frame. + assert(frames.back()->trust != StackFrame::FRAME_TRUST_INLINE); StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); // Save the stack walking info we found, in case we need it later to @@ -187,9 +189,15 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( uint32_t last_frame_callee_parameter_size = 0; int frames_already_walked = frames.size(); - if (frames_already_walked >= 2) { + for (int last_frame_callee_id = frames_already_walked - 2; + last_frame_callee_id >= 0; last_frame_callee_id--) { + // Searching for a real callee frame. Skipping inline frames since they + // cannot be downcasted to StackFrameX86. + if (frames[last_frame_callee_id]->trust == StackFrame::FRAME_TRUST_INLINE) { + continue; + } const StackFrameX86* last_frame_callee - = static_cast<StackFrameX86*>(frames[frames_already_walked - 2]); + = static_cast<StackFrameX86*>(frames[last_frame_callee_id]); WindowsFrameInfo* last_frame_callee_info = last_frame_callee->windows_frame_info; if (last_frame_callee_info && @@ -385,9 +393,10 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( // frame pointer. uint32_t location_start = last_frame->context.esp; uint32_t location, eip; - if (!stack_scan_allowed - || !ScanForReturnAddress(location_start, &location, &eip, - frames.size() == 1 /* is_context_frame */)) { + if (!stack_scan_allowed || + !ScanForReturnAddress(location_start, &location, &eip, + /*is_context_frame=*/last_frame->trust == + StackFrame::FRAME_TRUST_CONTEXT)) { // if we can't find an instruction pointer even with stack scanning, // give up. return NULL; @@ -429,9 +438,10 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( // looking one 32-bit word above that location. uint32_t location_start = dictionary[".raSearchStart"] + 4; uint32_t location; - if (stack_scan_allowed - && ScanForReturnAddress(location_start, &location, &eip, - frames.size() == 1 /* is_context_frame */)) { + if (stack_scan_allowed && + ScanForReturnAddress(location_start, &location, &eip, + /*is_context_frame=*/last_frame->trust == + StackFrame::FRAME_TRUST_CONTEXT)) { // This is a better return address that what program string // evaluation found. Use it, and set %esp to the location above the // one where the return address was found. @@ -514,8 +524,11 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( } StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo( - const vector<StackFrame*> &frames, + const vector<StackFrame*>& frames, CFIFrameInfo* cfi_frame_info) { + // The last frame can never be inline. A sequence of inline frames always + // finishes with a conventional frame. + assert(frames.back()->trust != StackFrame::FRAME_TRUST_INLINE); StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); last_frame->cfi_frame_info = cfi_frame_info; @@ -539,9 +552,12 @@ StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo( } StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase( - const vector<StackFrame*> &frames, + const vector<StackFrame*>& frames, bool stack_scan_allowed) { StackFrame::FrameTrust trust; + // The last frame can never be inline. A sequence of inline frames always + // finishes with a conventional frame. + assert(frames.back()->trust != StackFrame::FRAME_TRUST_INLINE); StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); uint32_t last_esp = last_frame->context.esp; uint32_t last_ebp = last_frame->context.ebp; @@ -581,9 +597,10 @@ StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase( // return address. This can happen if last_frame is executing code // for a module for which we don't have symbols, and that module // is compiled without a frame pointer. - if (!stack_scan_allowed - || !ScanForReturnAddress(last_esp, &caller_esp, &caller_eip, - frames.size() == 1 /* is_context_frame */)) { + if (!stack_scan_allowed || + !ScanForReturnAddress(last_esp, &caller_esp, &caller_eip, + /*is_context_frame=*/last_frame->trust == + StackFrame::FRAME_TRUST_CONTEXT)) { // if we can't find an instruction pointer even with stack scanning, // give up. return NULL; @@ -632,8 +649,11 @@ StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack, return NULL; } - const vector<StackFrame*> &frames = *stack->frames(); + const vector<StackFrame*>& frames = *stack->frames(); StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); + // The last frame can never be inline. A sequence of inline frames always + // finishes with a conventional frame. + assert(last_frame->trust != StackFrame::FRAME_TRUST_INLINE); scoped_ptr<StackFrameX86> new_frame; // If the resolver has Windows stack walking information, use that. @@ -660,10 +680,10 @@ StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack, return NULL; // Should we terminate the stack walk? (end-of-stack or broken invariant) - if (TerminateWalk(new_frame->context.eip, - new_frame->context.esp, + if (TerminateWalk(new_frame->context.eip, new_frame->context.esp, last_frame->context.esp, - frames.size() == 1)) { + /*first_unwind=*/last_frame->trust == + StackFrame::FRAME_TRUST_CONTEXT)) { return NULL; } |