aboutsummaryrefslogtreecommitdiff
path: root/src/processor/stackwalker_x86.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/processor/stackwalker_x86.cc')
-rw-r--r--src/processor/stackwalker_x86.cc62
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;
}