xref: /drstd/src/std/sys_common/backtrace.rs (revision b38c79420b3f9b2af3cf74b30d9faaadb20eb8b0)
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