]> git.proxmox.com Git - rustc.git/blob - vendor/backtrace/src/lib.rs
New upstream version 1.38.0+dfsg1
[rustc.git] / vendor / backtrace / src / lib.rs
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 //!
20 //! # API Principles
21 //!
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.
27 //!
28 //! # Usage
29 //!
30 //! First, add this to your Cargo.toml
31 //!
32 //! ```toml
33 //! [dependencies]
34 //! backtrace = "0.3"
35 //! ```
36 //!
37 //! Next:
38 //!
39 //! ```
40 //! extern crate backtrace;
41 //!
42 //! fn main() {
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();
48 //!
49 //! // Resolve this instruction pointer to a symbol name
50 //! backtrace::resolve_frame(frame, |symbol| {
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 //! }
62 //! # }
63 //! ```
64
65 #![doc(html_root_url = "https://docs.rs/backtrace")]
66 #![deny(missing_docs)]
67 #![no_std]
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
71
72 #[cfg(feature = "std")]
73 #[macro_use]
74 extern crate std;
75
76 pub use crate::backtrace::{trace_unsynchronized, Frame};
77 mod backtrace;
78
79 pub use crate::symbolize::resolve_frame_unsynchronized;
80 pub use crate::symbolize::{resolve_unsynchronized, Symbol, SymbolName};
81 mod symbolize;
82
83 pub use crate::types::BytesOrWideString;
84 mod types;
85
86 #[cfg(feature = "std")]
87 pub use crate::symbolize::clear_symbol_cache;
88
89 cfg_if::cfg_if! {
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};
94 mod capture;
95 }
96 }
97
98 #[allow(dead_code)]
99 struct Bomb {
100 enabled: bool,
101 }
102
103 #[allow(dead_code)]
104 impl Drop for Bomb {
105 fn drop(&mut self) {
106 if self.enabled {
107 panic!("cannot panic during the backtrace function");
108 }
109 }
110 }
111
112 #[allow(dead_code)]
113 #[cfg(feature = "std")]
114 mod lock {
115 use std::boxed::Box;
116 use std::cell::Cell;
117 use std::sync::{Mutex, MutexGuard, Once};
118
119 pub struct LockGuard(Option<MutexGuard<'static, ()>>);
120
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));
124
125 impl Drop for LockGuard {
126 fn drop(&mut self) {
127 if self.0.is_some() {
128 LOCK_HELD.with(|slot| {
129 assert!(slot.get());
130 slot.set(false);
131 });
132 }
133 }
134 }
135
136 pub fn lock() -> LockGuard {
137 if LOCK_HELD.with(|l| l.get()) {
138 return LockGuard(None);
139 }
140 LOCK_HELD.with(|s| s.set(true));
141 unsafe {
142 INIT.call_once(|| {
143 LOCK = Box::into_raw(Box::new(Mutex::new(())));
144 });
145 LockGuard(Some((*LOCK).lock().unwrap()))
146 }
147 }
148 }
149
150 #[cfg(all(windows, feature = "dbghelp", not(target_vendor = "uwp")))]
151 mod dbghelp;
152 #[cfg(windows)]
153 mod windows;