1 //use crate::std::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt};
2
3 use crate::std::sync::{Mutex, PoisonError};
4
5 #[allow(dead_code)]
6 /// Max number of frames to print.
7 const MAX_NB_FRAMES: usize = 100;
8
9 #[allow(dead_code)]
lock() -> impl Drop10 pub fn lock() -> impl Drop {
11 static LOCK: Mutex<()> = Mutex::new(());
12 LOCK.lock().unwrap_or_else(PoisonError::into_inner)
13 }
14
15 /// Prints the current backtrace.
16 // pub fn print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> {
17 // // There are issues currently linking libbacktrace into tests, and in
18 // // general during std's own unit tests we're not testing this path. In
19 // // test mode immediately return here to optimize away any references to the
20 // // libbacktrace symbols
21 // if cfg!(test) {
22 // return Ok(());
23 // }
24
25 // // Use a lock to prevent mixed output in multithreading context.
26 // // Some platforms also requires it, like `SymFromAddr` on Windows.
27 // unsafe {
28 // let _lock = lock();
29 // _print(w, format)
30 // }
31 // }
32
33 // unsafe fn _print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> {
34 // struct DisplayBacktrace {
35 // format: PrintFmt,
36 // }
37 // impl fmt::Display for DisplayBacktrace {
38 // fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
39 // unsafe { _print_fmt(fmt, self.format) }
40 // }
41 // }
42 // write!(w, "{}", DisplayBacktrace { format })
43 // }
44
45 // unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::Result {
46 // // // Always 'fail' to get the cwd when running under Miri -
47 // // // this allows Miri to display backtraces in isolation mode
48 // // let cwd = if !cfg!(miri) { env::current_dir().ok() } else { None };
49
50 // // let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| {
51 // // output_filename(fmt, bows, print_fmt, cwd.as_ref())
52 // // };
53 // // writeln!(fmt, "stack backtrace:")?;
54 // // let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path);
55 // // bt_fmt.add_context()?;
56 // // let mut idx = 0;
57 // // let mut res = Ok(());
58 // // let mut omitted_count: usize = 0;
59 // // let mut first_omit = true;
60 // // // Start immediately if we're not using a short backtrace.
61 // // let mut start = print_fmt != PrintFmt::Short;
62 // // // backtrace_rs::trace_unsynchronized(|frame| {
63 // // // if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
64 // // // return false;
65 // // // }
66
67 // // // let mut hit = false;
68 // // // backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
69 // // // hit = true;
70
71 // // // // Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace`
72 // // // // are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be
73 // // // // called before the panic hook, so we won't ignore any frames if there is no
74 // // // // invoke of `__rust_begin_short_backtrace`.
75 // // // if print_fmt == PrintFmt::Short {
76 // // // if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
77 // // // if start && sym.contains("__rust_begin_short_backtrace") {
78 // // // start = false;
79 // // // return;
80 // // // }
81 // // // if sym.contains("__rust_end_short_backtrace") {
82 // // // start = true;
83 // // // return;
84 // // // }
85 // // // if !start {
86 // // // omitted_count += 1;
87 // // // }
88 // // // }
89 // // // }
90
91 // // // if start {
92 // // // if omitted_count > 0 {
93 // // // debug_assert!(print_fmt == PrintFmt::Short);
94 // // // // only print the message between the middle of frames
95 // // // if !first_omit {
96 // // // let _ = writeln!(
97 // // // bt_fmt.formatter(),
98 // // // " [... omitted {} frame{} ...]",
99 // // // omitted_count,
100 // // // if omitted_count > 1 { "s" } else { "" }
101 // // // );
102 // // // }
103 // // // first_omit = false;
104 // // // omitted_count = 0;
105 // // // }
106 // // // res = bt_fmt.frame().symbol(frame, symbol);
107 // // // }
108 // // // });
109 // // // #[cfg(target_os = "nto")]
110 // // // if dlibc::__my_thread_exit as *mut dlibc::c_void == frame.ip() {
111 // // // if !hit && start {
112 // // // use crate::std::backtrace_rs::SymbolName;
113 // // // res = bt_fmt.frame().print_raw(
114 // // // frame.ip(),
115 // // // Some(SymbolName::new("__my_thread_exit".as_bytes())),
116 // // // None,
117 // // // None,
118 // // // );
119 // // // }
120 // // // return false;
121 // // // }
122 // // // if !hit && start {
123 // // // res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
124 // // // }
125
126 // // // idx += 1;
127 // // // res.is_ok()
128 // // // });
129 // // res?;
130 // // bt_fmt.finish()?;
131 // // if print_fmt == PrintFmt::Short {
132 // // writeln!(
133 // // fmt,
134 // // "note: Some details are omitted, \
135 // // run with `RUST_BACKTRACE=full` for a verbose backtrace."
136 // // )?;
137 // // }
138 // Ok(())
139 // }
140
141 /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
142 /// this is only inline(never) when backtraces in std are enabled, otherwise
143 /// it's fine to optimize away.
144 #[cfg_attr(feature = "backtrace", inline(never))]
__rust_begin_short_backtrace<F, T>(f: F) -> T where F: FnOnce() -> T,145 pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
146 where
147 F: FnOnce() -> T,
148 {
149 let result = f();
150
151 // prevent this frame from being tail-call optimised away
152 crate::std::hint::black_box(());
153
154 result
155 }
156
157 /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
158 /// this is only inline(never) when backtraces in std are enabled, otherwise
159 /// it's fine to optimize away.
160 #[cfg_attr(feature = "backtrace", inline(never))]
__rust_end_short_backtrace<F, T>(f: F) -> T where F: FnOnce() -> T,161 pub fn __rust_end_short_backtrace<F, T>(f: F) -> T
162 where
163 F: FnOnce() -> T,
164 {
165 let result = f();
166
167 // prevent this frame from being tail-call optimised away
168 crate::std::hint::black_box(());
169
170 result
171 }
172
173 // pub fn output_filename(
174 // fmt: &mut fmt::Formatter<'_>,
175 // bows: BytesOrWideString<'_>,
176 // print_fmt: PrintFmt,
177 // cwd: Option<&PathBuf>,
178 // ) -> fmt::Result {
179 // let file: Cow<'_, Path> = match bows {
180 // #[cfg(unix)]
181 // BytesOrWideString::Bytes(bytes) => {
182 // use crate::std::os::unix::prelude::*;
183 // Path::new(crate::std::ffi::OsStr::from_bytes(bytes)).into()
184 // }
185 // #[cfg(not(unix))]
186 // BytesOrWideString::Bytes(bytes) => {
187 // Path::new(crate::std::str::from_utf8(bytes).unwrap_or("<unknown>")).into()
188 // }
189 // #[cfg(windows)]
190 // BytesOrWideString::Wide(wide) => {
191 // use crate::std::os::windows::prelude::*;
192 // Cow::Owned(crate::std::ffi::OsString::from_wide(wide).into())
193 // }
194 // #[cfg(not(windows))]
195 // BytesOrWideString::Wide(_wide) => Path::new("<unknown>").into(),
196 // };
197 // if print_fmt == PrintFmt::Short && file.is_absolute() {
198 // if let Some(cwd) = cwd {
199 // if let Ok(stripped) = file.strip_prefix(&cwd) {
200 // if let Some(s) = stripped.to_str() {
201 // return write!(fmt, ".{}{s}", path::MAIN_SEPARATOR);
202 // }
203 // }
204 // }
205 // }
206 // fmt::Display::fmt(&file.display(), fmt)
207 // }
208