From 7d74ebecce49448b1d969f8e6cee27c472a6f6b0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 24 Feb 2024 14:27:27 +0000 Subject: [PATCH 1/2] Directly implement native exception raise methods in miri Windows still needs the old custom ABI as SEH unwinding isn't supported by miri. Unlike DWARF unwinding it preserves all stack frames until right after the do_catch function has executed. Because of this panic_unwind stack allocates the exception object. Miri can't currently model unwinding without destroying stack frames and as such will report a use-after-free of the exception object. --- src/intrinsics/mod.rs | 7 ++- src/shims/foreign_items.rs | 4 ++ src/shims/mod.rs | 2 + src/shims/unix/foreign_items.rs | 11 ++++ tests/pass/panic/unwind_dwarf.rs | 95 ++++++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 tests/pass/panic/unwind_dwarf.rs diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 7344846d6d..59b24b0f63 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -26,7 +26,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, ret: Option, - _unwind: mir::UnwindAction, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option>> { let this = self.eval_context_mut(); @@ -67,6 +67,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.return_to_block(ret)?; Ok(None) } + EmulateItemResult::NeedsUnwind => { + // Jump to the unwind block to begin unwinding. + this.unwind_to_block(unwind)?; + Ok(None) + } EmulateItemResult::AlreadyJumped => Ok(None), } } diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index a65da823e2..b363531a2d 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -87,6 +87,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { trace!("{:?}", this.dump_place(&dest.clone().into())); this.return_to_block(ret)?; } + EmulateItemResult::NeedsUnwind => { + // Jump to the unwind block to begin unwinding. + this.unwind_to_block(unwind)?; + } EmulateItemResult::AlreadyJumped => (), EmulateItemResult::NotSupported => { if let Some(body) = this.lookup_exported_symbol(link_name)? { diff --git a/src/shims/mod.rs b/src/shims/mod.rs index d9c4a2282c..0e80c142b4 100644 --- a/src/shims/mod.rs +++ b/src/shims/mod.rs @@ -23,6 +23,8 @@ pub use unix::{DirTable, FdTable}; pub enum EmulateItemResult { /// The caller is expected to jump to the return block. NeedsJumping, + /// The caller is expected to jump to the unwind block. + NeedsUnwind, /// Jumping has already been taken care of. AlreadyJumped, /// The item is not supported. diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 396011cc22..ed23771d2b 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -639,6 +639,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.gen_random(ptr, len)?; this.write_scalar(Scalar::from_target_usize(len, this), dest)?; } + "_Unwind_RaiseException" => { + trace!("_Unwind_RaiseException: {:?}", this.frame().instance); + + // Get the raw pointer stored in arg[0] (the panic payload). + let [payload] = this.check_shim(abi, Abi::C { unwind: true }, link_name, args)?; + let payload = this.read_scalar(payload)?; + let thread = this.active_thread_mut(); + thread.panic_payloads.push(payload); + + return Ok(EmulateItemResult::NeedsUnwind); + } // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. diff --git a/tests/pass/panic/unwind_dwarf.rs b/tests/pass/panic/unwind_dwarf.rs new file mode 100644 index 0000000000..aa5ec05fbc --- /dev/null +++ b/tests/pass/panic/unwind_dwarf.rs @@ -0,0 +1,95 @@ +//@only-target-linux +#![feature(core_intrinsics, panic_unwind, rustc_attrs)] +#![allow(internal_features)] + +//! Unwinding using `_Unwind_RaiseException` + +extern crate unwind as uw; + +use std::any::Any; +use std::ptr; + +#[repr(C)] +struct Exception { + _uwe: uw::_Unwind_Exception, + cause: Box, +} + +pub fn panic(data: Box) -> u32 { + let exception = Box::new(Exception { + _uwe: uw::_Unwind_Exception { + exception_class: rust_exception_class(), + exception_cleanup, + private: [core::ptr::null(); uw::unwinder_private_data_size], + }, + cause: data, + }); + let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception; + return unsafe { uw::_Unwind_RaiseException(exception_param) as u32 }; + + extern "C" fn exception_cleanup( + _unwind_code: uw::_Unwind_Reason_Code, + _exception: *mut uw::_Unwind_Exception, + ) { + std::process::abort(); + } +} + +pub unsafe fn rust_panic_cleanup(ptr: *mut u8) -> Box { + let exception = ptr as *mut uw::_Unwind_Exception; + if (*exception).exception_class != rust_exception_class() { + std::process::abort(); + } + + let exception = exception.cast::(); + + let exception = Box::from_raw(exception as *mut Exception); + exception.cause +} + +fn rust_exception_class() -> uw::_Unwind_Exception_Class { + // M O Z \0 R U S T -- vendor, language + 0x4d4f5a_00_52555354 +} + +pub fn catch_unwind R>(f: F) -> Result> { + struct Data { + f: Option, + r: Option, + p: Option>, + } + + let mut data = Data { f: Some(f), r: None, p: None }; + + let data_ptr = ptr::addr_of_mut!(data) as *mut u8; + unsafe { + return if std::intrinsics::r#try(do_call::, data_ptr, do_catch::) == 0 { + Ok(data.r.take().unwrap()) + } else { + Err(data.p.take().unwrap()) + }; + } + + fn do_call R, R>(data: *mut u8) { + unsafe { + let data = &mut *data.cast::>(); + let f = data.f.take().unwrap(); + data.r = Some(f()); + } + } + + #[rustc_nounwind] + fn do_catch R, R>(data: *mut u8, payload: *mut u8) { + unsafe { + let obj = rust_panic_cleanup(payload); + (*data.cast::>()).p = Some(obj); + } + } +} + +fn main() { + assert_eq!( + catch_unwind(|| panic(Box::new(42))).unwrap_err().downcast::().unwrap(), + Box::new(42) + ); +} From c7debbdb0284a2d385511900b3cf8ae4bf6c6c06 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 19 May 2024 19:07:53 +0200 Subject: [PATCH 2/2] various small nits - share implementation with miri_starting_unwind - make test use a custom unwinding class - extend comments - use NeedsUnwind more consistently --- ci/ci.sh | 2 +- src/intrinsics/atomic.rs | 2 +- src/intrinsics/mod.rs | 4 +-- src/intrinsics/simd.rs | 2 +- src/shims/alloc.rs | 2 +- src/shims/foreign_items.rs | 19 +++++++-------- src/shims/mod.rs | 4 +-- src/shims/panic.rs | 13 +--------- src/shims/unix/android/foreign_items.rs | 2 +- src/shims/unix/foreign_items.rs | 30 +++++++++++++++++------ src/shims/unix/freebsd/foreign_items.rs | 2 +- src/shims/unix/linux/foreign_items.rs | 2 +- src/shims/unix/macos/foreign_items.rs | 2 +- src/shims/unix/solarish/foreign_items.rs | 2 +- src/shims/wasi/foreign_items.rs | 2 +- src/shims/windows/foreign_items.rs | 2 +- src/shims/x86/aesni.rs | 2 +- src/shims/x86/avx.rs | 2 +- src/shims/x86/avx2.rs | 2 +- src/shims/x86/mod.rs | 2 +- src/shims/x86/sse.rs | 2 +- src/shims/x86/sse2.rs | 2 +- src/shims/x86/sse3.rs | 2 +- src/shims/x86/sse41.rs | 2 +- src/shims/x86/ssse3.rs | 2 +- tests/pass/panic/unwind_dwarf.rs | 31 ++++++++++++------------ 26 files changed, 72 insertions(+), 69 deletions(-) diff --git a/ci/ci.sh b/ci/ci.sh index 9480663a01..4e92169b3d 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -145,7 +145,7 @@ case $HOST_TARGET in TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice # Partially supported targets (tier 2) BASIC="empty_main integer vec string btreemap hello hashmap heap_alloc align" # ensures we have the basics: stdout/stderr, system allocator, randomness (for HashMap initialization) - UNIX="panic/panic concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there + UNIX="panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX pthread-sync diff --git a/src/intrinsics/atomic.rs b/src/intrinsics/atomic.rs index 0c212c45db..501dbc1603 100644 --- a/src/intrinsics/atomic.rs +++ b/src/intrinsics/atomic.rs @@ -116,7 +116,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 59b24b0f63..0a7927d062 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -62,7 +62,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { args: instance.args, })) } - EmulateItemResult::NeedsJumping => { + EmulateItemResult::NeedsReturn => { trace!("{:?}", this.dump_place(&dest.clone().into())); this.return_to_block(ret)?; Ok(None) @@ -446,6 +446,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index d0a78429ca..4cde364fbc 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -746,7 +746,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } fn fminmax_op( diff --git a/src/shims/alloc.rs b/src/shims/alloc.rs index bd84de81e6..ca672bdc61 100644 --- a/src/shims/alloc.rs +++ b/src/shims/alloc.rs @@ -87,7 +87,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } AllocatorKind::Default => { default(this)?; - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } } diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index b363531a2d..eccccb4a44 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -82,8 +82,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // The rest either implements the logic, or falls back to `lookup_exported_symbol`. - match this.emulate_foreign_item_inner(link_name, abi, args, dest, unwind)? { - EmulateItemResult::NeedsJumping => { + match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { + EmulateItemResult::NeedsReturn => { trace!("{:?}", this.dump_place(&dest.clone().into())); this.return_to_block(ret)?; } @@ -210,7 +210,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - unwind: mir::UnwindAction, ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); @@ -222,7 +221,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // by the specified `.so` file; we should continue and check if it corresponds to // a provided shim. if this.call_native_fn(link_name, dest, args)? { - return Ok(EmulateItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsReturn); } } @@ -267,9 +266,9 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { match link_name.as_str() { // Miri-specific extern functions "miri_start_unwind" => { - // `check_shim` happens inside `handle_miri_start_unwind`. - this.handle_miri_start_unwind(abi, link_name, args, unwind)?; - return Ok(EmulateItemResult::AlreadyJumped); + let [payload] = this.check_shim(abi, Abi::Rust, link_name, args)?; + this.handle_miri_start_unwind(payload)?; + return Ok(EmulateItemResult::NeedsUnwind); } "miri_run_provenance_gc" => { let [] = this.check_shim(abi, Abi::Rust, link_name, args)?; @@ -484,7 +483,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "__rust_alloc" => return this.emulate_allocator(default), "miri_alloc" => { default(this)?; - return Ok(EmulateItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsReturn); } _ => unreachable!(), } @@ -544,7 +543,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "miri_dealloc" => { default(this)?; - return Ok(EmulateItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsReturn); } _ => unreachable!(), } @@ -965,6 +964,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; // We only fall through to here if we did *not* hit the `_` arm above, // i.e., if we actually emulated the function with one of the shims. - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/mod.rs b/src/shims/mod.rs index 0e80c142b4..a41a2883c9 100644 --- a/src/shims/mod.rs +++ b/src/shims/mod.rs @@ -22,10 +22,10 @@ pub use unix::{DirTable, FdTable}; /// What needs to be done after emulating an item (a shim or an intrinsic) is done. pub enum EmulateItemResult { /// The caller is expected to jump to the return block. - NeedsJumping, + NeedsReturn, /// The caller is expected to jump to the unwind block. NeedsUnwind, - /// Jumping has already been taken care of. + /// Jumping to the next block has already been taken care of. AlreadyJumped, /// The item is not supported. NotSupported, diff --git a/src/shims/panic.rs b/src/shims/panic.rs index 4444d29746..e0e5396a45 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -13,7 +13,6 @@ use rustc_ast::Mutability; use rustc_middle::{mir, ty}; -use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use rustc_target::spec::PanicStrategy; @@ -46,25 +45,15 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Handles the special `miri_start_unwind` intrinsic, which is called /// by libpanic_unwind to delegate the actual unwinding process to Miri. - fn handle_miri_start_unwind( - &mut self, - abi: Abi, - link_name: Symbol, - args: &[OpTy<'tcx, Provenance>], - unwind: mir::UnwindAction, - ) -> InterpResult<'tcx> { + fn handle_miri_start_unwind(&mut self, payload: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); trace!("miri_start_unwind: {:?}", this.frame().instance); - // Get the raw pointer stored in arg[0] (the panic payload). - let [payload] = this.check_shim(abi, Abi::Rust, link_name, args)?; let payload = this.read_scalar(payload)?; let thread = this.active_thread_mut(); thread.panic_payloads.push(payload); - // Jump to the unwind block to begin unwinding. - this.unwind_to_block(unwind)?; Ok(()) } diff --git a/src/shims/unix/android/foreign_items.rs b/src/shims/unix/android/foreign_items.rs index f85b8a725f..590a5672f1 100644 --- a/src/shims/unix/android/foreign_items.rs +++ b/src/shims/unix/android/foreign_items.rs @@ -27,6 +27,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index ed23771d2b..86dd23f31c 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -640,14 +640,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(Scalar::from_target_usize(len, this), dest)?; } "_Unwind_RaiseException" => { - trace!("_Unwind_RaiseException: {:?}", this.frame().instance); - - // Get the raw pointer stored in arg[0] (the panic payload). + // This is not formally part of POSIX, but it is very wide-spread on POSIX systems. + // It was originally specified as part of the Itanium C++ ABI: + // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-throw. + // On Linux it is + // documented as part of the LSB: + // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib--unwind-raiseexception.html + // Basically every other UNIX uses the exact same api though. Arm also references + // back to the Itanium C++ ABI for the definition of `_Unwind_RaiseException` for + // arm64: + // https://github.com/ARM-software/abi-aa/blob/main/cppabi64/cppabi64.rst#toc-entry-35 + // For arm32 they did something custom, but similar enough that the same + // `_Unwind_RaiseException` impl in miri should work: + // https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst + if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "illumos" | "solaris" | "android" | "macos") { + throw_unsup_format!( + "`_Unwind_RaiseException` is not supported on {}", + this.tcx.sess.target.os + ); + } + // This function looks and behaves excatly like miri_start_unwind. let [payload] = this.check_shim(abi, Abi::C { unwind: true }, link_name, args)?; - let payload = this.read_scalar(payload)?; - let thread = this.active_thread_mut(); - thread.panic_payloads.push(payload); - + this.handle_miri_start_unwind(payload)?; return Ok(EmulateItemResult::NeedsUnwind); } @@ -771,6 +785,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } }; - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/unix/freebsd/foreign_items.rs b/src/shims/unix/freebsd/foreign_items.rs index e70cd35dda..8a7f7e9d1f 100644 --- a/src/shims/unix/freebsd/foreign_items.rs +++ b/src/shims/unix/freebsd/foreign_items.rs @@ -86,6 +86,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/unix/linux/foreign_items.rs b/src/shims/unix/linux/foreign_items.rs index 7cd749a410..b2666101ff 100644 --- a/src/shims/unix/linux/foreign_items.rs +++ b/src/shims/unix/linux/foreign_items.rs @@ -203,6 +203,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), }; - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/unix/macos/foreign_items.rs b/src/shims/unix/macos/foreign_items.rs index 912623b722..2b9ce746a5 100644 --- a/src/shims/unix/macos/foreign_items.rs +++ b/src/shims/unix/macos/foreign_items.rs @@ -177,6 +177,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), }; - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/unix/solarish/foreign_items.rs b/src/shims/unix/solarish/foreign_items.rs index c216d8afd7..6c5155618c 100644 --- a/src/shims/unix/solarish/foreign_items.rs +++ b/src/shims/unix/solarish/foreign_items.rs @@ -45,6 +45,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/wasi/foreign_items.rs b/src/shims/wasi/foreign_items.rs index d911f43eb6..774a5e7202 100644 --- a/src/shims/wasi/foreign_items.rs +++ b/src/shims/wasi/foreign_items.rs @@ -35,6 +35,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index 086abf19c5..91def80227 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -762,6 +762,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/x86/aesni.rs b/src/shims/x86/aesni.rs index 8dc3748a12..3a66c43150 100644 --- a/src/shims/x86/aesni.rs +++ b/src/shims/x86/aesni.rs @@ -127,7 +127,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // with an external crate. _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/x86/avx.rs b/src/shims/x86/avx.rs index 86ef180a44..b1c61c8b3b 100644 --- a/src/shims/x86/avx.rs +++ b/src/shims/x86/avx.rs @@ -344,6 +344,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/x86/avx2.rs b/src/shims/x86/avx2.rs index adecf7b892..e0bd2298ab 100644 --- a/src/shims/x86/avx2.rs +++ b/src/shims/x86/avx2.rs @@ -440,6 +440,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/x86/mod.rs b/src/shims/x86/mod.rs index 58d6db1886..1f7138ca33 100644 --- a/src/shims/x86/mod.rs +++ b/src/shims/x86/mod.rs @@ -144,7 +144,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/x86/sse.rs b/src/shims/x86/sse.rs index ea967a8cf7..3636fb2f3f 100644 --- a/src/shims/x86/sse.rs +++ b/src/shims/x86/sse.rs @@ -212,6 +212,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/x86/sse2.rs b/src/shims/x86/sse2.rs index 31fa66a496..54d1e0c803 100644 --- a/src/shims/x86/sse2.rs +++ b/src/shims/x86/sse2.rs @@ -388,6 +388,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/x86/sse3.rs b/src/shims/x86/sse3.rs index 8de339eb9e..fa1dd07e90 100644 --- a/src/shims/x86/sse3.rs +++ b/src/shims/x86/sse3.rs @@ -51,6 +51,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/x86/sse41.rs b/src/shims/x86/sse41.rs index 011a7a16c6..cd82108678 100644 --- a/src/shims/x86/sse41.rs +++ b/src/shims/x86/sse41.rs @@ -176,6 +176,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/src/shims/x86/ssse3.rs b/src/shims/x86/ssse3.rs index d30de43008..ec625da68c 100644 --- a/src/shims/x86/ssse3.rs +++ b/src/shims/x86/ssse3.rs @@ -137,6 +137,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsReturn) } } diff --git a/tests/pass/panic/unwind_dwarf.rs b/tests/pass/panic/unwind_dwarf.rs index aa5ec05fbc..f690be471b 100644 --- a/tests/pass/panic/unwind_dwarf.rs +++ b/tests/pass/panic/unwind_dwarf.rs @@ -1,4 +1,4 @@ -//@only-target-linux +//@ignore-target-windows: Windows uses a different unwinding mechanism #![feature(core_intrinsics, panic_unwind, rustc_attrs)] #![allow(internal_features)] @@ -16,28 +16,28 @@ struct Exception { } pub fn panic(data: Box) -> u32 { + extern "C" fn exception_cleanup( + _unwind_code: uw::_Unwind_Reason_Code, + _exception: *mut uw::_Unwind_Exception, + ) { + std::process::abort(); + } + let exception = Box::new(Exception { _uwe: uw::_Unwind_Exception { - exception_class: rust_exception_class(), - exception_cleanup, + exception_class: miri_exception_class(), + exception_cleanup: Some(exception_cleanup), private: [core::ptr::null(); uw::unwinder_private_data_size], }, cause: data, }); let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception; return unsafe { uw::_Unwind_RaiseException(exception_param) as u32 }; - - extern "C" fn exception_cleanup( - _unwind_code: uw::_Unwind_Reason_Code, - _exception: *mut uw::_Unwind_Exception, - ) { - std::process::abort(); - } } pub unsafe fn rust_panic_cleanup(ptr: *mut u8) -> Box { let exception = ptr as *mut uw::_Unwind_Exception; - if (*exception).exception_class != rust_exception_class() { + if (*exception).exception_class != miri_exception_class() { std::process::abort(); } @@ -47,9 +47,10 @@ pub unsafe fn rust_panic_cleanup(ptr: *mut u8) -> Box { exception.cause } -fn rust_exception_class() -> uw::_Unwind_Exception_Class { - // M O Z \0 R U S T -- vendor, language - 0x4d4f5a_00_52555354 +fn miri_exception_class() -> uw::_Unwind_Exception_Class { + // M O Z \0 M I R I -- vendor, language + // (Miri's own exception class is just used for testing) + 0x4d4f5a_00_4d495249 } pub fn catch_unwind R>(f: F) -> Result> { @@ -63,7 +64,7 @@ pub fn catch_unwind R>(f: F) -> Result> let data_ptr = ptr::addr_of_mut!(data) as *mut u8; unsafe { - return if std::intrinsics::r#try(do_call::, data_ptr, do_catch::) == 0 { + return if std::intrinsics::catch_unwind(do_call::, data_ptr, do_catch::) == 0 { Ok(data.r.take().unwrap()) } else { Err(data.p.take().unwrap())