1 //! A library for acquiring a backtrace at runtime
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
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.
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.
22 //! This library attempts to be as flexible as possible to accommodate different
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.
30 //! First, add this to your Cargo.toml
40 //! extern crate backtrace;
43 //! # // Unsafe here so test passes on no_std.
44 //! # #[cfg(feature = "std")] {
45 //! backtrace::trace(|frame| {
46 //! let ip = frame.ip();
47 //! let symbol_address = frame.symbol_address();
49 //! // Resolve this instruction pointer to a symbol name
50 //! backtrace::resolve_frame(frame, |symbol| {
51 //! if let Some(name) = symbol.name() {
54 //! if let Some(filename) = symbol.filename() {
59 //! true // keep going to the next frame
65 #![doc(html_root_url = "https://docs.rs/backtrace")]
66 #![deny(missing_docs)]
68 #![cfg_attr(all(feature = "std", target_env = "sgx"), feature(sgx_platform))]
69 #![allow(bare_trait_objects)] // TODO: remove when updating to 2018 edition
70 #![allow(rust_2018_idioms)] // TODO: remove when updating to 2018 edition
72 #[cfg(feature = "std")]
76 pub use crate::backtrace
::{trace_unsynchronized, Frame}
;
79 pub use crate::symbolize
::resolve_frame_unsynchronized
;
80 pub use crate::symbolize
::{resolve_unsynchronized, Symbol, SymbolName}
;
83 pub use crate::types
::BytesOrWideString
;
86 #[cfg(feature = "std")]
87 pub use crate::symbolize
::clear_symbol_cache
;
90 if #[cfg(feature = "std")] {
91 pub use crate::backtrace
::trace
;
92 pub use crate::symbolize
::{resolve, resolve_frame}
;
93 pub use crate::capture
::{Backtrace, BacktraceFrame, BacktraceSymbol}
;
107 panic
!("cannot panic during the backtrace function");
113 #[cfg(feature = "std")]
117 use std
::sync
::{Mutex, MutexGuard, Once}
;
119 pub struct LockGuard(Option
<MutexGuard
<'
static, ()>>);
121 static mut LOCK
: *mut Mutex
<()> = 0 as *mut _
;
122 static INIT
: Once
= Once
::new();
123 thread_local
!(static LOCK_HELD
: Cell
<bool
> = Cell
::new(false));
125 impl Drop
for LockGuard
{
127 if self.0.is_some
() {
128 LOCK_HELD
.with(|slot
| {
136 pub fn lock() -> LockGuard
{
137 if LOCK_HELD
.with(|l
| l
.get()) {
138 return LockGuard(None
);
140 LOCK_HELD
.with(|s
| s
.set(true));
143 LOCK
= Box
::into_raw(Box
::new(Mutex
::new(())));
145 LockGuard(Some((*LOCK
).lock().unwrap()))
150 #[cfg(all(windows, feature = "dbghelp", not(target_vendor = "uwp")))]