summaryrefslogtreecommitdiffstats
path: root/library/backtrace/src/lib.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /library/backtrace/src/lib.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/backtrace/src/lib.rs')
-rw-r--r--library/backtrace/src/lib.rs193
1 files changed, 193 insertions, 0 deletions
diff --git a/library/backtrace/src/lib.rs b/library/backtrace/src/lib.rs
new file mode 100644
index 000000000..e5dea3387
--- /dev/null
+++ b/library/backtrace/src/lib.rs
@@ -0,0 +1,193 @@
+//! A library for acquiring a backtrace at runtime
+//!
+//! This library is meant to supplement the `RUST_BACKTRACE=1` support of the
+//! standard library by allowing an acquisition of a backtrace at runtime
+//! programmatically. The backtraces generated by this library do not need to be
+//! parsed, for example, and expose the functionality of multiple backend
+//! implementations.
+//!
+//! # Usage
+//!
+//! First, add this to your Cargo.toml
+//!
+//! ```toml
+//! [dependencies]
+//! backtrace = "0.3"
+//! ```
+//!
+//! Next:
+//!
+//! ```
+//! fn main() {
+//! # // Unsafe here so test passes on no_std.
+//! # #[cfg(feature = "std")] {
+//! backtrace::trace(|frame| {
+//! let ip = frame.ip();
+//! let symbol_address = frame.symbol_address();
+//!
+//! // Resolve this instruction pointer to a symbol name
+//! backtrace::resolve_frame(frame, |symbol| {
+//! if let Some(name) = symbol.name() {
+//! // ...
+//! }
+//! if let Some(filename) = symbol.filename() {
+//! // ...
+//! }
+//! });
+//!
+//! true // keep going to the next frame
+//! });
+//! }
+//! # }
+//! ```
+//!
+//! # Backtrace accuracy
+//!
+//! This crate implements best-effort attempts to get the native backtrace. This
+//! is not always guaranteed to work, and some platforms don't return any
+//! backtrace at all. If your application requires accurate backtraces then it's
+//! recommended to closely evaluate this crate to see whether it's suitable
+//! for your use case on your target platforms.
+//!
+//! Even on supported platforms, there's a number of reasons that backtraces may
+//! be less-than-accurate, including but not limited to:
+//!
+//! * Unwind information may not be available. This crate primarily implements
+//! backtraces by unwinding the stack, but not all functions may have
+//! unwinding information (e.g. DWARF unwinding information).
+//!
+//! * Rust code may be compiled without unwinding information for some
+//! functions. This can also happen for Rust code compiled with
+//! `-Cpanic=abort`. You can remedy this, however, with
+//! `-Cforce-unwind-tables` as a compiler option.
+//!
+//! * Unwind information may be inaccurate or corrupt. In the worst case
+//! inaccurate unwind information can lead this library to segfault. In the
+//! best case inaccurate information will result in a truncated stack trace.
+//!
+//! * Backtraces may not report filenames/line numbers correctly due to missing
+//! or corrupt debug information. This won't lead to segfaults unlike corrupt
+//! unwinding information, but missing or malformed debug information will
+//! mean that filenames and line numbers will not be available. This may be
+//! because debug information wasn't generated by the compiler, or it's just
+//! missing on the filesystem.
+//!
+//! * Not all platforms are supported. For example there's no way to get a
+//! backtrace on WebAssembly at the moment.
+//!
+//! * Crate features may be disabled. Currently this crate supports using Gimli
+//! libbacktrace on non-Windows platforms for reading debuginfo for
+//! backtraces. If both crate features are disabled, however, then these
+//! platforms will generate a backtrace but be unable to generate symbols for
+//! it.
+//!
+//! In most standard workflows for most standard platforms you generally don't
+//! need to worry about these caveats. We'll try to fix ones where we can over
+//! time, but otherwise it's important to be aware of the limitations of
+//! unwinding-based backtraces!
+
+#![doc(html_root_url = "https://docs.rs/backtrace")]
+#![deny(missing_docs)]
+#![no_std]
+#![cfg_attr(
+ all(feature = "std", target_env = "sgx", target_vendor = "fortanix"),
+ feature(sgx_platform)
+)]
+#![warn(rust_2018_idioms)]
+// When we're building as part of libstd, silence all warnings since they're
+// irrelevant as this crate is developed out-of-tree.
+#![cfg_attr(backtrace_in_libstd, allow(warnings))]
+#![cfg_attr(not(feature = "std"), allow(dead_code))]
+// We know this is deprecated, it's only here for back-compat reasons.
+#![cfg_attr(feature = "rustc-serialize", allow(deprecated))]
+
+#[cfg(feature = "std")]
+#[macro_use]
+extern crate std;
+
+// This is only used for gimli right now, which is only used on some platforms, and miri
+// so don't worry if it's unused in other configurations.
+#[allow(unused_extern_crates)]
+extern crate alloc;
+
+pub use self::backtrace::{trace_unsynchronized, Frame};
+mod backtrace;
+
+pub use self::symbolize::resolve_frame_unsynchronized;
+pub use self::symbolize::{resolve_unsynchronized, Symbol, SymbolName};
+mod symbolize;
+
+pub use self::types::BytesOrWideString;
+mod types;
+
+#[cfg(feature = "std")]
+pub use self::symbolize::clear_symbol_cache;
+
+mod print;
+pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt};
+
+cfg_if::cfg_if! {
+ if #[cfg(feature = "std")] {
+ pub use self::backtrace::trace;
+ pub use self::symbolize::{resolve, resolve_frame};
+ pub use self::capture::{Backtrace, BacktraceFrame, BacktraceSymbol};
+ mod capture;
+ }
+}
+
+#[allow(dead_code)]
+struct Bomb {
+ enabled: bool,
+}
+
+#[allow(dead_code)]
+impl Drop for Bomb {
+ fn drop(&mut self) {
+ if self.enabled {
+ panic!("cannot panic during the backtrace function");
+ }
+ }
+}
+
+#[allow(dead_code)]
+#[cfg(feature = "std")]
+mod lock {
+ use std::boxed::Box;
+ use std::cell::Cell;
+ use std::sync::{Mutex, MutexGuard, Once};
+
+ pub struct LockGuard(Option<MutexGuard<'static, ()>>);
+
+ static mut LOCK: *mut Mutex<()> = 0 as *mut _;
+ static INIT: Once = Once::new();
+ thread_local!(static LOCK_HELD: Cell<bool> = Cell::new(false));
+
+ impl Drop for LockGuard {
+ fn drop(&mut self) {
+ if self.0.is_some() {
+ LOCK_HELD.with(|slot| {
+ assert!(slot.get());
+ slot.set(false);
+ });
+ }
+ }
+ }
+
+ pub fn lock() -> LockGuard {
+ if LOCK_HELD.with(|l| l.get()) {
+ return LockGuard(None);
+ }
+ LOCK_HELD.with(|s| s.set(true));
+ unsafe {
+ INIT.call_once(|| {
+ LOCK = Box::into_raw(Box::new(Mutex::new(())));
+ });
+ LockGuard(Some((*LOCK).lock().unwrap()))
+ }
+ }
+}
+
+#[cfg(all(windows, not(target_vendor = "uwp")))]
+mod dbghelp;
+#[cfg(windows)]
+mod windows;