Coverage Report

Created: 2026-05-16 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/backtrace-0.3.76/src/backtrace/mod.rs
Line
Count
Source
1
use core::ffi::c_void;
2
use core::fmt;
3
4
/// Inspects the current call-stack, passing all active frames into the closure
5
/// provided to calculate a stack trace.
6
///
7
/// This function is the workhorse of this library in calculating the stack
8
/// traces for a program. The given closure `cb` is yielded instances of a
9
/// `Frame` which represent information about that call frame on the stack. The
10
/// closure is yielded frames in a top-down fashion (most recently called
11
/// functions first).
12
///
13
/// The closure's return value is an indication of whether the backtrace should
14
/// continue. A return value of `false` will terminate the backtrace and return
15
/// immediately.
16
///
17
/// Once a `Frame` is acquired you will likely want to call `backtrace::resolve`
18
/// to convert the `ip` (instruction pointer) or symbol address to a `Symbol`
19
/// through which the name and/or filename/line number can be learned.
20
///
21
/// Note that this is a relatively low-level function and if you'd like to, for
22
/// example, capture a backtrace to be inspected later, then the `Backtrace`
23
/// type may be more appropriate.
24
///
25
/// # Required features
26
///
27
/// This function requires the `std` feature of the `backtrace` crate to be
28
/// enabled, and the `std` feature is enabled by default.
29
///
30
/// # Panics
31
///
32
/// This function strives to never panic, but if the `cb` provided panics then
33
/// some platforms will force a double panic to abort the process. Some
34
/// platforms use a C library which internally uses callbacks which cannot be
35
/// unwound through, so panicking from `cb` may trigger a process abort.
36
///
37
/// # Example
38
///
39
/// ```
40
/// extern crate backtrace;
41
///
42
/// fn main() {
43
///     backtrace::trace(|frame| {
44
///         // ...
45
///
46
///         true // continue the backtrace
47
///     });
48
/// }
49
/// ```
50
#[cfg(feature = "std")]
51
0
pub fn trace<F: FnMut(&Frame) -> bool>(cb: F) {
52
0
    let _guard = crate::lock::lock();
53
0
    unsafe { trace_unsynchronized(cb) }
54
0
}
55
56
/// Same as `trace`, only unsafe as it's unsynchronized.
57
///
58
/// This function does not have synchronization guarantees but is available
59
/// when the `std` feature of this crate isn't compiled in. See the `trace`
60
/// function for more documentation and examples.
61
///
62
/// # Panics
63
///
64
/// See information on `trace` for caveats on `cb` panicking.
65
0
pub unsafe fn trace_unsynchronized<F: FnMut(&Frame) -> bool>(mut cb: F) {
66
0
    unsafe { trace_imp(&mut cb) }
67
0
}
68
69
/// A trait representing one frame of a backtrace, yielded to the `trace`
70
/// function of this crate.
71
///
72
/// The tracing function's closure will be yielded frames, and the frame is
73
/// virtually dispatched as the underlying implementation is not always known
74
/// until runtime.
75
#[derive(Clone)]
76
pub struct Frame {
77
    pub(crate) inner: FrameImp,
78
}
79
80
impl Frame {
81
    /// Returns the current instruction pointer of this frame.
82
    ///
83
    /// This is normally the next instruction to execute in the frame, but not
84
    /// all implementations list this with 100% accuracy (but it's generally
85
    /// pretty close).
86
    ///
87
    /// It is recommended to pass this value to `backtrace::resolve` to turn it
88
    /// into a symbol name.
89
0
    pub fn ip(&self) -> *mut c_void {
90
0
        self.inner.ip()
91
0
    }
92
93
    /// Returns the current stack pointer of this frame.
94
    ///
95
    /// In the case that a backend cannot recover the stack pointer for this
96
    /// frame, a null pointer is returned.
97
0
    pub fn sp(&self) -> *mut c_void {
98
0
        self.inner.sp()
99
0
    }
100
101
    /// Returns the starting symbol address of the frame of this function.
102
    ///
103
    /// This will attempt to rewind the instruction pointer returned by `ip` to
104
    /// the start of the function, returning that value. In some cases, however,
105
    /// backends will just return `ip` from this function.
106
    ///
107
    /// The returned value can sometimes be used if `backtrace::resolve` failed
108
    /// on the `ip` given above.
109
0
    pub fn symbol_address(&self) -> *mut c_void {
110
0
        self.inner.symbol_address()
111
0
    }
112
113
    /// Returns the base address of the module to which the frame belongs.
114
0
    pub fn module_base_address(&self) -> Option<*mut c_void> {
115
0
        self.inner.module_base_address()
116
0
    }
117
}
118
119
impl fmt::Debug for Frame {
120
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121
0
        f.debug_struct("Frame")
122
0
            .field("ip", &self.ip())
123
0
            .field("symbol_address", &self.symbol_address())
124
0
            .finish()
125
0
    }
