diff --git a/library/std/src/sys/backtrace.rs b/library/std/src/sys/backtrace.rs index 7401d8ce320..133ea520e30 100644 --- a/library/std/src/sys/backtrace.rs +++ b/library/std/src/sys/backtrace.rs @@ -1,4 +1,5 @@ //! Common code for printing backtraces. +#![forbid(unsafe_op_in_unsafe_fn)] use crate::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt}; use crate::borrow::Cow; @@ -62,73 +63,76 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: // Start immediately if we're not using a short backtrace. let mut start = print_fmt != PrintFmt::Short; set_image_base(); - backtrace_rs::trace_unsynchronized(|frame| { - if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { - return false; - } - - let mut hit = false; - backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| { - hit = true; - - // Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace` - // are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be - // called before the panic hook, so we won't ignore any frames if there is no - // invoke of `__rust_begin_short_backtrace`. - if print_fmt == PrintFmt::Short { - if let Some(sym) = symbol.name().and_then(|s| s.as_str()) { - if start && sym.contains("__rust_begin_short_backtrace") { - start = false; - return; - } - if sym.contains("__rust_end_short_backtrace") { - start = true; - return; - } - if !start { - omitted_count += 1; - } - } + // SAFETY: we roll our own locking in this town + unsafe { + backtrace_rs::trace_unsynchronized(|frame| { + if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { + return false; } - if start { - if omitted_count > 0 { - debug_assert!(print_fmt == PrintFmt::Short); - // only print the message between the middle of frames - if !first_omit { - let _ = writeln!( - bt_fmt.formatter(), - " [... omitted {} frame{} ...]", - omitted_count, - if omitted_count > 1 { "s" } else { "" } - ); + let mut hit = false; + backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| { + hit = true; + + // Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace` + // are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be + // called before the panic hook, so we won't ignore any frames if there is no + // invoke of `__rust_begin_short_backtrace`. + if print_fmt == PrintFmt::Short { + if let Some(sym) = symbol.name().and_then(|s| s.as_str()) { + if start && sym.contains("__rust_begin_short_backtrace") { + start = false; + return; + } + if sym.contains("__rust_end_short_backtrace") { + start = true; + return; + } + if !start { + omitted_count += 1; + } } - first_omit = false; - omitted_count = 0; } - res = bt_fmt.frame().symbol(frame, symbol); + + if start { + if omitted_count > 0 { + debug_assert!(print_fmt == PrintFmt::Short); + // only print the message between the middle of frames + if !first_omit { + let _ = writeln!( + bt_fmt.formatter(), + " [... omitted {} frame{} ...]", + omitted_count, + if omitted_count > 1 { "s" } else { "" } + ); + } + first_omit = false; + omitted_count = 0; + } + res = bt_fmt.frame().symbol(frame, symbol); + } + }); + #[cfg(target_os = "nto")] + if libc::__my_thread_exit as *mut libc::c_void == frame.ip() { + if !hit && start { + use crate::backtrace_rs::SymbolName; + res = bt_fmt.frame().print_raw( + frame.ip(), + Some(SymbolName::new("__my_thread_exit".as_bytes())), + None, + None, + ); + } + return false; } - }); - #[cfg(target_os = "nto")] - if libc::__my_thread_exit as *mut libc::c_void == frame.ip() { if !hit && start { - use crate::backtrace_rs::SymbolName; - res = bt_fmt.frame().print_raw( - frame.ip(), - Some(SymbolName::new("__my_thread_exit".as_bytes())), - None, - None, - ); + res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); } - return false; - } - if !hit && start { - res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); - } - idx += 1; - res.is_ok() - }); + idx += 1; + res.is_ok() + }) + }; res?; bt_fmt.finish()?; if print_fmt == PrintFmt::Short {