Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Ignore inline frames when getting current frame #838

Merged
merged 1 commit into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/agent/debugger/src/dbghelp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#![allow(clippy::collapsible_if)]
#![allow(clippy::needless_return)]
#![allow(clippy::upper_case_acronyms)]

/// This module defines a wrapper around dbghelp apis so they can be used in a thread safe manner
/// as well as providing a more Rust like api.
use std::{
Expand All @@ -34,8 +35,9 @@ use winapi::{
dbghelp::{
AddrModeFlat, StackWalkEx, SymCleanup, SymFindFileInPathW, SymFromNameW,
SymFunctionTableAccess64, SymGetModuleBase64, SymInitializeW, SymLoadModuleExW,
IMAGEHLP_LINEW64, PIMAGEHLP_LINEW64, PSYMBOL_INFOW, STACKFRAME_EX, SYMBOL_INFOW,
SYMOPT_DEBUG, SYMOPT_DEFERRED_LOADS, SYMOPT_FAIL_CRITICAL_ERRORS, SYMOPT_NO_PROMPTS,
IMAGEHLP_LINEW64, INLINE_FRAME_CONTEXT_IGNORE, INLINE_FRAME_CONTEXT_INIT,
PIMAGEHLP_LINEW64, PSYMBOL_INFOW, STACKFRAME_EX, SYMBOL_INFOW, SYMOPT_DEBUG,
SYMOPT_DEFERRED_LOADS, SYMOPT_FAIL_CRITICAL_ERRORS, SYMOPT_NO_PROMPTS,
SYM_STKWALK_DEFAULT,
},
errhandlingapi::GetLastError,
Expand Down Expand Up @@ -537,6 +539,7 @@ impl DebugHelpGuard {
&self,
process_handle: HANDLE,
thread_handle: HANDLE,
walk_inline_frames: bool,
mut f: F,
) -> Result<()> {
let mut frame_context = get_thread_frame(process_handle, thread_handle)?;
Expand All @@ -548,6 +551,11 @@ impl DebugHelpGuard {
frame.AddrStack.Mode = AddrModeFlat;
frame.AddrFrame.Offset = frame_context.frame_pointer();
frame.AddrFrame.Mode = AddrModeFlat;
frame.InlineFrameContext = if walk_inline_frames {
INLINE_FRAME_CONTEXT_INIT
} else {
INLINE_FRAME_CONTEXT_IGNORE
};

loop {
let success = unsafe {
Expand Down
1 change: 1 addition & 0 deletions src/agent/debugger/src/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ impl Debugger {
dbghlp.stackwalk_ex(
self.target.process_handle(),
self.target.current_thread_handle(),
false, /* ignore inline frames */
|frame| {
return_address = frame.AddrReturn;
stack_pointer = frame.AddrStack;
Expand Down
64 changes: 35 additions & 29 deletions src/agent/debugger/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,39 +228,45 @@ pub fn get_stack(

let mut stack = vec![];

dbghlp.stackwalk_ex(process_handle, thread_handle, |frame| {
let program_counter = frame.AddrPC.Offset;

let debug_stack_frame = if resolve_symbols {
if let Ok(module_info) = dbghlp.sym_get_module_info(process_handle, program_counter) {
get_function_location_in_module(
&dbghlp,
&module_info,
process_handle,
program_counter,
frame.InlineFrameContext,
)
dbghlp.stackwalk_ex(
process_handle,
thread_handle,
true, /* visit inline frames */
lzybkr marked this conversation as resolved.
Show resolved Hide resolved
|frame| {
let program_counter = frame.AddrPC.Offset;

let debug_stack_frame = if resolve_symbols {
if let Ok(module_info) = dbghlp.sym_get_module_info(process_handle, program_counter)
{
get_function_location_in_module(
&dbghlp,
&module_info,
process_handle,
program_counter,
frame.InlineFrameContext,
)
} else {
// We ignore the error from sym_get_module_info because corrupt stacks in the
// target are a common cause of not finding the module - a condition we expect.
get_frame_with_unknown_module(process_handle, program_counter)
}
} else {
// We ignore the error from sym_get_module_info because corrupt stacks in the
// target are a common cause of not finding the module - a condition we expect.
get_frame_with_unknown_module(process_handle, program_counter)
}
} else {
get_frame_with_unknown_module(process_handle, program_counter)
};
};

// Avoid pushing consecutive corrupt frames.
if !debug_stack_frame.is_corrupt_frame()
|| stack
.last()
.map_or(true, |f: &DebugStackFrame| !f.is_corrupt_frame())
{
stack.push(debug_stack_frame);
};
// Avoid pushing consecutive corrupt frames.
if !debug_stack_frame.is_corrupt_frame()
|| stack
.last()
.map_or(true, |f: &DebugStackFrame| !f.is_corrupt_frame())
{
stack.push(debug_stack_frame);
};

// We want all frames, so continue walking.
true
})?;
// We want all frames, so continue walking.
true
},
)?;

Ok(DebugStack::new(stack))
}
Expand Down