panic.rs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. use alloc::boxed::Box;
  2. use core::any::Any;
  3. use core::mem::MaybeUninit;
  4. use crate::abi::*;
  5. #[cfg(feature = "panic-handler")]
  6. pub use crate::panic_handler::*;
  7. use crate::panicking::Exception;
  8. static CANARY: u8 = 0;
  9. #[repr(transparent)]
  10. struct RustPanic(Box<dyn Any + Send>, DropGuard);
  11. struct DropGuard;
  12. impl Drop for DropGuard {
  13. fn drop(&mut self) {
  14. #[cfg(feature = "panic-handler")]
  15. {
  16. drop_panic();
  17. }
  18. crate::util::abort();
  19. }
  20. }
  21. #[repr(C)]
  22. struct ExceptionWithPayload {
  23. exception: MaybeUninit<UnwindException>,
  24. // See rust/library/panic_unwind/src/gcc.rs for the canary values
  25. canary: *const u8,
  26. payload: RustPanic,
  27. }
  28. unsafe impl Exception for RustPanic {
  29. const CLASS: [u8; 8] = *b"MOZ\0RUST";
  30. fn wrap(this: Self) -> *mut UnwindException {
  31. Box::into_raw(Box::new(ExceptionWithPayload {
  32. exception: MaybeUninit::uninit(),
  33. canary: &CANARY,
  34. payload: this,
  35. })) as *mut UnwindException
  36. }
  37. unsafe fn unwrap(ex: *mut UnwindException) -> Self {
  38. let ex = ex as *mut ExceptionWithPayload;
  39. let canary = unsafe { core::ptr::addr_of!((*ex).canary).read() };
  40. if !core::ptr::eq(canary, &CANARY) {
  41. // This is a Rust exception but not generated by us.
  42. #[cfg(feature = "panic-handler")]
  43. {
  44. foreign_exception();
  45. }
  46. crate::util::abort();
  47. }
  48. let ex = unsafe { Box::from_raw(ex) };
  49. ex.payload
  50. }
  51. }
  52. pub fn begin_panic(payload: Box<dyn Any + Send>) -> UnwindReasonCode {
  53. crate::panicking::begin_panic(RustPanic(payload, DropGuard))
  54. }
  55. pub fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
  56. #[cold]
  57. fn process_panic(p: Option<RustPanic>) -> Box<dyn Any + Send> {
  58. match p {
  59. None => {
  60. #[cfg(feature = "panic-handler")]
  61. {
  62. foreign_exception();
  63. }
  64. crate::util::abort();
  65. }
  66. Some(e) => {
  67. #[cfg(feature = "panic-handler")]
  68. {
  69. panic_caught();
  70. }
  71. core::mem::forget(e.1);
  72. e.0
  73. }
  74. }
  75. }
  76. crate::panicking::catch_unwind(f).map_err(process_panic)
  77. }