interpret/miri: call panic_cannot_unwind lang item instead of hard-coding the same message

This commit is contained in:
Ralf Jung 2023-08-19 13:21:41 +02:00
parent 818ec8e23a
commit 788fd44a3b
14 changed files with 147 additions and 42 deletions

View File

@ -765,7 +765,10 @@ pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tc
}
mir::UnwindAction::Terminate => {
self.frame_mut().loc = Right(self.frame_mut().body.span);
M::abort(self, "panic in a function that cannot unwind".to_owned())?;
M::unwind_terminate(self)?;
// This might have pushed a new stack frame, or it terminated execution.
// Either way, `loc` will not be updated.
return Ok(());
}
};
Ok(())
@ -865,6 +868,7 @@ pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx>
panic!("encountered StackPopCleanup::Root when unwinding!")
}
};
// This must be the very last thing that happens, since it can in fact push a new stack frame.
self.unwind_to_block(unwind)
} else {
// Follow the normal return edge.

View File

@ -223,6 +223,9 @@ fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: String) -> InterpResult<'t
throw_unsup_format!("aborting execution is not supported")
}
/// Called when unwinding reached a state where execution should be terminated.
fn unwind_terminate(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
/// Called for all binary operations where the LHS has pointer type.
///
/// Returns a (value, overflowed) pair if the operation succeeded
@ -499,6 +502,11 @@ fn ignore_optional_overflow_checks(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
false
}
#[inline(always)]
fn unwind_terminate(_ecx: &mut InterpCx<$mir, $tcx, Self>) -> InterpResult<$tcx> {
unreachable!("unwinding cannot happen during compile-time evaluation")
}
#[inline(always)]
fn call_extra_fn(
_ecx: &mut InterpCx<$mir, $tcx, Self>,

View File

@ -197,8 +197,7 @@ pub(super) fn eval_terminator(
}
UnwindTerminate => {
// FIXME: maybe should call `panic_no_unwind` lang item instead.
M::abort(self, "panic in a function that cannot unwind".to_owned())?;
M::unwind_terminate(self)?;
}
// When we encounter Resume, we've finished unwinding

View File

@ -976,6 +976,20 @@ fn abort(_ecx: &mut MiriInterpCx<'mir, 'tcx>, msg: String) -> InterpResult<'tcx,
throw_machine_stop!(TerminationInfo::Abort(msg))
}
fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
// Call the lang item.
let panic = ecx.tcx.lang_items().panic_cannot_unwind().unwrap();
let panic = ty::Instance::mono(ecx.tcx.tcx, panic);
ecx.call_function(
panic,
Abi::Rust,
&[],
None,
StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
)?;
Ok(())
}
#[inline(always)]
fn binary_ptr_op(
ecx: &MiriInterpCx<'mir, 'tcx>,

View File

@ -1,22 +1,35 @@
thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC:
explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: abnormal termination: panic in a function that cannot unwind
thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
note: inside `nounwind`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
|
LL | / extern "C-unwind" fn nounwind() {
LL | |
LL | |
LL | | panic!();
LL | | }
| |_^ panic in a function that cannot unwind
|
= note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
| |_^
note: inside `main`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
|
LL | unsafe { nounwind() }
| ^^^^^^^^^^
| ^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,22 +1,35 @@
thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC:
explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: abnormal termination: panic in a function that cannot unwind
thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
note: inside `nounwind`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
|
LL | / extern "C-unwind" fn nounwind() {
LL | |
LL | |
LL | | panic!();
LL | | }
| |_^ panic in a function that cannot unwind
|
= note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
| |_^
note: inside `main`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
|
LL | unsafe { nounwind() }
| ^^^^^^^^^^
| ^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -5,7 +5,7 @@ error: Undefined Behavior: unwinding past a stack frame that does not allow unwi
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
|
LL | unsafe { nounwind() }
| ^^^^^^^^^^ unwinding past a stack frame that does not allow unwinding
| ^ unwinding past a stack frame that does not allow unwinding
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -1,11 +1,14 @@
//@revisions: extern_block definition both
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
//@[definition,both]error-in-other-file: aborted execution
#![feature(rustc_attrs, c_unwind)]
#[cfg_attr(any(definition, both), rustc_nounwind)]
#[no_mangle]
extern "C-unwind" fn nounwind() {
//~[definition]^ ERROR: abnormal termination: panic in a function that cannot unwind
//~[both]^^ ERROR: abnormal termination: panic in a function that cannot unwind
panic!();
}

View File

@ -1,6 +1,8 @@
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
//@error-in-other-file: aborted execution
struct Foo;
impl Drop for Foo {
@ -9,7 +11,6 @@ fn drop(&mut self) {
}
}
fn main() {
//~^ERROR: panic in a function that cannot unwind
let _foo = Foo;
panic!("first");
}

View File

@ -4,17 +4,31 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at $DIR/double_panic.rs:LL:CC:
second
stack backtrace:
error: abnormal termination: panic in a function that cannot unwind
thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
note: inside `main`
--> $DIR/double_panic.rs:LL:CC
|
LL | / fn main() {
LL | |
LL | | let _foo = Foo;
LL | | panic!("first");
LL | | }
| |_^ panic in a function that cannot unwind
|
= note: inside `main` at $DIR/double_panic.rs:LL:CC
| |_^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,5 +1,10 @@
//@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000
// Enable MIR inlining to ensure that `TerminatorKind::Terminate` is generated
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
//@error-in-other-file: aborted execution
// Enable MIR inlining to ensure that `TerminatorKind::UnwindTerminate` is generated
// instead of just `UnwindAction::Terminate`.
#![feature(c_unwind)]
@ -12,7 +17,6 @@ fn drop(&mut self) {}
#[inline(always)]
fn has_cleanup() {
//~^ ERROR: panic in a function that cannot unwind
let _f = Foo;
panic!();
}

View File

@ -3,27 +3,41 @@ warning: You have explicitly enabled MIR optimizations, overriding Miri's defaul
thread 'main' panicked at $DIR/terminate-terminator.rs:LL:CC:
explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: abnormal termination: panic in a function that cannot unwind
thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
note: inside `has_cleanup`
--> $DIR/terminate-terminator.rs:LL:CC
|
LL | / fn has_cleanup() {
LL | |
LL | | let _f = Foo;
LL | | panic!();
LL | | }
| |_^ panic in a function that cannot unwind
|
= note: inside `has_cleanup` at $DIR/terminate-terminator.rs:LL:CC
| |_^
note: inside `panic_abort`
--> $DIR/terminate-terminator.rs:LL:CC
|
LL | has_cleanup();
| ^^^^^^^^^^^^^
| ^
note: inside `main`
--> $DIR/terminate-terminator.rs:LL:CC
|
LL | panic_abort();
| ^^^^^^^^^^^^^
| ^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,7 +1,11 @@
//@error-in-other-file: aborted execution
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
#![feature(c_unwind)]
extern "C" fn panic_abort() {
//~^ ERROR: panic in a function that cannot unwind
panic!()
}

View File

@ -1,21 +1,35 @@
thread 'main' panicked at $DIR/unwind-action-terminate.rs:LL:CC:
explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: abnormal termination: panic in a function that cannot unwind
thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
note: inside `panic_abort`
--> $DIR/unwind-action-terminate.rs:LL:CC
|
LL | / extern "C" fn panic_abort() {
LL | |
LL | | panic!()
LL | | }
| |_^ panic in a function that cannot unwind
|
= note: inside `panic_abort` at $DIR/unwind-action-terminate.rs:LL:CC
| |_^
note: inside `main`
--> $DIR/unwind-action-terminate.rs:LL:CC
|
LL | panic_abort();
| ^^^^^^^^^^^^^
| ^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace