Panic utilities
This commit is contained in:
parent
487ca98456
commit
af031eb4b1
@ -21,6 +21,7 @@ hide-trace = []
|
|||||||
personality = []
|
personality = []
|
||||||
personality-dummy = []
|
personality-dummy = []
|
||||||
print = ["libc"]
|
print = ["libc"]
|
||||||
|
panic = ["alloc"]
|
||||||
system-alloc = []
|
system-alloc = []
|
||||||
default = ["dwarf-expr", "hide-trace", "fde-phdr", "fde-registry"]
|
default = ["dwarf-expr", "hide-trace", "fde-phdr", "fde-registry"]
|
||||||
|
|
||||||
|
17
src/abi.rs
17
src/abi.rs
@ -10,7 +10,7 @@ use crate::util::*;
|
|||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct UnwindReasonCode(c_int);
|
pub struct UnwindReasonCode(pub c_int);
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
impl UnwindReasonCode {
|
impl UnwindReasonCode {
|
||||||
@ -27,7 +27,7 @@ impl UnwindReasonCode {
|
|||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct UnwindAction(c_int);
|
pub struct UnwindAction(pub c_int);
|
||||||
|
|
||||||
impl UnwindAction {
|
impl UnwindAction {
|
||||||
pub const SEARCH_PHASE: Self = Self(1);
|
pub const SEARCH_PHASE: Self = Self(1);
|
||||||
@ -78,6 +78,19 @@ pub struct UnwindException {
|
|||||||
private_unused: [usize; Arch::UNWIND_PRIVATE_DATA_SIZE - 2],
|
private_unused: [usize; Arch::UNWIND_PRIVATE_DATA_SIZE - 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UnwindException {
|
||||||
|
#[inline]
|
||||||
|
pub fn new() -> UnwindException {
|
||||||
|
UnwindException {
|
||||||
|
exception_class: 0,
|
||||||
|
exception_cleanup: None,
|
||||||
|
private_1: None,
|
||||||
|
private_2: 0,
|
||||||
|
private_unused: [0; Arch::UNWIND_PRIVATE_DATA_SIZE - 2],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type UnwindTraceFn =
|
pub type UnwindTraceFn =
|
||||||
unsafe extern "C" fn(ctx: &mut UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode;
|
unsafe extern "C" fn(ctx: &mut UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
any(feature = "personality", feature = "personality-dummy"),
|
any(feature = "personality", feature = "personality-dummy"),
|
||||||
feature(lang_items)
|
feature(lang_items)
|
||||||
)]
|
)]
|
||||||
|
#![cfg_attr(feature = "panic", feature(core_intrinsics))]
|
||||||
#![warn(rust_2018_idioms)]
|
#![warn(rust_2018_idioms)]
|
||||||
#![warn(unsafe_op_in_unsafe_fn)]
|
#![warn(unsafe_op_in_unsafe_fn)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
@ -12,7 +13,8 @@
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
mod abi;
|
pub mod abi;
|
||||||
|
|
||||||
mod arch;
|
mod arch;
|
||||||
mod find_fde;
|
mod find_fde;
|
||||||
mod frame;
|
mod frame;
|
||||||
@ -26,7 +28,8 @@ mod personality;
|
|||||||
#[cfg(feature = "personality-dummy")]
|
#[cfg(feature = "personality-dummy")]
|
||||||
mod personality_dummy;
|
mod personality_dummy;
|
||||||
|
|
||||||
|
#[cfg(feature = "panic")]
|
||||||
|
pub mod panic;
|
||||||
|
|
||||||
#[cfg(feature = "system-alloc")]
|
#[cfg(feature = "system-alloc")]
|
||||||
mod system_alloc;
|
mod system_alloc;
|
||||||
|
|
||||||
pub use abi::*;
|
|
||||||
|
86
src/panic.rs
Normal file
86
src/panic.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
use alloc::boxed::Box;
|
||||||
|
use core::any::Any;
|
||||||
|
use core::mem::ManuallyDrop;
|
||||||
|
|
||||||
|
use crate::abi::*;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct Exception {
|
||||||
|
exception: UnwindException,
|
||||||
|
payload: Box<dyn Any + Send>,
|
||||||
|
}
|
||||||
|
|
||||||
|
const RUST_EXCEPTION_CLASS: u64 = u64::from_be_bytes(*b"MOZ\0RUST");
|
||||||
|
|
||||||
|
pub fn begin_panic(payload: Box<dyn Any + Send>) -> UnwindReasonCode {
|
||||||
|
unsafe extern "C" fn exception_cleanup(
|
||||||
|
_unwind_code: UnwindReasonCode,
|
||||||
|
exception: *mut UnwindException,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
let _ = Box::from_raw(exception as *mut Exception);
|
||||||
|
}
|
||||||
|
core::intrinsics::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut unwind_ex = UnwindException::new();
|
||||||
|
unwind_ex.exception_class = RUST_EXCEPTION_CLASS;
|
||||||
|
unwind_ex.exception_cleanup = Some(exception_cleanup);
|
||||||
|
let exception = Box::new(Exception {
|
||||||
|
exception: unwind_ex,
|
||||||
|
payload,
|
||||||
|
});
|
||||||
|
_Unwind_RaiseException(unsafe { &mut *(Box::into_raw(exception) as *mut UnwindException) })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cold]
|
||||||
|
unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send + 'static> {
|
||||||
|
let exception = payload as *mut UnwindException;
|
||||||
|
if unsafe { (*exception).exception_class } != RUST_EXCEPTION_CLASS {
|
||||||
|
unsafe { _Unwind_DeleteException(exception) };
|
||||||
|
core::intrinsics::abort();
|
||||||
|
}
|
||||||
|
let unwind_ex = unsafe { Box::from_raw(exception as *mut Exception) };
|
||||||
|
unwind_ex.payload
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
|
||||||
|
union Data<F, R> {
|
||||||
|
f: ManuallyDrop<F>,
|
||||||
|
r: ManuallyDrop<R>,
|
||||||
|
p: ManuallyDrop<Box<dyn Any + Send>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut data = Data {
|
||||||
|
f: ManuallyDrop::new(f),
|
||||||
|
};
|
||||||
|
|
||||||
|
let data_ptr = &mut data as *mut _ as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
return if core::intrinsics::r#try(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
|
||||||
|
Ok(ManuallyDrop::into_inner(data.r))
|
||||||
|
} else {
|
||||||
|
Err(ManuallyDrop::into_inner(data.p))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
|
||||||
|
unsafe {
|
||||||
|
let data = data as *mut Data<F, R>;
|
||||||
|
let data = &mut (*data);
|
||||||
|
let f = ManuallyDrop::take(&mut data.f);
|
||||||
|
data.r = ManuallyDrop::new(f());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn do_catch<F: FnOnce() -> R, R>(data: *mut u8, payload: *mut u8) {
|
||||||
|
unsafe {
|
||||||
|
let data = data as *mut Data<F, R>;
|
||||||
|
let data = &mut (*data);
|
||||||
|
let obj = cleanup(payload);
|
||||||
|
data.p = ManuallyDrop::new(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user