/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 | | } |