]> git.proxmox.com Git - rustc.git/blob - src/vendor/backtrace/src/lib.rs
New upstream version 1.20.0+dfsg1
[rustc.git] / src / 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 //! # Platform Support
21 //!
22 //! Currently this library is verified to work on Linux, OSX, and Windows, but
23 //! it may work on other platforms as well. Note that the quality of the
24 //! backtrace may vary across platforms.
25 //!
26 //! # API Principles
27 //!
28 //! This library attempts to be as flexible as possible to accomodate different
29 //! backend implementations of acquiring a backtrace. Consequently the currently
30 //! exported functions are closure-based as opposed to the likely expected
31 //! iterator-based versions. This is done due to limitations of the underlying
32 //! APIs used from the system.
33 //!
34 //! # Usage
35 //!
36 //! First, add this to your Cargo.toml
37 //!
38 //! ```toml
39 //! [dependencies]
40 //! backtrace = "0.2"
41 //! ```
42 //!
43 //! Next:
44 //!
45 //! ```
46 //! extern crate backtrace;
47 //!
48 //! fn main() {
49 //! backtrace::trace(|frame| {
50 //! let ip = frame.ip();
51 //! let symbol_address = frame.symbol_address();
52 //!
53 //! // Resolve this instruction pointer to a symbol name
54 //! backtrace::resolve(ip, |symbol| {
55 //! if let Some(name) = symbol.name() {
56 //! // ...
57 //! }
58 //! if let Some(filename) = symbol.filename() {
59 //! // ...
60 //! }
61 //! });
62 //!
63 //! true // keep going to the next frame
64 //! });
65 //! }
66 //! ```
67
68 #![doc(html_root_url = "http://alexcrichton.com/backtrace-rs")]
69 #![deny(missing_docs)]
70 #![deny(warnings)]
71
72 extern crate libc;
73 #[cfg(all(windows, feature = "kernel32-sys"))] extern crate kernel32;
74 #[cfg(all(windows, feature = "winapi"))] extern crate winapi;
75 #[cfg(all(windows, feature = "dbghelp"))] extern crate dbghelp;
76
77 #[cfg(feature = "serde")]
78 extern crate serde;
79
80 #[cfg(feature = "serde_derive")]
81 #[cfg_attr(feature = "serde_derive", macro_use)]
82 extern crate serde_derive;
83
84 #[cfg(feature = "rustc-serialize")]
85 extern crate rustc_serialize;
86
87 #[macro_use]
88 extern crate cfg_if;
89
90 extern crate rustc_demangle;
91
92 #[cfg(feature = "cpp_demangle")]
93 extern crate cpp_demangle;
94
95 #[allow(dead_code)] // not used everywhere
96 #[cfg(unix)]
97 #[macro_use]
98 mod dylib;
99
100 pub use backtrace::{trace, Frame};
101 mod backtrace;
102
103 pub use symbolize::{resolve, Symbol, SymbolName};
104 mod symbolize;
105
106 pub use capture::{Backtrace, BacktraceFrame, BacktraceSymbol};
107 mod capture;
108
109 #[allow(dead_code)]
110 struct Bomb {
111 enabled: bool,
112 }
113
114 #[allow(dead_code)]
115 impl Drop for Bomb {
116 fn drop(&mut self) {
117 if self.enabled {
118 panic!("cannot panic during the backtrace function");
119 }
120 }
121 }
122
123 #[allow(dead_code)]
124 mod lock {
125 use std::cell::Cell;
126 use std::mem;
127 use std::sync::{Once, Mutex, MutexGuard, ONCE_INIT};
128
129 pub struct LockGuard(MutexGuard<'static, ()>);
130
131 static mut LOCK: *mut Mutex<()> = 0 as *mut _;
132 static INIT: Once = ONCE_INIT;
133 thread_local!(static LOCK_HELD: Cell<bool> = Cell::new(false));
134
135 impl Drop for LockGuard {
136 fn drop(&mut self) {
137 LOCK_HELD.with(|slot| {
138 assert!(slot.get());
139 slot.set(false);
140 });
141 }
142 }
143
144 pub fn lock() -> Option<LockGuard> {
145 if LOCK_HELD.with(|l| l.get()) {
146 return None
147 }
148 LOCK_HELD.with(|s| s.set(true));
149 unsafe {
150 INIT.call_once(|| {
151 LOCK = mem::transmute(Box::new(Mutex::new(())));
152 });
153 Some(LockGuard((*LOCK).lock().unwrap()))
154 }
155 }
156 }
157
158 // requires external synchronization
159 #[cfg(all(windows, feature = "dbghelp"))]
160 unsafe fn dbghelp_init() {
161 static mut INITIALIZED: bool = false;
162
163 if !INITIALIZED {
164 dbghelp::SymInitializeW(kernel32::GetCurrentProcess(),
165 0 as *mut _,
166 winapi::TRUE);
167 INITIALIZED = true;
168 }
169 }