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

source

pub fn from_context(context: MinidumpContext, trust: FrameTrust) -> StackFrame

Create a StackFrame from a MinidumpContext.

Trait Implementations§

source§

impl Clone for StackFrame

source§

fn clone(&self) -> StackFrame

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StackFrame

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl FrameSymbolizer for StackFrame

source§

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.

source§

fn get_instruction(&self) -> u64

Get the program counter value for this frame.
source§

fn set_function(&mut self, name: &str, base: u64, parameter_size: u32)

Set the name, base address, and parameter size of the function in which this frame is executing.
source§

fn set_source_file(&mut self, file: &str, line: u32, base: u64)

Set the source file and (1-based) line number this frame represents.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,