12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- use alloc::boxed::Box;
- use core::any::Any;
- use core::mem::MaybeUninit;
- use crate::abi::*;
- #[cfg(feature = "panic-handler")]
- pub use crate::panic_handler::*;
- use crate::panicking::Exception;
- static CANARY: u8 = 0;
- #[repr(transparent)]
- struct RustPanic(Box<dyn Any + Send>, DropGuard);
- struct DropGuard;
- impl Drop for DropGuard {
- fn drop(&mut self) {
- #[cfg(feature = "panic-handler")]
- {
- drop_panic();
- }
- crate::util::abort();
- }
- }
- #[repr(C)]
- struct ExceptionWithPayload {
- exception: MaybeUninit<UnwindException>,
- // See rust/library/panic_unwind/src/gcc.rs for the canary values
- canary: *const u8,
- payload: RustPanic,
- }
- unsafe impl Exception for RustPanic {
- const CLASS: [u8; 8] = *b"MOZ\0RUST";
- fn wrap(this: Self) -> *mut UnwindException {
- Box::into_raw(Box::new(ExceptionWithPayload {
- exception: MaybeUninit::uninit(),
- canary: &CANARY,
- payload: this,
- })) as *mut UnwindException
- }
- unsafe fn unwrap(ex: *mut UnwindException) -> Self {
- let ex = ex as *mut ExceptionWithPayload;
- let canary = unsafe { core::ptr::addr_of!((*ex).canary).read() };
- if !core::ptr::eq(canary, &CANARY) {
- // This is a Rust exception but not generated by us.
- #[cfg(feature = "panic-handler")]
- {
- foreign_exception();
- }
- crate::util::abort();
- }
- let ex = unsafe { Box::from_raw(ex) };
- ex.payload
- }
- }
- pub fn begin_panic(payload: Box<dyn Any + Send>) -> UnwindReasonCode {
- crate::panicking::begin_panic(RustPanic(payload, DropGuard))
- }
- pub fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
- #[cold]
- fn process_panic(p: Option<RustPanic>) -> Box<dyn Any + Send> {
- match p {
- None => {
- #[cfg(feature = "panic-handler")]
- {
- foreign_exception();
- }
- crate::util::abort();
- }
- Some(e) => {
- #[cfg(feature = "panic-handler")]
- {
- panic_caught();
- }
- core::mem::forget(e.1);
- e.0
- }
- }
- }
- crate::panicking::catch_unwind(f).map_err(process_panic)
- }
|