diff options
| author | Alan Egerton <eggyal@gmail.com> | 2020-08-04 22:18:20 +0100 |
|---|---|---|
| committer | Alan Egerton <eggyal@gmail.com> | 2020-08-07 19:31:25 +0100 |
| commit | 5792840bf52e4cf77ebb7b3bd93e9c90dd23f4e7 (patch) | |
| tree | a3bfeaade21999a1b1bba131225ba0238e767d19 /library/std/src | |
| parent | 4d4342347b71313258a46e506ee0a258f365185c (diff) | |
| download | rust-5792840bf52e4cf77ebb7b3bd93e9c90dd23f4e7.tar.gz rust-5792840bf52e4cf77ebb7b3bd93e9c90dd23f4e7.zip | |
Prevent `__rust_begin_short_backtrace` frames from being tail-call optimised away
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/panicking.rs | 9 | ||||
| -rw-r--r-- | library/std/src/rt.rs | 10 | ||||
| -rw-r--r-- | library/std/src/sys_common/backtrace.rs | 39 |
3 files changed, 47 insertions, 11 deletions
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index ab2a6010306..21ab0faed3e 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -434,7 +434,9 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { let loc = info.location().unwrap(); // The current implementation always returns Some let msg = info.message().unwrap(); // The current implementation always returns Some - rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc); + crate::sys_common::backtrace::__rust_end_short_backtrace(move || { + rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc); + }) } /// This is the entry point of panicking for the non-format-string variants of @@ -453,7 +455,10 @@ pub fn begin_panic<M: Any + Send>(msg: M) -> ! { intrinsics::abort() } - rust_panic_with_hook(&mut PanicPayload::new(msg), None, Location::caller()); + let loc = Location::caller(); + return crate::sys_common::backtrace::__rust_end_short_backtrace(move || { + rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc) + }); struct PanicPayload<A> { inner: Option<A>, diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index fb825ab16eb..45af9f68a0f 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -48,9 +48,7 @@ fn lang_start_internal( sys::args::init(argc, argv); // Let's run some code! - let exit_code = panic::catch_unwind(|| { - sys_common::backtrace::__rust_begin_short_backtrace(move || main()) - }); + let exit_code = panic::catch_unwind(main); sys_common::cleanup(); exit_code.unwrap_or(101) as isize @@ -64,5 +62,9 @@ fn lang_start<T: crate::process::Termination + 'static>( argc: isize, argv: *const *const u8, ) -> isize { - lang_start_internal(&move || main().report(), argc, argv) + lang_start_internal( + &move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report(), + argc, + argv, + ) } diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index d386a656e4f..1c5fbf7d701 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -74,6 +74,8 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: bt_fmt.add_context()?; let mut idx = 0; let mut res = Ok(()); + // Start immediately if we're not using a short backtrace. + let mut start = print_fmt != PrintFmt::Short; backtrace_rs::trace_unsynchronized(|frame| { if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { return false; @@ -89,16 +91,24 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: stop = true; return; } + if sym.contains("__rust_end_short_backtrace") { + start = true; + return; + } } } - res = bt_fmt.frame().symbol(frame, symbol); + if start { + res = bt_fmt.frame().symbol(frame, symbol); + } }); if stop { return false; } if !hit { - res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); + if start { + res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); + } } idx += 1; @@ -123,10 +133,29 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T where F: FnOnce() -> T, - F: Send, - T: Send, { - f() + let result = f(); + + // prevent this frame from being tail-call optimised away + crate::hint::black_box(()); + + result +} + +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that +/// this is only inline(never) when backtraces in libstd are enabled, otherwise +/// it's fine to optimize away. +#[cfg_attr(feature = "backtrace", inline(never))] +pub fn __rust_end_short_backtrace<F, T>(f: F) -> T +where + F: FnOnce() -> T, +{ + let result = f(); + + // prevent this frame from being tail-call optimised away + crate::hint::black_box(()); + + result } pub enum RustBacktrace { |
