From 57572cf8096ccb332370f7a711641a061bfd7434 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Mon, 10 Aug 2020 14:08:31 +0200 Subject: [PATCH 1/3] Call into fastfail on abort in libpanic_abort on Windows x86(_64) --- library/panic_abort/src/lib.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index cf52091f609ed..339be6111aa61 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -17,6 +17,7 @@ #![feature(panic_runtime)] #![feature(staged_api)] #![feature(rustc_attrs)] +#![feature(llvm_asm)] use core::any::Any; @@ -55,6 +56,19 @@ pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 { } __rust_abort(); } + } else if #[cfg(all(windows, any(target_arch = "x86", target_arch = "x86_64")))] { + // On Windows, use the processor-specific __fastfail mechanism. In Windows 8 + // and later, this will terminate the process immediately without running any + // in-process exception handlers. In earlier versions of Windows, this + // sequence of instructions will be treated as an access violation, + // terminating the process but without necessarily bypassing all exception + // handlers. + // + // https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail + unsafe fn abort() -> ! { + llvm_asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT + core::intrinsics::unreachable(); + } } else { unsafe fn abort() -> ! { core::intrinsics::abort(); From 6778baf516cf00d6ba2d3f448aa312b4ac2e43b5 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Mon, 10 Aug 2020 17:39:06 +0200 Subject: [PATCH 2/3] Fix up docs --- library/panic_abort/src/lib.rs | 17 +++++------------ library/std/src/sys/windows/mod.rs | 18 +++++++++--------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index 339be6111aa61..ccc067a3c943d 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -27,16 +27,7 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen unreachable!() } -// "Leak" the payload and shim to the relevant abort on the platform in -// question. -// -// For Unix we just use `abort` from libc as it'll trigger debuggers, core -// dumps, etc, as one might expect. On Windows, however, the best option we have -// is the `__fastfail` intrinsics, but that's unfortunately not defined in LLVM, -// and the `RaiseFailFastException` function isn't available until Windows 7 -// which would break compat with XP. For now just use `intrinsics::abort` which -// will kill us with an illegal instruction, which will do a good enough job for -// now hopefully. +// "Leak" the payload and shim to the relevant abort on the platform in question. #[rustc_std_internal_symbol] pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 { abort(); @@ -57,14 +48,16 @@ pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 { __rust_abort(); } } else if #[cfg(all(windows, any(target_arch = "x86", target_arch = "x86_64")))] { - // On Windows, use the processor-specific __fastfail mechanism. In Windows 8 + // On Windows, use the processor-specific __fastfail mechanism. In Windows 8 // and later, this will terminate the process immediately without running any - // in-process exception handlers. In earlier versions of Windows, this + // in-process exception handlers. In earlier versions of Windows, this // sequence of instructions will be treated as an access violation, // terminating the process but without necessarily bypassing all exception // handlers. // // https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail + // + // Note: this is the same implementation as in libstd's `abort_internal` unsafe fn abort() -> ! { llvm_asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT core::intrinsics::unreachable(); diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index 982ec912c44b7..4334447b8b1da 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -281,7 +281,11 @@ macro_rules! impl_is_zero { impl_is_zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } pub fn cvt(i: I) -> crate::io::Result { - if i.is_zero() { Err(crate::io::Error::last_os_error()) } else { Ok(i) } + if i.is_zero() { + Err(crate::io::Error::last_os_error()) + } else { + Ok(i) + } } pub fn dur2timeout(dur: Duration) -> c::DWORD { @@ -300,14 +304,10 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD { .unwrap_or(c::INFINITE) } -// On Windows, use the processor-specific __fastfail mechanism. In Windows 8 -// and later, this will terminate the process immediately without running any -// in-process exception handlers. In earlier versions of Windows, this -// sequence of instructions will be treated as an access violation, -// terminating the process but without necessarily bypassing all exception -// handlers. -// -// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail +/// Use `__fastfail` to abort the process +/// +/// This is the same implementation as in libpanic_abort's `__rust_start_panic`. See +/// that function for more information on `__fastfail` #[allow(unreachable_code)] pub fn abort_internal() -> ! { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] From b9b8b5c96b60789b6b7846a4036d3cbf2d393014 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Mon, 10 Aug 2020 18:04:44 +0200 Subject: [PATCH 3/3] Reverse formatting --- library/std/src/sys/windows/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index 4334447b8b1da..a0d5a7471d8af 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -281,11 +281,7 @@ macro_rules! impl_is_zero { impl_is_zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } pub fn cvt(i: I) -> crate::io::Result { - if i.is_zero() { - Err(crate::io::Error::last_os_error()) - } else { - Ok(i) - } + if i.is_zero() { Err(crate::io::Error::last_os_error()) } else { Ok(i) } } pub fn dur2timeout(dur: Duration) -> c::DWORD {