panic_unwind: Apply unsafe_op_in_unsafe_fn
This commit is contained in:
parent
e13928de93
commit
331911e699
6 changed files with 110 additions and 89 deletions
|
@ -71,42 +71,46 @@ pub(crate) unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
|
|||
ptr: *mut u8,
|
||||
is_rust_panic: bool,
|
||||
}
|
||||
let catch_data = &*(ptr as *mut CatchData);
|
||||
unsafe {
|
||||
let catch_data = &*(ptr as *mut CatchData);
|
||||
|
||||
let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception;
|
||||
if !catch_data.is_rust_panic {
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception;
|
||||
if !catch_data.is_rust_panic {
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
|
||||
let canary = (&raw const (*adjusted_ptr).canary).read();
|
||||
if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) {
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
let canary = (&raw const (*adjusted_ptr).canary).read();
|
||||
if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) {
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
|
||||
let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::Relaxed);
|
||||
if was_caught {
|
||||
// Since cleanup() isn't allowed to panic, we just abort instead.
|
||||
intrinsics::abort();
|
||||
let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::Relaxed);
|
||||
if was_caught {
|
||||
// Since cleanup() isn't allowed to panic, we just abort instead.
|
||||
intrinsics::abort();
|
||||
}
|
||||
let out = (*adjusted_ptr).data.take().unwrap();
|
||||
__cxa_end_catch();
|
||||
out
|
||||
}
|
||||
let out = (*adjusted_ptr).data.take().unwrap();
|
||||
__cxa_end_catch();
|
||||
out
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
|
||||
let exception = __cxa_allocate_exception(mem::size_of::<Exception>()) as *mut Exception;
|
||||
if exception.is_null() {
|
||||
return uw::_URC_FATAL_PHASE1_ERROR as u32;
|
||||
unsafe {
|
||||
let exception = __cxa_allocate_exception(mem::size_of::<Exception>()) as *mut Exception;
|
||||
if exception.is_null() {
|
||||
return uw::_URC_FATAL_PHASE1_ERROR as u32;
|
||||
}
|
||||
ptr::write(
|
||||
exception,
|
||||
Exception {
|
||||
canary: &EXCEPTION_TYPE_INFO,
|
||||
caught: AtomicBool::new(false),
|
||||
data: Some(data),
|
||||
},
|
||||
);
|
||||
__cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup);
|
||||
}
|
||||
ptr::write(
|
||||
exception,
|
||||
Exception {
|
||||
canary: &EXCEPTION_TYPE_INFO,
|
||||
caught: AtomicBool::new(false),
|
||||
data: Some(data),
|
||||
},
|
||||
);
|
||||
__cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup);
|
||||
}
|
||||
|
||||
extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> *mut libc::c_void {
|
||||
|
|
|
@ -69,7 +69,7 @@ pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
|
|||
cause: data,
|
||||
});
|
||||
let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception;
|
||||
return uw::_Unwind_RaiseException(exception_param) as u32;
|
||||
return unsafe { uw::_Unwind_RaiseException(exception_param) as u32 };
|
||||
|
||||
extern "C" fn exception_cleanup(
|
||||
_unwind_code: uw::_Unwind_Reason_Code,
|
||||
|
@ -83,26 +83,28 @@ pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
|
|||
}
|
||||
|
||||
pub(crate) unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
|
||||
let exception = ptr as *mut uw::_Unwind_Exception;
|
||||
if (*exception).exception_class != RUST_EXCEPTION_CLASS {
|
||||
uw::_Unwind_DeleteException(exception);
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
unsafe {
|
||||
let exception = ptr as *mut uw::_Unwind_Exception;
|
||||
if (*exception).exception_class != RUST_EXCEPTION_CLASS {
|
||||
uw::_Unwind_DeleteException(exception);
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
|
||||
let exception = exception.cast::<Exception>();
|
||||
// Just access the canary field, avoid accessing the entire `Exception` as
|
||||
// it can be a foreign Rust exception.
|
||||
let canary = (&raw const (*exception).canary).read();
|
||||
if !ptr::eq(canary, &CANARY) {
|
||||
// A foreign Rust exception, treat it slightly differently from other
|
||||
// foreign exceptions, because call into `_Unwind_DeleteException` will
|
||||
// call into `__rust_drop_panic` which produces a confusing
|
||||
// "Rust panic must be rethrown" message.
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
let exception = exception.cast::<Exception>();
|
||||
// Just access the canary field, avoid accessing the entire `Exception` as
|
||||
// it can be a foreign Rust exception.
|
||||
let canary = (&raw const (*exception).canary).read();
|
||||
if !ptr::eq(canary, &CANARY) {
|
||||
// A foreign Rust exception, treat it slightly differently from other
|
||||
// foreign exceptions, because call into `_Unwind_DeleteException` will
|
||||
// call into `__rust_drop_panic` which produces a confusing
|
||||
// "Rust panic must be rethrown" message.
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
|
||||
let exception = Box::from_raw(exception as *mut Exception);
|
||||
exception.cause
|
||||
let exception = Box::from_raw(exception as *mut Exception);
|
||||
exception.cause
|
||||
}
|
||||
}
|
||||
|
||||
// Rust's exception class identifier. This is used by personality routines to
|
||||
|
|
|
@ -9,12 +9,16 @@ pub(crate) unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
|
|||
unsafe extern "C" {
|
||||
fn __rust_abort() -> !;
|
||||
}
|
||||
__rust_abort();
|
||||
unsafe {
|
||||
__rust_abort();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
|
||||
unsafe extern "C" {
|
||||
fn __rust_abort() -> !;
|
||||
}
|
||||
__rust_abort();
|
||||
unsafe {
|
||||
__rust_abort();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#![allow(internal_features)]
|
||||
#![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))]
|
||||
#![warn(unreachable_pub)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::any::Any;
|
||||
|
@ -87,14 +88,16 @@ unsafe extern "C" {
|
|||
#[rustc_std_internal_symbol]
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) {
|
||||
Box::into_raw(imp::cleanup(payload))
|
||||
unsafe { Box::into_raw(imp::cleanup(payload)) }
|
||||
}
|
||||
|
||||
// Entry point for raising an exception, just delegates to the platform-specific
|
||||
// implementation.
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32 {
|
||||
let payload = Box::from_raw(payload.take_box());
|
||||
unsafe {
|
||||
let payload = Box::from_raw(payload.take_box());
|
||||
|
||||
imp::panic(payload)
|
||||
imp::panic(payload)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@ pub(crate) unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 {
|
|||
// The payload we pass to `miri_start_unwind` will be exactly the argument we get
|
||||
// in `cleanup` below. So we just box it up once, to get something pointer-sized.
|
||||
let payload_box: Payload = Box::new(payload);
|
||||
miri_start_unwind(Box::into_raw(payload_box) as *mut u8)
|
||||
unsafe { miri_start_unwind(Box::into_raw(payload_box) as *mut u8) }
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> {
|
||||
// Recover the underlying `Box`.
|
||||
let payload_box: Payload = Box::from_raw(payload_box as *mut _);
|
||||
let payload_box: Payload = unsafe { Box::from_raw(payload_box as *mut _) };
|
||||
*payload_box
|
||||
}
|
||||
|
|
|
@ -268,9 +268,11 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
|
|||
macro_rules! define_cleanup {
|
||||
($abi:tt $abi2:tt) => {
|
||||
unsafe extern $abi fn exception_cleanup(e: *mut Exception) {
|
||||
if let Exception { data: Some(b), .. } = e.read() {
|
||||
drop(b);
|
||||
super::__rust_drop_panic();
|
||||
unsafe {
|
||||
if let Exception { data: Some(b), .. } = e.read() {
|
||||
drop(b);
|
||||
super::__rust_drop_panic();
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe extern $abi2 fn exception_copy(
|
||||
|
@ -322,45 +324,51 @@ pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
|
|||
//
|
||||
// In any case, we basically need to do something like this until we can
|
||||
// express more operations in statics (and we may never be able to).
|
||||
atomic_store_seqcst(
|
||||
(&raw mut THROW_INFO.pmfnUnwind).cast(),
|
||||
ptr_t::new(exception_cleanup as *mut u8).raw(),
|
||||
);
|
||||
atomic_store_seqcst(
|
||||
(&raw mut THROW_INFO.pCatchableTypeArray).cast(),
|
||||
ptr_t::new((&raw mut CATCHABLE_TYPE_ARRAY).cast()).raw(),
|
||||
);
|
||||
atomic_store_seqcst(
|
||||
(&raw mut CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[0]).cast(),
|
||||
ptr_t::new((&raw mut CATCHABLE_TYPE).cast()).raw(),
|
||||
);
|
||||
atomic_store_seqcst(
|
||||
(&raw mut CATCHABLE_TYPE.pType).cast(),
|
||||
ptr_t::new((&raw mut TYPE_DESCRIPTOR).cast()).raw(),
|
||||
);
|
||||
atomic_store_seqcst(
|
||||
(&raw mut CATCHABLE_TYPE.copyFunction).cast(),
|
||||
ptr_t::new(exception_copy as *mut u8).raw(),
|
||||
);
|
||||
unsafe {
|
||||
atomic_store_seqcst(
|
||||
(&raw mut THROW_INFO.pmfnUnwind).cast(),
|
||||
ptr_t::new(exception_cleanup as *mut u8).raw(),
|
||||
);
|
||||
atomic_store_seqcst(
|
||||
(&raw mut THROW_INFO.pCatchableTypeArray).cast(),
|
||||
ptr_t::new((&raw mut CATCHABLE_TYPE_ARRAY).cast()).raw(),
|
||||
);
|
||||
atomic_store_seqcst(
|
||||
(&raw mut CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[0]).cast(),
|
||||
ptr_t::new((&raw mut CATCHABLE_TYPE).cast()).raw(),
|
||||
);
|
||||
atomic_store_seqcst(
|
||||
(&raw mut CATCHABLE_TYPE.pType).cast(),
|
||||
ptr_t::new((&raw mut TYPE_DESCRIPTOR).cast()).raw(),
|
||||
);
|
||||
atomic_store_seqcst(
|
||||
(&raw mut CATCHABLE_TYPE.copyFunction).cast(),
|
||||
ptr_t::new(exception_copy as *mut u8).raw(),
|
||||
);
|
||||
}
|
||||
|
||||
unsafe extern "system-unwind" {
|
||||
fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8) -> !;
|
||||
}
|
||||
|
||||
_CxxThrowException(throw_ptr, (&raw mut THROW_INFO) as *mut _);
|
||||
unsafe {
|
||||
_CxxThrowException(throw_ptr, (&raw mut THROW_INFO) as *mut _);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> {
|
||||
// A null payload here means that we got here from the catch (...) of
|
||||
// __rust_try. This happens when a non-Rust foreign exception is caught.
|
||||
if payload.is_null() {
|
||||
super::__rust_foreign_exception();
|
||||
unsafe {
|
||||
// A null payload here means that we got here from the catch (...) of
|
||||
// __rust_try. This happens when a non-Rust foreign exception is caught.
|
||||
if payload.is_null() {
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
let exception = payload as *mut Exception;
|
||||
let canary = (&raw const (*exception).canary).read();
|
||||
if !core::ptr::eq(canary, &raw const TYPE_DESCRIPTOR) {
|
||||
// A foreign Rust exception.
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
(*exception).data.take().unwrap()
|
||||
}
|
||||
let exception = payload as *mut Exception;
|
||||
let canary = (&raw const (*exception).canary).read();
|
||||
if !core::ptr::eq(canary, &raw const TYPE_DESCRIPTOR) {
|
||||
// A foreign Rust exception.
|
||||
super::__rust_foreign_exception();
|
||||
}
|
||||
(*exception).data.take().unwrap()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue