deduplicate abort implementations
Currently, the code for process aborts is duplicated across `panic_abort` and `std`. This PR uses `#[rustc_std_internal_symbol]` to make the `std` implementation available to `panic_abort` via the linker, thereby deduplicating the code.
This commit is contained in:
parent
414482f6a0
commit
b7f2cd3a2b
11 changed files with 43 additions and 117 deletions
|
|
@ -196,7 +196,6 @@ name = "panic_abort"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ bench = false
|
|||
doc = false
|
||||
|
||||
[dependencies]
|
||||
alloc = { path = "../alloc" }
|
||||
cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
|
||||
core = { path = "../core" }
|
||||
compiler_builtins = "0.1.0"
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
libc = { version = "0.2", default-features = false }
|
||||
|
||||
[target.'cfg(any(target_os = "android", target_os = "zkvm"))'.dependencies]
|
||||
alloc = { path = "../alloc" }
|
||||
|
|
|
|||
|
|
@ -7,15 +7,11 @@
|
|||
#![unstable(feature = "panic_abort", issue = "32837")]
|
||||
#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
|
||||
#![panic_runtime]
|
||||
#![allow(unused_features)]
|
||||
#![feature(asm_experimental_arch)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(panic_runtime)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
mod android;
|
||||
|
|
@ -45,75 +41,13 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
|
|||
zkvm::zkvm_set_abort_message(_payload);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
abort();
|
||||
unsafe extern "Rust" {
|
||||
// This is defined in std::rt.
|
||||
#[rustc_std_internal_symbol]
|
||||
safe fn __rust_abort() -> !;
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(unix, target_os = "solid_asp3"))] {
|
||||
unsafe fn abort() -> ! {
|
||||
unsafe { libc::abort(); }
|
||||
}
|
||||
} else if #[cfg(any(target_os = "hermit",
|
||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
target_os = "xous",
|
||||
target_os = "uefi",
|
||||
))] {
|
||||
unsafe fn abort() -> ! {
|
||||
// call std::sys::abort_internal
|
||||
unsafe extern "C" {
|
||||
pub fn __rust_abort() -> !;
|
||||
}
|
||||
unsafe { __rust_abort(); }
|
||||
}
|
||||
} else if #[cfg(all(windows, not(miri)))] {
|
||||
// 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
|
||||
//
|
||||
// Note: this is the same implementation as in std's `abort_internal`
|
||||
unsafe fn abort() -> ! {
|
||||
#[allow(unused)]
|
||||
const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
|
||||
unsafe {
|
||||
core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
|
||||
}
|
||||
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
|
||||
unsafe {
|
||||
core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
|
||||
}
|
||||
} else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
|
||||
unsafe {
|
||||
core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
|
||||
}
|
||||
} else {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if #[cfg(target_os = "teeos")] {
|
||||
mod teeos {
|
||||
unsafe extern "C" {
|
||||
pub fn TEE_Panic(code: u32) -> !;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn abort() -> ! {
|
||||
unsafe { teeos::TEE_Panic(1); }
|
||||
}
|
||||
} else {
|
||||
unsafe fn abort() -> ! {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
__rust_abort()
|
||||
}
|
||||
|
||||
// This... is a bit of an oddity. The tl;dr; is that this is required to link
|
||||
|
|
|
|||
|
|
@ -5,20 +5,16 @@
|
|||
use alloc::boxed::Box;
|
||||
use core::any::Any;
|
||||
|
||||
unsafe extern "Rust" {
|
||||
// This is defined in std::rt
|
||||
#[rustc_std_internal_symbol]
|
||||
safe fn __rust_abort() -> !;
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
|
||||
unsafe extern "C" {
|
||||
fn __rust_abort() -> !;
|
||||
}
|
||||
unsafe {
|
||||
__rust_abort();
|
||||
}
|
||||
__rust_abort()
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
|
||||
unsafe extern "C" {
|
||||
fn __rust_abort() -> !;
|
||||
}
|
||||
unsafe {
|
||||
__rust_abort();
|
||||
}
|
||||
__rust_abort()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,13 @@ use crate::sync::Once;
|
|||
use crate::thread::{self, main_thread};
|
||||
use crate::{mem, panic, sys};
|
||||
|
||||
// This function is needed by the panic runtime.
|
||||
#[cfg(not(test))]
|
||||
#[rustc_std_internal_symbol]
|
||||
fn __rust_abort() {
|
||||
crate::process::abort();
|
||||
}
|
||||
|
||||
// Prints to the "panic output", depending on the platform this may be:
|
||||
// - the standard error output
|
||||
// - some dedicated platform specific output
|
||||
|
|
@ -47,7 +54,7 @@ macro_rules! rtabort {
|
|||
($($t:tt)*) => {
|
||||
{
|
||||
rtprintpanic!("fatal runtime error: {}, aborting\n", format_args!($($t)*));
|
||||
crate::sys::abort_internal();
|
||||
crate::process::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,15 +43,6 @@ pub fn abort_internal() -> ! {
|
|||
unsafe { hermit_abi::abort() }
|
||||
}
|
||||
|
||||
// This function is needed by the panic runtime. The symbol is named in
|
||||
// pre-link args for the target specification, so keep that in sync.
|
||||
#[cfg(not(test))]
|
||||
#[unsafe(no_mangle)]
|
||||
// NB. used by both libunwind and libpanic_abort
|
||||
pub extern "C" fn __rust_abort() {
|
||||
abort_internal();
|
||||
}
|
||||
|
||||
// SAFETY: must be called only once during runtime initialization.
|
||||
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
|
||||
|
|
|
|||
|
|
@ -112,11 +112,14 @@ pub fn abort_internal() -> ! {
|
|||
abi::usercalls::exit(true)
|
||||
}
|
||||
|
||||
// This function is needed by the panic runtime. The symbol is named in
|
||||
// This function is needed by libunwind. The symbol is named in
|
||||
// pre-link args for the target specification, so keep that in sync.
|
||||
// Note: contrary to the `__rust_abort` in `crate::rt`, this uses `no_mangle`
|
||||
// because it is actually used from C code. Because symbols annotated with
|
||||
// #[rustc_std_internal_symbol] get mangled, this will not lead to linker
|
||||
// conflicts.
|
||||
#[cfg(not(test))]
|
||||
#[unsafe(no_mangle)]
|
||||
// NB. used by both libunwind and libpanic_abort
|
||||
pub extern "C" fn __rust_abort() {
|
||||
abort_internal();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,14 +161,6 @@ pub fn abort_internal() -> ! {
|
|||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
// This function is needed by the panic runtime. The symbol is named in
|
||||
// pre-link args for the target specification, so keep that in sync.
|
||||
#[cfg(not(test))]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn __rust_abort() {
|
||||
abort_internal();
|
||||
}
|
||||
|
||||
/// Disable access to BootServices if `EVT_SIGNAL_EXIT_BOOT_SERVICES` is signaled
|
||||
extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) {
|
||||
uefi::env::disable_boot_services();
|
||||
|
|
|
|||
|
|
@ -328,8 +328,13 @@ pub fn dur2timeout(dur: Duration) -> u32 {
|
|||
|
||||
/// 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`
|
||||
/// 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
|
||||
#[cfg(not(miri))] // inline assembly does not work in Miri
|
||||
pub fn abort_internal() -> ! {
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::os::xous::ffi::exit;
|
||||
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
|
|
@ -9,3 +11,7 @@ pub mod time;
|
|||
#[path = "../unsupported/common.rs"]
|
||||
mod common;
|
||||
pub use common::*;
|
||||
|
||||
pub fn abort_internal() -> ! {
|
||||
exit(101);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,14 +62,6 @@ mod c_compat {
|
|||
}
|
||||
exit(unsafe { main() });
|
||||
}
|
||||
|
||||
// This function is needed by the panic runtime. The symbol is named in
|
||||
// pre-link args for the target specification, so keep that in sync.
|
||||
#[unsafe(no_mangle)]
|
||||
// NB. used by both libunwind and libpanic_abort
|
||||
pub extern "C" fn __rust_abort() -> ! {
|
||||
exit(101);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn errno() -> i32 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue