mirror of
https://git.suyu.dev/suyu/breakpad
synced 2024-11-21 14:29:09 -07:00
Better identification of context frames.
Since the introduction of inlined frames, it is not sufficient to check the stack trace length (== 1) in order to identify context frames. Updating all location that were depending on this assumption to check for frame trust level instead. Change-Id: I98f966889367c2270c268b8e78b67418c89c50f1 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3499020 Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
42d2475617
commit
c685fe1153
8 changed files with 42 additions and 33 deletions
|
@ -223,7 +223,7 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery(
|
|||
|
||||
StackFrameAMD64* StackwalkerAMD64::GetCallerBySimulatingReturn(
|
||||
const vector<StackFrame*>& frames) {
|
||||
assert(frames.size() == 1);
|
||||
assert(frames.back()->trust == StackFrame::FRAME_TRUST_CONTEXT);
|
||||
StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
|
||||
uint64_t last_rsp = last_frame->context.rsp;
|
||||
uint64_t caller_rip_address, caller_rip;
|
||||
|
@ -257,7 +257,8 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByStackScan(
|
|||
uint64_t caller_rip_address, caller_rip;
|
||||
|
||||
if (!ScanForReturnAddress(last_rsp, &caller_rip_address, &caller_rip,
|
||||
frames.size() == 1 /* is_context_frame */)) {
|
||||
/*is_context_frame=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
// No plausible return address was found.
|
||||
return NULL;
|
||||
}
|
||||
|
@ -322,7 +323,8 @@ StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack,
|
|||
// According to https://reviews.llvm.org/D24748, LLVM doesn't generate unwind
|
||||
// info for such functions. According to MSDN, leaf functions can be unwound
|
||||
// simply by simulating a return.
|
||||
if (!new_frame.get() && stack->frames()->size() == 1 &&
|
||||
if (!new_frame.get() &&
|
||||
last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT &&
|
||||
system_info_->os_short == "windows") {
|
||||
new_frame.reset(GetCallerBySimulatingReturn(frames));
|
||||
}
|
||||
|
@ -356,7 +358,9 @@ StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack,
|
|||
|
||||
// Should we terminate the stack walk? (end-of-stack or broken invariant)
|
||||
if (TerminateWalk(new_frame->context.rip, new_frame->context.rsp,
|
||||
last_frame->context.rsp, frames.size() == 1)) {
|
||||
last_frame->context.rsp,
|
||||
/*first_unwind=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -168,7 +168,8 @@ StackFrameARM* StackwalkerARM::GetCallerByStackScan(
|
|||
uint32_t caller_sp, caller_pc;
|
||||
|
||||
if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc,
|
||||
frames.size() == 1 /* is_context_frame */)) {
|
||||
/*is_context_frame=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
// No plausible return address was found.
|
||||
return NULL;
|
||||
}
|
||||
|
@ -276,7 +277,8 @@ StackFrame* StackwalkerARM::GetCallerFrame(const CallStack* stack,
|
|||
if (TerminateWalk(frame->context.iregs[MD_CONTEXT_ARM_REG_PC],
|
||||
frame->context.iregs[MD_CONTEXT_ARM_REG_SP],
|
||||
last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP],
|
||||
frames.size() == 1)) {
|
||||
/*first_unwind=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -181,7 +181,8 @@ StackFrameARM64* StackwalkerARM64::GetCallerByStackScan(
|
|||
uint64_t caller_sp, caller_pc;
|
||||
|
||||
if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc,
|
||||
frames.size() == 1 /* is_context_frame */)) {
|
||||
/*is_context_frame=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
// No plausible return address was found.
|
||||
return NULL;
|
||||
}
|
||||
|
@ -320,7 +321,8 @@ StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack,
|
|||
if (TerminateWalk(frame->context.iregs[MD_CONTEXT_ARM64_REG_PC],
|
||||
frame->context.iregs[MD_CONTEXT_ARM64_REG_SP],
|
||||
last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP],
|
||||
frames.size() == 1)) {
|
||||
/*first_unwind=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -276,7 +276,8 @@ StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack,
|
|||
if (TerminateWalk(new_frame->context.epc,
|
||||
new_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP],
|
||||
last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP],
|
||||
frames.size() == 1)) {
|
||||
/*first_unwind=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -132,10 +132,9 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack,
|
|||
frame->trust = StackFrame::FRAME_TRUST_FP;
|
||||
|
||||
// Should we terminate the stack walk? (end-of-stack or broken invariant)
|
||||
if (TerminateWalk(instruction,
|
||||
stack_pointer,
|
||||
last_frame->context.gpr[1],
|
||||
stack->frames()->size() == 1)) {
|
||||
if (TerminateWalk(instruction, stack_pointer, last_frame->context.gpr[1],
|
||||
/*first_unwind=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -123,10 +123,9 @@ StackFrame* StackwalkerPPC64::GetCallerFrame(const CallStack* stack,
|
|||
frame->trust = StackFrame::FRAME_TRUST_FP;
|
||||
|
||||
// Should we terminate the stack walk? (end-of-stack or broken invariant)
|
||||
if (TerminateWalk(instruction,
|
||||
stack_pointer,
|
||||
last_frame->context.gpr[1],
|
||||
stack->frames()->size() == 1)) {
|
||||
if (TerminateWalk(instruction, stack_pointer, last_frame->context.gpr[1],
|
||||
/*is_context_frame=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -112,10 +112,9 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack* stack,
|
|||
}
|
||||
|
||||
// Should we terminate the stack walk? (end-of-stack or broken invariant)
|
||||
if (TerminateWalk(instruction,
|
||||
stack_pointer,
|
||||
last_frame->context.g_r[14],
|
||||
stack->frames()->size() == 1)) {
|
||||
if (TerminateWalk(instruction, stack_pointer, last_frame->context.g_r[14],
|
||||
/*is_context_frame=*/last_frame->trust ==
|
||||
StackFrame::FRAME_TRUST_CONTEXT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -394,9 +394,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;
|
||||
|
@ -438,9 +439,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.
|
||||
|
@ -596,9 +598,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;
|
||||
|
@ -678,10 +681,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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue