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

Commit

Permalink
Ignore inline frames when getting current frame (#838)
Browse files Browse the repository at this point in the history
  • Loading branch information
lzybkr authored Apr 28, 2021
1 parent d6953fd commit f255301
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 31 deletions.
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 */
|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

0 comments on commit f255301

Please sign in to comment.