crash_handler/
windows.rs

1pub mod jmp;
2mod signal;
3mod state;
4
5use crate::Error;
6
7/// Possible exception codes values for the the `exception_code` field
8/// in the crash context.
9///
10/// This is mainly for testing purposes, and is not exhaustive nor really accurate,
11/// as eg. a distinction is made between a divide by zero between integers and
12/// floats.
13#[derive(Copy, Clone)]
14#[repr(i32)]
15#[allow(overflowing_literals)]
16pub enum ExceptionCode {
17    Abort = 0x40000015,             // STATUS_FATAL_APP_EXIT
18    Fpe = -1073741676,              // EXCEPTION_INT_DIVIDE_BY_ZERO
19    Illegal = -1073741795,          // EXCEPTION_ILLEGAL_INSTRUCTION
20    Segv = -1073741819,             // EXCEPTION_ACCESS_VIOLATION
21    StackOverflow = -1073741571,    // EXCEPTION_STACK_OVERFLOW
22    Trap = -2147483645,             // EXCEPTION_BREAKPOINT
23    InvalidParameter = -1073741811, // STATUS_INVALID_PARAMETER
24    Purecall = -1073741787,         // STATUS_NONCONTINUABLE_EXCEPTION
25    User = 0xcca11ed, // https://github.com/chromium/crashpad/blob/fca8871ca3fb721d3afab370ca790122f9333bfd/util/win/exception_codes.h#L32
26    HeapCorruption = 0xc0000374, // STATUS_HEAP_CORRUPTION
27}
28
29/// A Windows exception handler
30pub struct CrashHandler;
31
32#[allow(clippy::unused_self)]
33impl CrashHandler {
34    /// Attaches the crash handler.
35    ///
36    /// The provided callback will be invoked if an exception is caught,
37    /// providing a [`crate::CrashContext`] with the details of the thread where
38    /// the exception was thrown.
39    pub fn attach(on_crash: Box<dyn crate::CrashEvent>) -> Result<Self, Error> {
40        state::attach(on_crash)?;
41        Ok(Self)
42    }
43
44    /// Detaches this handler, removing it from the handler stack.
45    ///
46    /// This is done automatically when this [`CrashHandler`] is dropped.
47    #[inline]
48    pub fn detach(self) {
49        state::detach();
50    }
51
52    /// Creates an exception with the specified exception code that is passed
53    /// through the user provided callback.
54    pub fn simulate_exception(&self, exception_code: Option<i32>) -> crate::CrashEventResult {
55        // Normally this would be an unsafe function, since this unsafe encompasses
56        // the entirety of the body, however the user is really not required to
57        // uphold any guarantees on their end, so no real need to declare the
58        // function itself unsafe.
59        unsafe { state::simulate_exception(exception_code) }
60    }
61}
62
63impl Drop for CrashHandler {
64    fn drop(&mut self) {
65        state::detach();
66    }
67}