126
}
127
128
#[cfg(all(target_env = "sgx", target_vendor = "fortanix"))]
129
mod sgx_image_base {
130
131
    #[cfg(not(feature = "std"))]
132
    pub(crate) mod imp {
133
        use core::ffi::c_void;
134
        use core::sync::atomic::{AtomicUsize, Ordering::SeqCst};
135
136
        static IMAGE_BASE: AtomicUsize = AtomicUsize::new(0);
137
138
        /// Set the image base address. This is only available for Fortanix SGX
139
        /// target when the `std` feature is not enabled. This can be used in the
140
        /// standard library to set the correct base address.
141
        #[doc(hidden)]
142
        pub fn set_image_base(base_addr: *mut c_void) {
143
            IMAGE_BASE.store(base_addr as _, SeqCst);
144
        }
145
146
        pub(crate) fn get_image_base() -> *mut c_void {
147
            IMAGE_BASE.load(SeqCst) as _
148
        }
149
    }
150
151
    #[cfg(feature = "std")]
152
    mod imp {
153
        use core::ffi::c_void;
154
155
        pub(crate) fn get_image_base() -> *mut c_void {
156
            std::os::fortanix_sgx::mem::image_base() as _
157
        }
158
    }
159
160
    pub(crate) use imp::get_image_base;
161
}
162
163
#[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))]
164
pub use sgx_image_base::imp::set_image_base;
165
166
cfg_if::cfg_if! {
167
    // This needs to come first, to ensure that
168
    // Miri takes priority over the host platform
169
    if #[cfg(miri)] {
170
        pub(crate) mod miri;
171
        use self::miri::trace as trace_imp;
172
        pub(crate) use self::miri::Frame as FrameImp;
173
    } else if #[cfg(
174
        any(
175
            all(
176
                unix,
177
                not(target_os = "emscripten"),
178
                not(all(target_os = "ios", target_arch = "arm")),
179
            ),
180
            all(
181
                target_env = "sgx",
182
                target_vendor = "fortanix",
183
            ),
184
        )
185
    )] {
186
        mod libunwind;
187
        use self::libunwind::trace as trace_imp;
188
        pub(crate) use self::libunwind::Frame as FrameImp;
189
    } else if #[cfg(all(windows, not(target_vendor = "uwp")))] {
190
        cfg_if::cfg_if! {
191
            if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "arm64ec"))] {
192
                mod win64;
193
                use self::win64::trace as trace_imp;
194
                pub(crate) use self::win64::Frame as FrameImp;
195
            } else if #[cfg(any(target_arch = "x86", target_arch = "arm"))] {
196
                mod win32;
197
                use self::win32::trace as trace_imp;
198
                pub(crate) use self::win32::Frame as FrameImp;
199
            }
200
        }
201
    } else {
202
        mod noop;
203
        use self::noop::trace as trace_imp;
204
        pub(crate) use self::noop::Frame as FrameImp;
205
    }
206
}