Struct minidump_unwind::StackFrame
source · pub struct StackFrame {Show 14 fields
pub instruction: u64,
pub resume_address: u64,
pub module: Option<MinidumpModule>,
pub unloaded_modules: BTreeMap<String, BTreeSet<u64>>,
pub function_name: Option<String>,
pub function_base: Option<u64>,
pub parameter_size: Option<u32>,
pub source_file_name: Option<String>,
pub source_line: Option<u32>,
pub source_line_base: Option<u64>,
pub inlines: Vec<InlineFrame>,
pub trust: FrameTrust,
pub context: MinidumpContext,
pub arguments: Option<FunctionArgs>,
}
Expand description
A single stack frame produced from unwinding a thread’s stack.
Fields§
§instruction: u64
The program counter location as an absolute virtual address.
-
For the innermost called frame in a stack, this will be an exact program counter or instruction pointer value.
-
For all other frames, this address is within the instruction that caused execution to branch to this frame’s callee (although it may not point to the exact beginning of that instruction). This ensures that, when we look up the source code location for this frame, we get the source location of the call, not of the point at which control will resume when the call returns, which may be on the next line. (If the compiler knows the callee never returns, it may even place the call instruction at the very end of the caller’s machine code, such that the “return address” (which will never be used) immediately after the call instruction is in an entirely different function, perhaps even from a different source file.)
On some architectures, the return address as saved on the stack or in a register is fine for looking up the point of the call. On others, it requires adjustment.
resume_address: u64
The instruction address (program counter) that execution of this function would resume at, if the callee returns.
This is exactly the return address of the of the callee. We use this nonstandard terminology because just calling this “return address” would be ambiguous and too easy to mix up.
Note: you should strongly prefer using StackFrame::instruction
, which should
be the address of the instruction before this one which called the callee.
That is the instruction that this function was logically “executing” when the
program’s state was captured, and therefore what people expect from
backtraces.
This is more than a matter of user expections: there are situations
where this value is nonsensical but the StackFrame::instruction
is valid.
Specifically, if the callee is “noreturn” then this function should never resume execution. The compiler has no obligation to emit any instructions after such a CALL, but CALL still implicitly pushes the instruction after itself to the stack. Such a return address may therefore be outside the “bounds” of this function!!!
Yes, compilers can just immediately jump into the callee for
noreturn calls, but it’s genuinely very helpful for them to emit a
CALL because it keeps the stack reasonable for backtraces and
debuggers, which are more interested in StackFrame::instruction
anyway!
(If this is the top frame of the call stack, then resume_address
and instruction
are exactly equal and should reflect the actual
program counter of this thread.)
module: Option<MinidumpModule>
The module in which the instruction resides.
unloaded_modules: BTreeMap<String, BTreeSet<u64>>
Any unloaded modules which overlap with this address.
This is currently only populated if module
is None.
Since unloaded modules may overlap, there may be more than one module. Since a module may be unloaded and reloaded at multiple positions, we keep track of all the offsets that apply. BTrees are used to produce a more stable output.
So this is a BTreeMap<module_name, Set<offsets>>
.
function_name: Option<String>
The function name, may be omitted if debug symbols are not available.
function_base: Option<u64>
The start address of the function, may be omitted if debug symbols are not available.
parameter_size: Option<u32>
The size, in bytes, of the arguments pushed on the stack for this function. WIN STACK unwinding needs this value to work; it’s otherwise uninteresting.
source_file_name: Option<String>
The source file name, may be omitted if debug symbols are not available.
source_line: Option<u32>
The (1-based) source line number, may be omitted if debug symbols are not available.
source_line_base: Option<u64>
The start address of the source line, may be omitted if debug symbols are not available.
inlines: Vec<InlineFrame>
Any inline frames that cover the frame address, ordered “inside to outside”, or “deepest callee to shallowest callee”. This is the same order that StackFrames appear in.
These frames are “fake” in that they don’t actually exist at runtime, and are only known because the compiler added debuginfo saying they exist.
As a result, many properties of these frames either don’t exist or are in some sense “inherited” from the parent real frame. For instance they have the same instruction/module by definiton.
If you were to print frames you would want to do something like:
let mut frame_num = 0;
for frame in &thread.frames {
// Inlines come first
for inline in &frame.inlines {
print_inline(frame_num, frame, inline);
frame_num += 1;
}
print_frame(frame_num, frame);
frame_num += 1;
}
trust: FrameTrust
Amount of trust the stack walker has in the instruction pointer of this frame.
context: MinidumpContext
The CPU context containing register state for this frame.
arguments: Option<FunctionArgs>
Any function args we recovered.
Implementations§
source§impl StackFrame
impl StackFrame
sourcepub fn from_context(context: MinidumpContext, trust: FrameTrust) -> StackFrame
pub fn from_context(context: MinidumpContext, trust: FrameTrust) -> StackFrame
Create a StackFrame
from a MinidumpContext
.
Trait Implementations§
source§impl Clone for StackFrame
impl Clone for StackFrame
source§fn clone(&self) -> StackFrame
fn clone(&self) -> StackFrame
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moresource§impl Debug for StackFrame
impl Debug for StackFrame
source§impl FrameSymbolizer for StackFrame
impl FrameSymbolizer for StackFrame
source§fn add_inline_frame(
&mut self,
name: &str,
file: Option<&str>,
line: Option<u32>
)
fn add_inline_frame( &mut self, name: &str, file: Option<&str>, line: Option<u32> )
This function can be called multiple times, for the inlines that cover the address at various levels of inlining. The call order is from outside to inside.