1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
use core::fmt;
/// Inspects the current call-stack, passing all active frames into the closure
/// provided to calculate a stack trace.
///
/// This function is the workhorse of this library in calculating the stack
/// traces for a program. The given closure `cb` is yielded instances of a
/// `Frame` which represent information about that call frame on the stack. The
/// closure is yielded frames in a top-down fashion (most recently called
/// functions first).
///
/// The closure's return value is an indication of whether the backtrace should
/// continue. A return value of `false` will terminate the backtrace and return
/// immediately.
///
/// Once a `Frame` is acquired you will likely want to call `backtrace::resolve`
/// to convert the `ip` (instruction pointer) or symbol address to a `Symbol`
/// through which the name and/or filename/line number can be learned.
///
/// Note that this is a relatively low-level function and if you'd like to, for
/// example, capture a backtrace to be inspected later, then the `Backtrace`
/// type may be more appropriate.
///
/// # Example
///
/// ```
/// extern crate backtracer;
///
/// fn main() {
/// backtrace::trace(|frame| {
/// // ...
///
/// true // continue the backtrace
/// });
/// }
/// ```
#[inline(never)] // if this is never inlined then the first frame can be known
// to be skipped
pub fn trace<F: FnMut(&Frame) -> bool>(mut cb: F) {
trace_imp(&mut cb)
}
/// Same as trace but starts from an user provided point in time.
#[inline(never)] // if this is never inlined then the first frame can be known
// to be skipped
pub fn trace_from<F: FnMut(&Frame) -> bool>(t: EntryPoint, mut cb: F) {
trace_from_imp(t, &mut cb)
}
/// A trait representing one frame of a backtrace, yielded to the `trace`
/// function of this crate.
///
/// The tracing function's closure will be yielded frames, and the frame is
/// virtually dispatched as the underlying implementation is not always known
/// until runtime.
pub struct Frame {
inner: FrameImp,
}
impl Frame {
/// Returns the current instruction pointer of this frame.
///
/// This is normally the next instruction to execute in the frame, but not
/// all implementations list this with 100% accuracy (but it's generally
/// pretty close).
///
/// It is recommended to pass this value to `backtrace::resolve` to turn it
/// into a symbol name.
pub fn ip(&self) -> *mut u8 {
self.inner.ip()
}
/// Returns the starting symbol address of the frame of this function.
///
/// This will attempt to rewind the instruction pointer returned by `ip` to
/// the start of the function, returning that value. In some cases, however,
/// backends will just return `ip` from this function.
///
/// The returned value can sometimes be used if `backtrace::resolve` failed
/// on the `ip` given above.
pub fn symbol_address(&self) -> *mut u8 {
self.inner.symbol_address()
}
}
impl fmt::Debug for Frame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Frame")
.field("ip", &self.ip())
.field("symbol_address", &self.symbol_address())
.field("inner", &self.inner)
.finish()
}
}
//mod libunwind;
//use self::libunwind::trace as trace_imp;
//use self::libunwind::Frame as FrameImp;
mod freestanding;
use self::freestanding::trace as trace_imp;
use self::freestanding::trace_from as trace_from_imp;
use self::freestanding::Frame as FrameImp;
pub use self::freestanding::Frame as EntryPoint;