Fix Ctrl-C Handler (#2124)

* fix

* fix

* win

* win clp

* a

* FMT

* aaaaaaaaaaa

* aa

---------

Co-authored-by: Your Name <you@example.com>
This commit is contained in:
Dongjia "toka" Zhang 2024-04-30 17:18:39 +02:00 committed by GitHub
parent 61ac4ea7be
commit b23180394b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 373 additions and 274 deletions

View File

@ -50,7 +50,7 @@ use typed_builder::TypedBuilder;
use super::{hooks::EventManagerHooksTuple, CustomBufEventResult, CustomBufHandlerFn}; use super::{hooks::EventManagerHooksTuple, CustomBufEventResult, CustomBufHandlerFn};
#[cfg(any(feature = "std", feature = "adaptive_serialization"))] #[cfg(any(feature = "std", feature = "adaptive_serialization"))]
use crate::events::AdaptiveSerializer; use crate::events::AdaptiveSerializer;
#[cfg(all(unix, feature = "std"))] #[cfg(all(unix, feature = "std", not(miri)))]
use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::events::EVENTMGR_SIGHANDLER_STATE;
#[cfg(feature = "adaptive_serialization")] #[cfg(feature = "adaptive_serialization")]
use crate::observers::TimeObserver; use crate::observers::TimeObserver;
@ -1426,19 +1426,6 @@ where
S: State + HasExecutions, S: State + HasExecutions,
MT: Monitor + Clone, MT: Monitor + Clone,
{ {
/// Internal function, returns true when shuttdown is requested by a `SIGINT` signal
#[inline]
#[allow(clippy::unused_self)]
fn is_shutting_down() -> bool {
#[cfg(unix)]
unsafe {
core::ptr::read_volatile(core::ptr::addr_of!(EVENTMGR_SIGHANDLER_STATE.shutting_down))
}
#[cfg(windows)]
false
}
/// Launch the broker and the clients and fuzz /// Launch the broker and the clients and fuzz
pub fn launch(&mut self) -> Result<(Option<S>, LlmpRestartingEventManager<EMH, S, SP>), Error> { pub fn launch(&mut self) -> Result<(Option<S>, LlmpRestartingEventManager<EMH, S, SP>), Error> {
// We start ourself as child process to actually fuzz // We start ourself as child process to actually fuzz
@ -1549,15 +1536,6 @@ where
// Store the information to a map. // Store the information to a map.
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
// We setup signal handlers to clean up shmem segments used by state restorer
#[cfg(all(unix, not(miri)))]
if let Err(_e) =
unsafe { setup_signal_handler(addr_of_mut!(EVENTMGR_SIGHANDLER_STATE)) }
{
// We can live without a proper ctrl+c signal handler. Print and ignore.
log::error!("Failed to setup signal handlers: {_e}");
}
let mut ctr: u64 = 0; let mut ctr: u64 = 0;
// Client->parent loop // Client->parent loop
loop { loop {
@ -1570,31 +1548,56 @@ where
match unsafe { fork() }? { match unsafe { fork() }? {
ForkResult::Parent(handle) => { ForkResult::Parent(handle) => {
unsafe { unsafe {
EVENTMGR_SIGHANDLER_STATE.set_exit_from_main(); libc::signal(libc::SIGINT, libc::SIG_IGN);
} }
self.shmem_provider.post_fork(false)?; self.shmem_provider.post_fork(false)?;
handle.status() handle.status()
} }
ForkResult::Child => { ForkResult::Child => {
// We setup signal handlers to clean up shmem segments used by state restorer
#[cfg(all(unix, not(miri)))]
if let Err(_e) = unsafe {
setup_signal_handler(addr_of_mut!(EVENTMGR_SIGHANDLER_STATE))
} {
// We can live without a proper ctrl+c signal handler. Print and ignore.
log::error!("Failed to setup signal handlers: {_e}");
}
// println!("child {}", std::process::id());
self.shmem_provider.post_fork(true)?; self.shmem_provider.post_fork(true)?;
break (staterestorer, self.shmem_provider.clone(), core_id); break (staterestorer, self.shmem_provider.clone(), core_id);
} }
} }
}; };
#[cfg(all(unix, not(feature = "fork")))] // If this guy wants to fork, then ignore sigit
#[cfg(any(windows, not(feature = "fork")))]
unsafe { unsafe {
EVENTMGR_SIGHANDLER_STATE.set_exit_from_main(); #[cfg(windows)]
libafl_bolts::os::windows_exceptions::signal(
libafl_bolts::os::windows_exceptions::SIGINT,
libafl_bolts::os::windows_exceptions::sig_ign(),
);
#[cfg(unix)]
libc::signal(libc::SIGINT, libc::SIG_IGN);
} }
// On Windows (or in any case without fork), we spawn ourself again // On Windows (or in any case without fork), we spawn ourself again
#[cfg(any(windows, not(feature = "fork")))] #[cfg(any(windows, not(feature = "fork")))]
let child_status = startable_self()?.status()?; let child_status = startable_self()?.status()?;
#[cfg(all(unix, not(feature = "fork")))] #[cfg(any(windows, not(feature = "fork")))]
let child_status = child_status.code().unwrap_or_default(); let child_status = child_status.code().unwrap_or_default();
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
if child_status == crate::events::CTRL_C_EXIT || staterestorer.wants_to_exit() {
// if ctrl-c is pressed, we end up in this branch
if let Err(err) = mgr.detach_from_broker(self.broker_port) {
log::error!("Failed to detach from broker: {err}");
}
return Err(Error::shutting_down());
}
#[allow(clippy::manual_assert)] #[allow(clippy::manual_assert)]
if !staterestorer.has_content() && !self.serialize_state.oom_safe() { if !staterestorer.has_content() && !self.serialize_state.oom_safe() {
if let Err(err) = mgr.detach_from_broker(self.broker_port) { if let Err(err) = mgr.detach_from_broker(self.broker_port) {
@ -1608,13 +1611,6 @@ where
panic!("Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"); panic!("Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})");
} }
if staterestorer.wants_to_exit() || Self::is_shutting_down() {
// if ctrl-c is pressed, we end up in this branch
if let Err(err) = mgr.detach_from_broker(self.broker_port) {
log::error!("Failed to detach from broker: {err}");
}
return Err(Error::shutting_down());
}
ctr = ctr.wrapping_add(1); ctr = ctr.wrapping_add(1);
} }
} else { } else {

View File

@ -55,31 +55,23 @@ use crate::{
state::HasScalabilityMonitor, state::HasScalabilityMonitor,
}; };
/// The special exit code when the target exited throught ctrl-c
#[cfg(unix)]
pub const CTRL_C_EXIT: i32 = 100;
/// The special exit code when the target exited throught ctrl-c
#[cfg(windows)]
pub const CTRL_C_EXIT: i32 = -1073741510;
/// Check if ctrl-c is sent with this struct /// Check if ctrl-c is sent with this struct
#[cfg(all(unix, feature = "std"))] #[cfg(all(unix, feature = "std"))]
pub static mut EVENTMGR_SIGHANDLER_STATE: ShutdownSignalData = ShutdownSignalData { pub static mut EVENTMGR_SIGHANDLER_STATE: ShutdownSignalData = ShutdownSignalData {};
shutting_down: false,
exit_from_main: false,
};
/// A signal handler for releasing `StateRestore` `ShMem` /// A signal handler for catching ctrl-c.
/// This struct holds a pointer to `StateRestore` and clean up the `ShMem` segment used by it. /// The purpose of this signal handler is solely for calling `exit()` with a specific exit code 100
/// In this way, the restarting manager can tell that we really want to exit
#[cfg(all(unix, feature = "std"))] #[cfg(all(unix, feature = "std"))]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ShutdownSignalData { pub struct ShutdownSignalData {}
shutting_down: bool,
exit_from_main: bool,
}
#[cfg(all(unix, feature = "std"))]
impl ShutdownSignalData {
/// Set the flag to true, indicating that this process has allocated shmem
pub fn set_exit_from_main(&mut self) {
unsafe {
core::ptr::write_volatile(core::ptr::addr_of_mut!(self.exit_from_main), true);
}
}
}
/// Shutdown handler. `SigTerm`, `SigInterrupt`, `SigQuit` call this /// Shutdown handler. `SigTerm`, `SigInterrupt`, `SigQuit` call this
/// We can't handle SIGKILL in the signal handler, this means that you shouldn't kill your fuzzer with `kill -9` because then the shmem segments are never freed /// We can't handle SIGKILL in the signal handler, this means that you shouldn't kill your fuzzer with `kill -9` because then the shmem segments are never freed
@ -91,27 +83,15 @@ impl Handler for ShutdownSignalData {
_info: &mut siginfo_t, _info: &mut siginfo_t,
_context: Option<&mut ucontext_t>, _context: Option<&mut ucontext_t>,
) { ) {
/* // println!("in handler! {}", std::process::id());
println!(
"in handler! {} {}",
self.exit_from_main,
std::process::id()
);
*/
// if this process has not allocated any shmem. then simply exit()
if !self.exit_from_main {
unsafe { unsafe {
// println!("Exiting from the handler....");
#[cfg(unix)] #[cfg(unix)]
libc::_exit(0); libc::_exit(100);
#[cfg(windows)] #[cfg(windows)]
windows::Win32::System::Threading::ExitProcess(1); windows::Win32::System::Threading::ExitProcess(100);
}
}
// else wait till the next is_shutting_down() is called. then the process will exit throught main().
unsafe {
core::ptr::write_volatile(core::ptr::addr_of_mut!(self.shutting_down), true);
} }
} }

View File

@ -23,7 +23,7 @@ use libafl_bolts::{shmem::ShMemProvider, staterestore::StateRestorer};
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use super::{CustomBufEventResult, CustomBufHandlerFn, HasCustomBufHandlers, ProgressReporter}; use super::{CustomBufEventResult, CustomBufHandlerFn, HasCustomBufHandlers, ProgressReporter};
#[cfg(all(unix, feature = "std"))] #[cfg(all(unix, feature = "std", not(miri)))]
use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::events::EVENTMGR_SIGHANDLER_STATE;
use crate::{ use crate::{
events::{ events::{
@ -453,19 +453,6 @@ where
} }
} }
/// Internal function, returns true when shuttdown is requested by a `SIGINT` signal
#[inline]
#[allow(clippy::unused_self)]
fn is_shutting_down() -> bool {
#[cfg(unix)]
unsafe {
core::ptr::read_volatile(core::ptr::addr_of!(EVENTMGR_SIGHANDLER_STATE.shutting_down))
}
#[cfg(windows)]
false
}
/// Launch the simple restarting manager. /// Launch the simple restarting manager.
/// This [`EventManager`] is simple and single threaded, /// This [`EventManager`] is simple and single threaded,
/// but can still used shared maps to recover from crashes and timeouts. /// but can still used shared maps to recover from crashes and timeouts.
@ -488,15 +475,6 @@ where
//let staterestorer = { LlmpSender::new(shmem_provider.clone(), 0, false)? }; //let staterestorer = { LlmpSender::new(shmem_provider.clone(), 0, false)? };
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
// We setup signal handlers to clean up shmem segments used by state restorer
#[cfg(all(unix, not(miri)))]
if let Err(_e) =
unsafe { setup_signal_handler(addr_of_mut!(EVENTMGR_SIGHANDLER_STATE)) }
{
// We can live without a proper ctrl+c signal handler. Print and ignore.
log::error!("Failed to setup signal handlers: {_e}");
}
let mut ctr: u64 = 0; let mut ctr: u64 = 0;
// Client->parent loop // Client->parent loop
loop { loop {
@ -509,37 +487,48 @@ where
match unsafe { fork() }? { match unsafe { fork() }? {
ForkResult::Parent(handle) => { ForkResult::Parent(handle) => {
unsafe { unsafe {
// The parent will later exit through is_shutting down below libc::signal(libc::SIGINT, libc::SIG_IGN);
// if the process exits gracefully, it cleans up the shmem.
EVENTMGR_SIGHANDLER_STATE.set_exit_from_main();
} }
shmem_provider.post_fork(false)?; shmem_provider.post_fork(false)?;
handle.status() handle.status()
} }
ForkResult::Child => { ForkResult::Child => {
// We setup signal handlers to clean up shmem segments used by state restorer
#[cfg(all(unix, not(miri)))]
if let Err(_e) = unsafe {
setup_signal_handler(addr_of_mut!(EVENTMGR_SIGHANDLER_STATE))
} {
// We can live without a proper ctrl+c signal handler. Print and ignore.
log::error!("Failed to setup signal handlers: {_e}");
}
shmem_provider.post_fork(true)?; shmem_provider.post_fork(true)?;
break staterestorer; break staterestorer;
} }
} }
}; };
// Same, as fork version, mark this main thread as the shmem allocator // If this guy wants to fork, then ignore sigit
// then it will not call exit or exitprocess in the sigint handler #[cfg(any(windows, not(feature = "fork")))]
// so that it exits after cleaning up the shmem segments
#[cfg(all(unix, not(feature = "fork")))]
unsafe { unsafe {
EVENTMGR_SIGHANDLER_STATE.set_exit_from_main(); #[cfg(windows)]
libafl_bolts::os::windows_exceptions::signal(
libafl_bolts::os::windows_exceptions::SIGINT,
libafl_bolts::os::windows_exceptions::sig_ign(),
);
#[cfg(unix)]
libc::signal(libc::SIGINT, libc::SIG_IGN);
} }
// On Windows (or in any case without forks), we spawn ourself again // On Windows (or in any case without forks), we spawn ourself again
#[cfg(any(windows, not(feature = "fork")))] #[cfg(any(windows, not(feature = "fork")))]
let child_status = startable_self()?.status()?; let child_status = startable_self()?.status()?;
#[cfg(all(unix, not(feature = "fork")))] #[cfg(any(windows, not(feature = "fork")))]
let child_status = child_status.code().unwrap_or_default(); let child_status = child_status.code().unwrap_or_default();
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
if staterestorer.wants_to_exit() || Self::is_shutting_down() { if child_status == crate::events::CTRL_C_EXIT || staterestorer.wants_to_exit() {
return Err(Error::shutting_down()); return Err(Error::shutting_down());
} }

View File

@ -36,7 +36,7 @@ use tokio::{
use typed_builder::TypedBuilder; use typed_builder::TypedBuilder;
use super::{CustomBufEventResult, CustomBufHandlerFn}; use super::{CustomBufEventResult, CustomBufHandlerFn};
#[cfg(all(unix, feature = "std"))] #[cfg(all(unix, feature = "std", not(miri)))]
use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::events::EVENTMGR_SIGHANDLER_STATE;
use crate::{ use crate::{
events::{ events::{
@ -1156,19 +1156,6 @@ where
S: State + HasExecutions + HasMetadata, S: State + HasExecutions + HasMetadata,
MT: Monitor + Clone, MT: Monitor + Clone,
{ {
/// Internal function, returns true when shuttdown is requested by a `SIGINT` signal
#[inline]
#[allow(clippy::unused_self)]
fn is_shutting_down() -> bool {
#[cfg(unix)]
unsafe {
core::ptr::read_volatile(core::ptr::addr_of!(EVENTMGR_SIGHANDLER_STATE.shutting_down))
}
#[cfg(windows)]
false
}
/// Launch the restarting manager /// Launch the restarting manager
pub fn launch(&mut self) -> Result<(Option<S>, TcpRestartingEventManager<EMH, S, SP>), Error> { pub fn launch(&mut self) -> Result<(Option<S>, TcpRestartingEventManager<EMH, S, SP>), Error> {
// We start ourself as child process to actually fuzz // We start ourself as child process to actually fuzz
@ -1257,15 +1244,6 @@ where
// Store the information to a map. // Store the information to a map.
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
// We setup signal handlers to clean up shmem segments used by state restorer
#[cfg(all(unix, not(miri)))]
if let Err(_e) =
unsafe { setup_signal_handler(addr_of_mut!(EVENTMGR_SIGHANDLER_STATE)) }
{
// We can live without a proper ctrl+c signal handler. Print and ignore.
log::error!("Failed to setup signal handlers: {_e}");
}
let mut ctr: u64 = 0; let mut ctr: u64 = 0;
// Client->parent loop // Client->parent loop
loop { loop {
@ -1279,31 +1257,51 @@ where
match unsafe { fork() }? { match unsafe { fork() }? {
ForkResult::Parent(handle) => { ForkResult::Parent(handle) => {
unsafe { unsafe {
EVENTMGR_SIGHANDLER_STATE.set_exit_from_main(); libc::signal(libc::SIGINT, libc::SIG_IGN);
} }
self.shmem_provider.post_fork(false)?; self.shmem_provider.post_fork(false)?;
handle.status() handle.status()
} }
ForkResult::Child => { ForkResult::Child => {
// We setup signal handlers to clean up shmem segments used by state restorer
#[cfg(all(unix, not(miri)))]
if let Err(_e) = unsafe {
setup_signal_handler(addr_of_mut!(EVENTMGR_SIGHANDLER_STATE))
} {
// We can live without a proper ctrl+c signal handler. Print and ignore.
log::error!("Failed to setup signal handlers: {_e}");
}
self.shmem_provider.post_fork(true)?; self.shmem_provider.post_fork(true)?;
break (staterestorer, self.shmem_provider.clone(), core_id); break (staterestorer, self.shmem_provider.clone(), core_id);
} }
} }
}; };
#[cfg(all(unix, not(feature = "fork")))] // If this guy wants to fork, then ignore sigit
#[cfg(any(windows, not(feature = "fork")))]
unsafe { unsafe {
EVENTMGR_SIGHANDLER_STATE.set_exit_from_main(); #[cfg(windows)]
libafl_bolts::os::windows_exceptions::signal(
libafl_bolts::os::windows_exceptions::SIGINT,
libafl_bolts::os::windows_exceptions::sig_ign(),
);
#[cfg(unix)]
libc::signal(libc::SIGINT, libc::SIG_IGN);
} }
// On Windows (or in any case without fork), we spawn ourself again // On Windows (or in any case without fork), we spawn ourself again
#[cfg(any(windows, not(feature = "fork")))] #[cfg(any(windows, not(feature = "fork")))]
let child_status = startable_self()?.status()?; let child_status = startable_self()?.status()?;
#[cfg(all(unix, not(feature = "fork")))] #[cfg(any(windows, not(feature = "fork")))]
let child_status = child_status.code().unwrap_or_default(); let child_status = child_status.code().unwrap_or_default();
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
if child_status == crate::events::CTRL_C_EXIT || staterestorer.wants_to_exit() {
return Err(Error::shutting_down());
}
#[allow(clippy::manual_assert)] #[allow(clippy::manual_assert)]
if !staterestorer.has_content() && self.serialize_state { if !staterestorer.has_content() && self.serialize_state {
#[cfg(unix)] #[cfg(unix)]
@ -1317,10 +1315,6 @@ where
panic!("Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"); panic!("Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})");
} }
if staterestorer.wants_to_exit() || Self::is_shutting_down() {
return Err(Error::shutting_down());
}
ctr = ctr.wrapping_add(1); ctr = ctr.wrapping_add(1);
} }
} else { } else {

View File

@ -329,15 +329,14 @@ pub mod windows_exception_handler {
let mut is_crash = true; let mut is_crash = true;
#[cfg(feature = "std")] #[cfg(feature = "std")]
if let Some(exception_pointers) = exception_pointers.as_mut() { if let Some(exception_pointers) = exception_pointers.as_mut() {
let code = ExceptionCode::try_from( let code: ExceptionCode = ExceptionCode::from(
exception_pointers exception_pointers
.ExceptionRecord .ExceptionRecord
.as_mut() .as_mut()
.unwrap() .unwrap()
.ExceptionCode .ExceptionCode
.0, .0,
) );
.unwrap();
let exception_list = data.exceptions(); let exception_list = data.exceptions();
if exception_list.contains(&code) { if exception_list.contains(&code) {

View File

@ -53,7 +53,7 @@ impl ChildHandle {
unsafe { unsafe {
libc::waitpid(self.pid, &mut status, 0); libc::waitpid(self.pid, &mut status, 0);
} }
status libc::WEXITSTATUS(status)
} }
} }

View File

@ -11,7 +11,7 @@ use core::{
use std::os::raw::{c_long, c_void}; use std::os::raw::{c_long, c_void};
use log::info; use log::info;
use num_enum::TryFromPrimitive; use num_enum::FromPrimitive;
pub use windows::Win32::{ pub use windows::Win32::{
Foundation::{BOOL, NTSTATUS}, Foundation::{BOOL, NTSTATUS},
System::{ System::{
@ -94,65 +94,130 @@ pub const STATUS_SXS_EARLY_DEACTIVATION: i32 = 0xC015000F;
pub const STATUS_SXS_INVALID_DEACTIVATION: i32 = 0xC0150010; pub const STATUS_SXS_INVALID_DEACTIVATION: i32 = 0xC0150010;
pub const STATUS_NOT_IMPLEMENTED: i32 = 0xC0000002; pub const STATUS_NOT_IMPLEMENTED: i32 = 0xC0000002;
#[derive(Debug, TryFromPrimitive, Clone, Copy)] // from https://github.com/x64dbg/x64dbg/blob/4d631707b89d97e199844c08f5b65d8ea5d5d3f3/bin/exceptiondb.txt
pub const STATUS_WX86_UNSIMULATE: i32 = 0x4000001C;
pub const STATUS_WX86_CONTINUE: i32 = 0x4000001D;
pub const STATUS_WX86_SINGLE_STEP: i32 = 0x4000001E;
pub const STATUS_WX86_BREAKPOINT: i32 = 0x4000001F;
pub const STATUS_WX86_EXCEPTION_CONTINUE: i32 = 0x40000020;
pub const STATUS_WX86_EXCEPTION_LASTCHANCE: i32 = 0x40000021;
pub const STATUS_WX86_EXCEPTION_CHAIN: i32 = 0x40000022;
pub const STATUS_WX86_CREATEWX86TIB: i32 = 0x40000028;
pub const DBG_TERMINATE_THREAD: i32 = 0x40010003;
pub const DBG_TERMINATE_PROCESS: i32 = 0x40010004;
pub const DBG_CONTROL_C: i32 = 0x40010005;
pub const DBG_PRINTEXCEPTION_C: i32 = 0x40010006;
pub const DBG_RIPEXCEPTION: i32 = 0x40010007;
pub const DBG_CONTROL_BREAK: i32 = 0x40010008;
pub const DBG_COMMAND_EXCEPTION: i32 = 0x40010009;
pub const DBG_PRINTEXCEPTION_WIDE_C: i32 = 0x4001000A;
pub const EXCEPTION_RO_ORIGINATEERROR: i32 = 0x40080201;
pub const EXCEPTION_RO_TRANSFORMERROR: i32 = 0x40080202;
pub const MS_VC_EXCEPTION: i32 = 0x406D1388;
pub const DBG_EXCEPTION_NOT_HANDLED: i32 = 0x80010001;
pub const STATUS_INVALID_PARAMETER: i32 = 0xC000000D;
pub const STATUS_ILLEGAL_FLOAT_CONTEXT: i32 = 0xC000014A;
pub const EXCEPTION_POSSIBLE_DEADLOCK: i32 = 0xC0000194;
pub const STATUS_INVALID_EXCEPTION_HANDLER: i32 = 0xC00001A5;
pub const STATUS_DATATYPE_MISALIGNMENT_ERROR: i32 = 0xC00002C5;
pub const STATUS_USER_CALLBACK: i32 = 0xC000041D;
pub const CLR_EXCEPTION: i32 = 0xE0434352;
pub const CPP_EH_EXCEPTION: i32 = 0xE06D7363;
pub const VCPP_EXCEPTION_ERROR_INVALID_PARAMETER: i32 = 0xC06D0057;
pub const VCPP_EXCEPTION_ERROR_MOD_NOT_FOUND: i32 = 0xC06D007E;
pub const VCPP_EXCEPTION_ERROR_PROC_NOT_FOUND: i32 = 0xC06D007F;
#[derive(Debug, FromPrimitive, Clone, Copy)]
#[repr(i32)] #[repr(i32)]
pub enum ExceptionCode { pub enum ExceptionCode {
// From https://docs.microsoft.com/en-us/windows/win32/debug/getexceptioncode // From https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L611
AccessViolation = STATUS_ACCESS_VIOLATION, WaitZero = STATUS_WAIT_0,
ArrayBoundsExceeded = STATUS_ARRAY_BOUNDS_EXCEEDED, AbandonedWaitZero = STATUS_ABANDONED_WAIT_0,
Breakpoint = STATUS_BREAKPOINT, UserApc = STATUS_USER_APC,
DatatypeMisalignment = STATUS_DATATYPE_MISALIGNMENT,
FltDenormalOperand = STATUS_FLOAT_DENORMAL_OPERAND,
FltDivideByZero = STATUS_FLOAT_DIVIDE_BY_ZERO,
FltInexactResult = STATUS_FLOAT_INEXACT_RESULT,
FltInvalidOperation = STATUS_FLOAT_INVALID_OPERATION,
FltOverflow = STATUS_FLOAT_OVERFLOW,
FltStackCheck = STATUS_FLOAT_STACK_CHECK,
FltUnderflow = STATUS_FLOAT_UNDERFLOW,
GuardPageViolation = STATUS_GUARD_PAGE_VIOLATION,
IllegalInstruction = STATUS_ILLEGAL_INSTRUCTION,
InPageError = STATUS_IN_PAGE_ERROR,
IntegerDivideByZero = STATUS_INTEGER_DIVIDE_BY_ZERO,
IntegerOverflow = STATUS_INTEGER_OVERFLOW,
InvalidDisposition = STATUS_INVALID_DISPOSITION,
InvalidHandle = STATUS_INVALID_HANDLE,
NoncontinuableException = STATUS_NONCONTINUABLE_EXCEPTION,
PrivilegedInstruction = STATUS_PRIVILEGED_INSTRUCTION,
SingleStep = STATUS_SINGLE_STEP,
StackOverflow = STATUS_STACK_OVERFLOW,
UnwindConsolidate = STATUS_UNWIND_CONSOLIDATE,
// Addition exceptions
Wait0 = STATUS_WAIT_0,
AbandonedWait0 = STATUS_ABANDONED_WAIT_0,
UserAPC = STATUS_USER_APC,
Timeout = STATUS_TIMEOUT, Timeout = STATUS_TIMEOUT,
Pending = STATUS_PENDING, Pending = STATUS_PENDING,
SegmentNotification = STATUS_SEGMENT_NOTIFICATION, SegmentNotification = STATUS_SEGMENT_NOTIFICATION,
FatalAppExit = STATUS_FATAL_APP_EXIT, FatalAppExit = STATUS_FATAL_APP_EXIT,
GuardPageViolation = STATUS_GUARD_PAGE_VIOLATION,
DatatypeMisalignment = STATUS_DATATYPE_MISALIGNMENT,
Breakpoint = STATUS_BREAKPOINT,
SingleStep = STATUS_SINGLE_STEP,
Longjump = STATUS_LONGJUMP, Longjump = STATUS_LONGJUMP,
DLLNotFound = STATUS_DLL_NOT_FOUND, UnwindConsolidate = STATUS_UNWIND_CONSOLIDATE,
AccessViolation = STATUS_ACCESS_VIOLATION,
InPageError = STATUS_IN_PAGE_ERROR,
InvalidHandle = STATUS_INVALID_HANDLE,
NoMemory = STATUS_NO_MEMORY,
IllegalInstruction = STATUS_ILLEGAL_INSTRUCTION,
NoncontinuableException = STATUS_NONCONTINUABLE_EXCEPTION,
InvalidDisposition = STATUS_INVALID_DISPOSITION,
ArrayBoundsExceeded = STATUS_ARRAY_BOUNDS_EXCEEDED,
FloatDenormalOperand = STATUS_FLOAT_DENORMAL_OPERAND,
FloatDivideByZero = STATUS_FLOAT_DIVIDE_BY_ZERO,
FloatInexactResult = STATUS_FLOAT_INEXACT_RESULT,
FloatInvalidOperation = STATUS_FLOAT_INVALID_OPERATION,
FloatOverflow = STATUS_FLOAT_OVERFLOW,
FloatStackCheck = STATUS_FLOAT_STACK_CHECK,
FloatUnderflow = STATUS_FLOAT_UNDERFLOW,
IntegerDivideByZero = STATUS_INTEGER_DIVIDE_BY_ZERO,
IntegerOverflow = STATUS_INTEGER_OVERFLOW,
PrivilegedInstruction = STATUS_PRIVILEGED_INSTRUCTION,
StackOverflow = STATUS_STACK_OVERFLOW,
DllNotFound = STATUS_DLL_NOT_FOUND,
OrdinalNotFound = STATUS_ORDINAL_NOT_FOUND, OrdinalNotFound = STATUS_ORDINAL_NOT_FOUND,
EntryPointNotFound = STATUS_ENTRYPOINT_NOT_FOUND, EntrypointNotFound = STATUS_ENTRYPOINT_NOT_FOUND,
ControlCExit = STATUS_CONTROL_C_EXIT, ControlCExit = STATUS_CONTROL_C_EXIT,
DllInitFailed = STATUS_DLL_INIT_FAILED, DllInitFailed = STATUS_DLL_INIT_FAILED,
FltMultipleFaults = STATUS_FLOAT_MULTIPLE_FAULTS, FloatMultipleFaults = STATUS_FLOAT_MULTIPLE_FAULTS,
FltMultipleTraps = STATUS_FLOAT_MULTIPLE_TRAPS, FloatMultipleTraps = STATUS_FLOAT_MULTIPLE_TRAPS,
RegNatConsumption = STATUS_REG_NAT_CONSUMPTION, RegNatConsumption = STATUS_REG_NAT_CONSUMPTION,
HeapCorruption = STATUS_HEAP_CORRUPTION, HeapCorruption = STATUS_HEAP_CORRUPTION,
StackBufferOverrun = STATUS_STACK_BUFFER_OVERRUN, StackBufferOverrun = STATUS_STACK_BUFFER_OVERRUN,
InvalidCRuntimeParameter = STATUS_INVALID_CRUNTIME_PARAMETER, InvalidCruntimeParameter = STATUS_INVALID_CRUNTIME_PARAMETER,
AssertionFailure = STATUS_ASSERTION_FAILURE, AssertionFailure = STATUS_ASSERTION_FAILURE,
SXSEarlyDeactivation = STATUS_SXS_EARLY_DEACTIVATION, SxsEarlyDeactivation = STATUS_SXS_EARLY_DEACTIVATION,
SXSInvalidDeactivation = STATUS_SXS_INVALID_DEACTIVATION, SxsInvalidDeactivation = STATUS_SXS_INVALID_DEACTIVATION,
NotImplemented = STATUS_NOT_IMPLEMENTED, NotImplemented = STATUS_NOT_IMPLEMENTED,
#[num_enum(default)] // from https://github.com/x64dbg/x64dbg/blob/4d631707b89d97e199844c08f5b65d8ea5d5d3f3/bin/exceptiondb.txt
Other, Wx86Unsimulate = STATUS_WX86_UNSIMULATE,
Wx86Continue = STATUS_WX86_CONTINUE,
Wx86SingleStep = STATUS_WX86_SINGLE_STEP,
Wx86Breakpoint = STATUS_WX86_BREAKPOINT,
Wx86ExceptionContinue = STATUS_WX86_EXCEPTION_CONTINUE,
Wx86ExceptionLastchance = STATUS_WX86_EXCEPTION_LASTCHANCE,
Wx86ExceptionChain = STATUS_WX86_EXCEPTION_CHAIN,
Wx86Createwx86Tib = STATUS_WX86_CREATEWX86TIB,
DbgTerminateThread = DBG_TERMINATE_THREAD,
DbgTerminateProcess = DBG_TERMINATE_PROCESS,
DbgControlC = DBG_CONTROL_C,
DbgPrintexceptionC = DBG_PRINTEXCEPTION_C,
DbgRipexception = DBG_RIPEXCEPTION,
DbgControlBreak = DBG_CONTROL_BREAK,
DbgCommandException = DBG_COMMAND_EXCEPTION,
DbgPrintexceptionWideC = DBG_PRINTEXCEPTION_WIDE_C,
ExceptionRoOriginateError = EXCEPTION_RO_ORIGINATEERROR,
ExceptionRoTransformError = EXCEPTION_RO_TRANSFORMERROR,
MsVcException = MS_VC_EXCEPTION,
DbgExceptionNotHandled = DBG_EXCEPTION_NOT_HANDLED,
InvalidParameter = STATUS_INVALID_PARAMETER,
IllegalFloatContext = STATUS_ILLEGAL_FLOAT_CONTEXT,
ExceptionPossibleDeadlock = EXCEPTION_POSSIBLE_DEADLOCK,
InvalidExceptionHandler = STATUS_INVALID_EXCEPTION_HANDLER,
DatatypeMisalignmentError = STATUS_DATATYPE_MISALIGNMENT_ERROR,
UserCallback = STATUS_USER_CALLBACK,
ClrException = CLR_EXCEPTION,
CppEhException = CPP_EH_EXCEPTION,
VcppExceptionErrorInvalidParameter = VCPP_EXCEPTION_ERROR_INVALID_PARAMETER,
VcppExceptionErrorModNotFound = VCPP_EXCEPTION_ERROR_MOD_NOT_FOUND,
VcppExceptionErrorProcNotFound = VCPP_EXCEPTION_ERROR_PROC_NOT_FOUND,
#[default]
Others,
} }
pub static CRASH_EXCEPTIONS: &[ExceptionCode] = &[ pub static CRASH_EXCEPTIONS: &[ExceptionCode] = &[
ExceptionCode::AccessViolation, ExceptionCode::AccessViolation,
ExceptionCode::ArrayBoundsExceeded, ExceptionCode::ArrayBoundsExceeded,
ExceptionCode::FltDivideByZero, ExceptionCode::FloatDivideByZero,
ExceptionCode::GuardPageViolation, ExceptionCode::GuardPageViolation,
ExceptionCode::IllegalInstruction, ExceptionCode::IllegalInstruction,
ExceptionCode::InPageError, ExceptionCode::InPageError,
@ -177,111 +242,181 @@ impl Eq for ExceptionCode {}
unsafe impl Sync for ExceptionCode {} unsafe impl Sync for ExceptionCode {}
impl Display for ExceptionCode { impl Display for ExceptionCode {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
ExceptionCode::AccessViolation => write!(f, "STATUS_ACCESS_VIOLATION")?, ExceptionCode::WaitZero => write!(f, "STATUS_WAIT_0"),
ExceptionCode::ArrayBoundsExceeded => write!(f, "STATUS_ARRAY_BOUNDS_EXCEEDED")?, ExceptionCode::AbandonedWaitZero => write!(f, "STATUS_ABANDONED_WAIT_0"),
ExceptionCode::Breakpoint => write!(f, "STATUS_BREAKPOINT")?, ExceptionCode::UserApc => write!(f, "STATUS_USER_APC"),
ExceptionCode::DatatypeMisalignment => write!(f, "STATUS_DATATYPE_MISALIGNMENT")?, ExceptionCode::Timeout => write!(f, "STATUS_TIMEOUT"),
ExceptionCode::FltDenormalOperand => write!(f, "STATUS_FLOAT_DENORMAL_OPERAND")?, ExceptionCode::Pending => write!(f, "STATUS_PENDING"),
ExceptionCode::FltDivideByZero => write!(f, "STATUS_FLOAT_DIVIDE_BY_ZERO")?, ExceptionCode::SegmentNotification => write!(f, "STATUS_SEGMENT_NOTIFICATION"),
ExceptionCode::FltInexactResult => write!(f, "STATUS_FLOAT_INEXACT_RESULT")?, ExceptionCode::FatalAppExit => write!(f, "STATUS_FATAL_APP_EXIT"),
ExceptionCode::FltInvalidOperation => write!(f, "STATUS_FLOAT_INVALID_OPERATION")?, ExceptionCode::GuardPageViolation => write!(f, "STATUS_GUARD_PAGE_VIOLATION"),
ExceptionCode::FltOverflow => write!(f, "STATUS_FLOAT_OVERFLOW")?, ExceptionCode::DatatypeMisalignment => write!(f, "STATUS_DATATYPE_MISALIGNMENT"),
ExceptionCode::FltStackCheck => write!(f, "STATUS_FLOAT_STACK_CHECK")?, ExceptionCode::Breakpoint => write!(f, "STATUS_BREAKPOINT"),
ExceptionCode::FltUnderflow => write!(f, "STATUS_FLOAT_UNDERFLOW")?, ExceptionCode::SingleStep => write!(f, "STATUS_SINGLE_STEP"),
ExceptionCode::GuardPageViolation => write!(f, "STATUS_GUARD_PAGE_VIOLATION")?, ExceptionCode::Longjump => write!(f, "STATUS_LONGJUMP"),
ExceptionCode::IllegalInstruction => write!(f, "STATUS_ILLEGAL_INSTRUCTION")?, ExceptionCode::UnwindConsolidate => write!(f, "STATUS_UNWIND_CONSOLIDATE"),
ExceptionCode::InPageError => write!(f, "STATUS_IN_PAGE_ERROR")?, ExceptionCode::AccessViolation => write!(f, "STATUS_ACCESS_VIOLATION"),
ExceptionCode::IntegerDivideByZero => write!(f, "STATUS_INTEGER_DIVIDE_BY_ZERO")?, ExceptionCode::InPageError => write!(f, "STATUS_IN_PAGE_ERROR"),
ExceptionCode::IntegerOverflow => write!(f, "STATUS_INTEGER_OVERFLOW")?, ExceptionCode::InvalidHandle => write!(f, "STATUS_INVALID_HANDLE"),
ExceptionCode::InvalidDisposition => write!(f, "STATUS_INVALID_DISPOSITION")?, ExceptionCode::NoMemory => write!(f, "STATUS_NO_MEMORY"),
ExceptionCode::InvalidHandle => write!(f, "STATUS_INVALID_HANDLE")?, ExceptionCode::IllegalInstruction => write!(f, "STATUS_ILLEGAL_INSTRUCTION"),
ExceptionCode::NoncontinuableException => write!(f, "STATUS_NONCONTINUABLE_EXCEPTION")?, ExceptionCode::NoncontinuableException => write!(f, "STATUS_NONCONTINUABLE_EXCEPTION"),
ExceptionCode::PrivilegedInstruction => write!(f, "STATUS_PRIVILEGED_INSTRUCTION")?, ExceptionCode::InvalidDisposition => write!(f, "STATUS_INVALID_DISPOSITION"),
ExceptionCode::SingleStep => write!(f, "STATUS_SINGLE_STEP")?, ExceptionCode::ArrayBoundsExceeded => write!(f, "STATUS_ARRAY_BOUNDS_EXCEEDED"),
ExceptionCode::StackOverflow => write!(f, "STATUS_STACK_OVERFLOW")?, ExceptionCode::FloatDenormalOperand => write!(f, "STATUS_FLOAT_DENORMAL_OPERAND"),
ExceptionCode::UnwindConsolidate => write!(f, "STATUS_UNWIND_CONSOLIDATE")?, ExceptionCode::FloatDivideByZero => write!(f, "STATUS_FLOAT_DIVIDE_BY_ZERO"),
ExceptionCode::Wait0 => write!(f, "STATUS_WAIT_0")?, ExceptionCode::FloatInexactResult => write!(f, "STATUS_FLOAT_INEXACT_RESULT"),
ExceptionCode::AbandonedWait0 => write!(f, "STATUS_ABANDONED_WAIT_0")?, ExceptionCode::FloatInvalidOperation => write!(f, "STATUS_FLOAT_INVALID_OPERATION"),
ExceptionCode::UserAPC => write!(f, "STATUS_USER_APC")?, ExceptionCode::FloatOverflow => write!(f, "STATUS_FLOAT_OVERFLOW"),
ExceptionCode::Timeout => write!(f, "STATUS_TIMEOUT")?, ExceptionCode::FloatStackCheck => write!(f, "STATUS_FLOAT_STACK_CHECK"),
ExceptionCode::Pending => write!(f, "STATUS_PENDING")?, ExceptionCode::FloatUnderflow => write!(f, "STATUS_FLOAT_UNDERFLOW"),
ExceptionCode::SegmentNotification => write!(f, "STATUS_SEGMENT_NOTIFICATION")?, ExceptionCode::IntegerDivideByZero => write!(f, "STATUS_INTEGER_DIVIDE_BY_ZERO"),
ExceptionCode::FatalAppExit => write!(f, "STATUS_FATAL_APP_EXIT")?, ExceptionCode::IntegerOverflow => write!(f, "STATUS_INTEGER_OVERFLOW"),
ExceptionCode::Longjump => write!(f, "STATUS_LONGJUMP")?, ExceptionCode::PrivilegedInstruction => write!(f, "STATUS_PRIVILEGED_INSTRUCTION"),
ExceptionCode::DLLNotFound => write!(f, "STATUS_DLL_NOT_FOUND")?, ExceptionCode::StackOverflow => write!(f, "STATUS_STACK_OVERFLOW"),
ExceptionCode::OrdinalNotFound => write!(f, "STATUS_ORDINAL_NOT_FOUND")?, ExceptionCode::DllNotFound => write!(f, "STATUS_DLL_NOT_FOUND"),
ExceptionCode::EntryPointNotFound => write!(f, "STATUS_ENTRYPOINT_NOT_FOUND")?, ExceptionCode::OrdinalNotFound => write!(f, "STATUS_ORDINAL_NOT_FOUND"),
ExceptionCode::ControlCExit => write!(f, "STATUS_CONTROL_C_EXIT")?, ExceptionCode::EntrypointNotFound => write!(f, "STATUS_ENTRYPOINT_NOT_FOUND"),
ExceptionCode::DllInitFailed => write!(f, "STATUS_DLL_INIT_FAILED")?, ExceptionCode::ControlCExit => write!(f, "STATUS_CONTROL_C_EXIT"),
ExceptionCode::FltMultipleFaults => write!(f, "STATUS_FLOAT_MULTIPLE_FAULTS")?, ExceptionCode::DllInitFailed => write!(f, "STATUS_DLL_INIT_FAILED"),
ExceptionCode::FltMultipleTraps => write!(f, "STATUS_FLOAT_MULTIPLE_TRAPS")?, ExceptionCode::FloatMultipleFaults => write!(f, "STATUS_FLOAT_MULTIPLE_FAULTS"),
ExceptionCode::RegNatConsumption => write!(f, "STATUS_REG_NAT_CONSUMPTION")?, ExceptionCode::FloatMultipleTraps => write!(f, "STATUS_FLOAT_MULTIPLE_TRAPS"),
ExceptionCode::HeapCorruption => write!(f, "STATUS_HEAP_CORRUPTION")?, ExceptionCode::RegNatConsumption => write!(f, "STATUS_REG_NAT_CONSUMPTION"),
ExceptionCode::StackBufferOverrun => write!(f, "STATUS_STACK_BUFFER_OVERRUN")?, ExceptionCode::HeapCorruption => write!(f, "STATUS_HEAP_CORRUPTION"),
ExceptionCode::InvalidCRuntimeParameter => { ExceptionCode::StackBufferOverrun => write!(f, "STATUS_STACK_BUFFER_OVERRUN"),
write!(f, "STATUS_INVALID_CRUNTIME_PARAMETER")?; ExceptionCode::InvalidCruntimeParameter => {
write!(f, "STATUS_INVALID_CRUNTIME_PARAMETER")
}
ExceptionCode::AssertionFailure => write!(f, "STATUS_ASSERTION_FAILURE"),
ExceptionCode::SxsEarlyDeactivation => write!(f, "STATUS_SXS_EARLY_DEACTIVATION"),
ExceptionCode::SxsInvalidDeactivation => write!(f, "STATUS_SXS_INVALID_DEACTIVATION"),
ExceptionCode::NotImplemented => write!(f, "STATUS_NOT_IMPLEMENTED"),
ExceptionCode::Wx86Unsimulate => write!(f, "STATUS_WX86_UNSIMULATE"),
ExceptionCode::Wx86Continue => write!(f, "STATUS_WX86_CONTINUE"),
ExceptionCode::Wx86SingleStep => write!(f, "STATUS_WX86_SINGLE_STEP"),
ExceptionCode::Wx86Breakpoint => write!(f, "STATUS_WX86_BREAKPOINT"),
ExceptionCode::Wx86ExceptionContinue => write!(f, "STATUS_WX86_EXCEPTION_CONTINUE"),
ExceptionCode::Wx86ExceptionLastchance => write!(f, "STATUS_WX86_EXCEPTION_LASTCHANCE"),
ExceptionCode::Wx86ExceptionChain => write!(f, "STATUS_WX86_EXCEPTION_CHAIN"),
ExceptionCode::Wx86Createwx86Tib => write!(f, "STATUS_WX86_CREATEWX86TIB"),
ExceptionCode::DbgTerminateThread => write!(f, "DBG_TERMINATE_THREAD"),
ExceptionCode::DbgTerminateProcess => write!(f, "DBG_TERMINATE_PROCESS"),
ExceptionCode::DbgControlC => write!(f, "DBG_CONTROL_C"),
ExceptionCode::DbgPrintexceptionC => write!(f, "DBG_PRINTEXCEPTION_C"),
ExceptionCode::DbgRipexception => write!(f, "DBG_RIPEXCEPTION"),
ExceptionCode::DbgControlBreak => write!(f, "DBG_CONTROL_BREAK"),
ExceptionCode::DbgCommandException => write!(f, "DBG_COMMAND_EXCEPTION"),
ExceptionCode::DbgPrintexceptionWideC => write!(f, "DBG_PRINTEXCEPTION_WIDE_C"),
ExceptionCode::ExceptionRoOriginateError => write!(f, "EXCEPTION_RO_ORIGINATEERROR"),
ExceptionCode::ExceptionRoTransformError => write!(f, "EXCEPTION_RO_TRANSFORMERROR"),
ExceptionCode::MsVcException => write!(f, "MS_VC_EXCEPTION"),
ExceptionCode::DbgExceptionNotHandled => write!(f, "DBG_EXCEPTION_NOT_HANDLED"),
ExceptionCode::InvalidParameter => write!(f, "STATUS_INVALID_PARAMETER"),
ExceptionCode::IllegalFloatContext => write!(f, "STATUS_ILLEGAL_FLOAT_CONTEXT"),
ExceptionCode::ExceptionPossibleDeadlock => write!(f, "EXCEPTION_POSSIBLE_DEADLOCK"),
ExceptionCode::InvalidExceptionHandler => write!(f, "STATUS_INVALID_EXCEPTION_HANDLER"),
ExceptionCode::DatatypeMisalignmentError => {
write!(f, "STATUS_DATATYPE_MISALIGNMENT_ERROR")
}
ExceptionCode::UserCallback => write!(f, "STATUS_USER_CALLBACK"),
ExceptionCode::ClrException => write!(f, "CLR_EXCEPTION"),
ExceptionCode::CppEhException => write!(f, "CPP_EH_EXCEPTION"),
ExceptionCode::VcppExceptionErrorInvalidParameter => {
write!(f, "VCPP_EXCEPTION_ERROR_INVALID_PARAMETER")
}
ExceptionCode::VcppExceptionErrorModNotFound => {
write!(f, "VCPP_EXCEPTION_ERROR_MOD_NOT_FOUND")
}
ExceptionCode::VcppExceptionErrorProcNotFound => {
write!(f, "VCPP_EXCEPTION_ERROR_PROC_NOT_FOUND")
}
ExceptionCode::Others => write!(f, "Unknown exception code"),
} }
ExceptionCode::AssertionFailure => write!(f, "STATUS_ASSERTION_FAILURE")?,
ExceptionCode::SXSEarlyDeactivation => write!(f, "STATUS_SXS_EARLY_DEACTIVATION")?,
ExceptionCode::SXSInvalidDeactivation => write!(f, "STATUS_SXS_INVALID_DEACTIVATION")?,
ExceptionCode::NotImplemented => write!(f, "STATUS_NOT_IMPLEMENTED")?,
ExceptionCode::Other => write!(f, "Other/User defined exception")?,
};
Ok(())
} }
} }
pub static EXCEPTION_CODES_MAPPING: [ExceptionCode; 47] = [ pub static EXCEPTION_CODES_MAPPING: [ExceptionCode; 79] = [
ExceptionCode::AccessViolation, ExceptionCode::WaitZero,
ExceptionCode::ArrayBoundsExceeded, ExceptionCode::AbandonedWaitZero,
ExceptionCode::Breakpoint, ExceptionCode::UserApc,
ExceptionCode::DatatypeMisalignment,
ExceptionCode::FltDenormalOperand,
ExceptionCode::FltDivideByZero,
ExceptionCode::FltInexactResult,
ExceptionCode::FltInvalidOperation,
ExceptionCode::FltOverflow,
ExceptionCode::FltStackCheck,
ExceptionCode::FltUnderflow,
ExceptionCode::GuardPageViolation,
ExceptionCode::IllegalInstruction,
ExceptionCode::InPageError,
ExceptionCode::IntegerDivideByZero,
ExceptionCode::IntegerOverflow,
ExceptionCode::InvalidDisposition,
ExceptionCode::InvalidHandle,
ExceptionCode::NoncontinuableException,
ExceptionCode::PrivilegedInstruction,
ExceptionCode::SingleStep,
ExceptionCode::StackOverflow,
ExceptionCode::UnwindConsolidate,
ExceptionCode::Wait0,
ExceptionCode::AbandonedWait0,
ExceptionCode::UserAPC,
ExceptionCode::Timeout, ExceptionCode::Timeout,
ExceptionCode::Pending, ExceptionCode::Pending,
ExceptionCode::SegmentNotification, ExceptionCode::SegmentNotification,
ExceptionCode::FatalAppExit, ExceptionCode::FatalAppExit,
ExceptionCode::GuardPageViolation,
ExceptionCode::DatatypeMisalignment,
ExceptionCode::Breakpoint,
ExceptionCode::SingleStep,
ExceptionCode::Longjump, ExceptionCode::Longjump,
ExceptionCode::DLLNotFound, ExceptionCode::UnwindConsolidate,
ExceptionCode::AccessViolation,
ExceptionCode::InPageError,
ExceptionCode::InvalidHandle,
ExceptionCode::NoMemory,
ExceptionCode::IllegalInstruction,
ExceptionCode::NoncontinuableException,
ExceptionCode::InvalidDisposition,
ExceptionCode::ArrayBoundsExceeded,
ExceptionCode::FloatDenormalOperand,
ExceptionCode::FloatDivideByZero,
ExceptionCode::FloatInexactResult,
ExceptionCode::FloatInvalidOperation,
ExceptionCode::FloatOverflow,
ExceptionCode::FloatStackCheck,
ExceptionCode::FloatUnderflow,
ExceptionCode::IntegerDivideByZero,
ExceptionCode::IntegerOverflow,
ExceptionCode::PrivilegedInstruction,
ExceptionCode::StackOverflow,
ExceptionCode::DllNotFound,
ExceptionCode::OrdinalNotFound, ExceptionCode::OrdinalNotFound,
ExceptionCode::EntryPointNotFound, ExceptionCode::EntrypointNotFound,
ExceptionCode::ControlCExit, ExceptionCode::ControlCExit,
ExceptionCode::DllInitFailed, ExceptionCode::DllInitFailed,
ExceptionCode::FltMultipleFaults, ExceptionCode::FloatMultipleFaults,
ExceptionCode::FltMultipleTraps, ExceptionCode::FloatMultipleTraps,
ExceptionCode::RegNatConsumption, ExceptionCode::RegNatConsumption,
ExceptionCode::HeapCorruption, ExceptionCode::HeapCorruption,
ExceptionCode::StackBufferOverrun, ExceptionCode::StackBufferOverrun,
ExceptionCode::InvalidCRuntimeParameter, ExceptionCode::InvalidCruntimeParameter,
ExceptionCode::AssertionFailure, ExceptionCode::AssertionFailure,
ExceptionCode::SXSEarlyDeactivation, ExceptionCode::SxsEarlyDeactivation,
ExceptionCode::SXSInvalidDeactivation, ExceptionCode::SxsInvalidDeactivation,
ExceptionCode::NotImplemented, ExceptionCode::NotImplemented,
ExceptionCode::Other, ExceptionCode::Wx86Unsimulate,
ExceptionCode::Wx86Continue,
ExceptionCode::Wx86SingleStep,
ExceptionCode::Wx86Breakpoint,
ExceptionCode::Wx86ExceptionContinue,
ExceptionCode::Wx86ExceptionLastchance,
ExceptionCode::Wx86ExceptionChain,
ExceptionCode::Wx86Createwx86Tib,
ExceptionCode::DbgTerminateThread,
ExceptionCode::DbgTerminateProcess,
ExceptionCode::DbgControlC,
ExceptionCode::DbgPrintexceptionC,
ExceptionCode::DbgRipexception,
ExceptionCode::DbgControlBreak,
ExceptionCode::DbgCommandException,
ExceptionCode::DbgPrintexceptionWideC,
ExceptionCode::ExceptionRoOriginateError,
ExceptionCode::ExceptionRoTransformError,
ExceptionCode::MsVcException,
ExceptionCode::DbgExceptionNotHandled,
ExceptionCode::InvalidParameter,
ExceptionCode::IllegalFloatContext,
ExceptionCode::ExceptionPossibleDeadlock,
ExceptionCode::InvalidExceptionHandler,
ExceptionCode::DatatypeMisalignmentError,
ExceptionCode::UserCallback,
ExceptionCode::ClrException,
ExceptionCode::CppEhException,
ExceptionCode::VcppExceptionErrorInvalidParameter,
ExceptionCode::VcppExceptionErrorModNotFound,
ExceptionCode::VcppExceptionErrorProcNotFound,
ExceptionCode::Others,
]; ];
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
@ -361,17 +496,23 @@ pub unsafe extern "system" fn handle_exception(
.as_mut() .as_mut()
.unwrap() .unwrap()
.ExceptionCode; .ExceptionCode;
let exception_code = match ExceptionCode::try_from(code.0) { let exception_code = From::from(code.0);
Ok(x) => x,
Err(_) => ExceptionCode::Other,
};
log::info!("Received exception; code: {}", exception_code); log::info!("Received exception; code: {}", exception_code);
internal_handle_exception(exception_code, exception_pointers) internal_handle_exception(exception_code, exception_pointers)
} }
/// Return `SIGIGN` this is 1 (when represented as u64)
/// Check `https://github.com/ziglang/zig/blob/956f53beb09c07925970453d4c178c6feb53ba70/lib/libc/include/any-windows-any/signal.h#L51`
/// # Safety
/// It is just casting into another type, nothing unsafe.
#[must_use]
pub const unsafe fn sig_ign() -> NativeSignalHandlerType {
core::mem::transmute(1u64)
}
type NativeSignalHandlerType = unsafe extern "C" fn(i32); type NativeSignalHandlerType = unsafe extern "C" fn(i32);
extern "C" { extern "C" {
fn signal(signum: i32, func: NativeSignalHandlerType) -> *const c_void; pub fn signal(signum: i32, func: NativeSignalHandlerType) -> *const c_void;
} }
unsafe extern "C" fn handle_signal(_signum: i32) { unsafe extern "C" fn handle_signal(_signum: i32) {