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:
parent
61ac4ea7be
commit
b23180394b
@ -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 {
|
||||||
|
@ -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 {
|
|
||||||
#[cfg(unix)]
|
|
||||||
libc::_exit(0);
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
windows::Win32::System::Threading::ExitProcess(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// else wait till the next is_shutting_down() is called. then the process will exit throught main().
|
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::write_volatile(core::ptr::addr_of_mut!(self.shutting_down), true);
|
// println!("Exiting from the handler....");
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
libc::_exit(100);
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
windows::Win32::System::Threading::ExitProcess(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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::AssertionFailure => write!(f, "STATUS_ASSERTION_FAILURE"),
|
||||||
ExceptionCode::SXSEarlyDeactivation => write!(f, "STATUS_SXS_EARLY_DEACTIVATION")?,
|
ExceptionCode::SxsEarlyDeactivation => write!(f, "STATUS_SXS_EARLY_DEACTIVATION"),
|
||||||
ExceptionCode::SXSInvalidDeactivation => write!(f, "STATUS_SXS_INVALID_DEACTIVATION")?,
|
ExceptionCode::SxsInvalidDeactivation => write!(f, "STATUS_SXS_INVALID_DEACTIVATION"),
|
||||||
ExceptionCode::NotImplemented => write!(f, "STATUS_NOT_IMPLEMENTED")?,
|
ExceptionCode::NotImplemented => write!(f, "STATUS_NOT_IMPLEMENTED"),
|
||||||
ExceptionCode::Other => write!(f, "Other/User defined exception")?,
|
ExceptionCode::Wx86Unsimulate => write!(f, "STATUS_WX86_UNSIMULATE"),
|
||||||
};
|
ExceptionCode::Wx86Continue => write!(f, "STATUS_WX86_CONTINUE"),
|
||||||
|
ExceptionCode::Wx86SingleStep => write!(f, "STATUS_WX86_SINGLE_STEP"),
|
||||||
Ok(())
|
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"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user