]>
Commit | Line | Data |
---|---|---|
7cac9316 XL |
1 | //! A library for acquiring a backtrace at runtime |
2 | //! | |
3 | //! This library is meant to supplement the `RUST_BACKTRACE=1` support of the | |
4 | //! standard library by allowing an acquisition of a backtrace at runtime | |
5 | //! programmatically. The backtraces generated by this library do not need to be | |
6 | //! parsed, for example, and expose the functionality of multiple backend | |
7 | //! implementations. | |
8 | //! | |
9 | //! # Implementation | |
10 | //! | |
11 | //! This library makes use of a number of strategies for actually acquiring a | |
12 | //! backtrace. For example unix uses libgcc's libunwind bindings by default to | |
13 | //! acquire a backtrace, but coresymbolication or dladdr is used on OSX to | |
14 | //! acquire symbol names while linux uses gcc's libbacktrace. | |
15 | //! | |
16 | //! When using the default feature set of this library the "most reasonable" set | |
17 | //! of defaults is chosen for the current platform, but the features activated | |
18 | //! can also be controlled at a finer granularity. | |
19 | //! | |
7cac9316 XL |
20 | //! # API Principles |
21 | //! | |
ea8adc8c | 22 | //! This library attempts to be as flexible as possible to accommodate different |
7cac9316 XL |
23 | //! backend implementations of acquiring a backtrace. Consequently the currently |
24 | //! exported functions are closure-based as opposed to the likely expected | |
25 | //! iterator-based versions. This is done due to limitations of the underlying | |
26 | //! APIs used from the system. | |
27 | //! | |
28 | //! # Usage | |
29 | //! | |
30 | //! First, add this to your Cargo.toml | |
31 | //! | |
32 | //! ```toml | |
33 | //! [dependencies] | |
dc9dc135 | 34 | //! backtrace = "0.3" |
7cac9316 XL |
35 | //! ``` |
36 | //! | |
37 | //! Next: | |
38 | //! | |
39 | //! ``` | |
40 | //! extern crate backtrace; | |
41 | //! | |
42 | //! fn main() { | |
0731742a XL |
43 | //! # // Unsafe here so test passes on no_std. |
44 | //! # #[cfg(feature = "std")] { | |
7cac9316 XL |
45 | //! backtrace::trace(|frame| { |
46 | //! let ip = frame.ip(); | |
47 | //! let symbol_address = frame.symbol_address(); | |
48 | //! | |
49 | //! // Resolve this instruction pointer to a symbol name | |
dc9dc135 | 50 | //! backtrace::resolve_frame(frame, |symbol| { |
7cac9316 XL |
51 | //! if let Some(name) = symbol.name() { |
52 | //! // ... | |
53 | //! } | |
54 | //! if let Some(filename) = symbol.filename() { | |
55 | //! // ... | |
56 | //! } | |
57 | //! }); | |
58 | //! | |
59 | //! true // keep going to the next frame | |
60 | //! }); | |
61 | //! } | |
0731742a | 62 | //! # } |
7cac9316 XL |
63 | //! ``` |
64 | ||
8faf50e0 | 65 | #![doc(html_root_url = "https://docs.rs/backtrace")] |
7cac9316 | 66 | #![deny(missing_docs)] |
0731742a | 67 | #![no_std] |
74b04a01 XL |
68 | #![cfg_attr( |
69 | all(feature = "std", target_env = "sgx", target_vendor = "fortanix"), | |
70 | feature(sgx_platform) | |
71 | )] | |
dc9dc135 | 72 | #![allow(bare_trait_objects)] // TODO: remove when updating to 2018 edition |
416331ca | 73 | #![allow(rust_2018_idioms)] // TODO: remove when updating to 2018 edition |
0731742a XL |
74 | |
75 | #[cfg(feature = "std")] | |
dc9dc135 XL |
76 | #[macro_use] |
77 | extern crate std; | |
7cac9316 | 78 | |
416331ca | 79 | pub use crate::backtrace::{trace_unsynchronized, Frame}; |
7cac9316 XL |
80 | mod backtrace; |
81 | ||
416331ca XL |
82 | pub use crate::symbolize::resolve_frame_unsynchronized; |
83 | pub use crate::symbolize::{resolve_unsynchronized, Symbol, SymbolName}; | |
7cac9316 XL |
84 | mod symbolize; |
85 | ||
416331ca | 86 | pub use crate::types::BytesOrWideString; |
0731742a XL |
87 | mod types; |
88 | ||
416331ca XL |
89 | #[cfg(feature = "std")] |
90 | pub use crate::symbolize::clear_symbol_cache; | |
91 | ||
e1599b0c XL |
92 | mod print; |
93 | pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt}; | |
94 | ||
416331ca | 95 | cfg_if::cfg_if! { |
0731742a | 96 | if #[cfg(feature = "std")] { |
416331ca XL |
97 | pub use crate::backtrace::trace; |
98 | pub use crate::symbolize::{resolve, resolve_frame}; | |
99 | pub use crate::capture::{Backtrace, BacktraceFrame, BacktraceSymbol}; | |
0731742a XL |
100 | mod capture; |
101 | } | |
102 | } | |
7cac9316 XL |
103 | |
104 | #[allow(dead_code)] | |
105 | struct Bomb { | |
106 | enabled: bool, | |
107 | } | |
108 | ||
109 | #[allow(dead_code)] | |
110 | impl Drop for Bomb { | |
111 | fn drop(&mut self) { | |
112 | if self.enabled { | |
113 | panic!("cannot panic during the backtrace function"); | |
114 | } | |
115 | } | |
116 | } | |
117 | ||
118 | #[allow(dead_code)] | |
0731742a | 119 | #[cfg(feature = "std")] |
7cac9316 | 120 | mod lock { |
0731742a | 121 | use std::boxed::Box; |
dc9dc135 | 122 | use std::cell::Cell; |
416331ca | 123 | use std::sync::{Mutex, MutexGuard, Once}; |
7cac9316 | 124 | |
dc9dc135 | 125 | pub struct LockGuard(Option<MutexGuard<'static, ()>>); |
7cac9316 XL |
126 | |
127 | static mut LOCK: *mut Mutex<()> = 0 as *mut _; | |
416331ca | 128 | static INIT: Once = Once::new(); |
7cac9316 XL |
129 | thread_local!(static LOCK_HELD: Cell<bool> = Cell::new(false)); |
130 | ||
131 | impl Drop for LockGuard { | |
132 | fn drop(&mut self) { | |
dc9dc135 XL |
133 | if self.0.is_some() { |
134 | LOCK_HELD.with(|slot| { | |
135 | assert!(slot.get()); | |
136 | slot.set(false); | |
137 | }); | |
138 | } | |
7cac9316 XL |
139 | } |
140 | } | |
141 | ||
dc9dc135 | 142 | pub fn lock() -> LockGuard { |
7cac9316 | 143 | if LOCK_HELD.with(|l| l.get()) { |
dc9dc135 | 144 | return LockGuard(None); |
7cac9316 XL |
145 | } |
146 | LOCK_HELD.with(|s| s.set(true)); | |
147 | unsafe { | |
148 | INIT.call_once(|| { | |
0731742a | 149 | LOCK = Box::into_raw(Box::new(Mutex::new(()))); |
7cac9316 | 150 | }); |
dc9dc135 | 151 | LockGuard(Some((*LOCK).lock().unwrap())) |
7cac9316 XL |
152 | } |
153 | } | |
154 | } | |
155 | ||
416331ca | 156 | #[cfg(all(windows, feature = "dbghelp", not(target_vendor = "uwp")))] |
dc9dc135 XL |
157 | mod dbghelp; |
158 | #[cfg(windows)] | |
159 | mod windows; |