Skip to content

Commit c078244

Browse files
committed
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.
1 parent 928468c commit c078244

File tree

11 files changed

+43
-117
lines changed

11 files changed

+43
-117
lines changed

library/Cargo.lock

-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,6 @@ name = "panic_abort"
203203
version = "0.0.0"
204204
dependencies = [
205205
"alloc",
206-
"cfg-if",
207206
"compiler_builtins",
208207
"core",
209208
"libc",

library/panic_abort/Cargo.toml

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ bench = false
1212
doc = false
1313

1414
[dependencies]
15-
alloc = { path = "../alloc" }
16-
cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
1715
core = { path = "../core" }
1816
compiler_builtins = "0.1.0"
1917

20-
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
18+
[target.'cfg(target_os = "android")'.dependencies]
2119
libc = { version = "0.2", default-features = false }
20+
21+
[target.'cfg(any(target_os = "android", target_os = "zkvm"))'.dependencies]
22+
alloc = { path = "../alloc" }

library/panic_abort/src/lib.rs

+5-71
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@
77
#![unstable(feature = "panic_abort", issue = "32837")]
88
#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
99
#![panic_runtime]
10-
#![allow(unused_features)]
11-
#![feature(asm_experimental_arch)]
12-
#![feature(core_intrinsics)]
1310
#![feature(panic_runtime)]
1411
#![feature(std_internals)]
1512
#![feature(staged_api)]
1613
#![feature(rustc_attrs)]
1714
#![allow(internal_features)]
18-
#![deny(unsafe_op_in_unsafe_fn)]
1915

2016
#[cfg(target_os = "android")]
2117
mod android;
@@ -45,75 +41,13 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
4541
zkvm::zkvm_set_abort_message(_payload);
4642
}
4743

48-
unsafe {
49-
abort();
44+
unsafe extern "Rust" {
45+
// This is defined in std::rt.
46+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
47+
safe fn __rust_abort() -> !;
5048
}
5149

52-
cfg_if::cfg_if! {
53-
if #[cfg(any(unix, target_os = "solid_asp3"))] {
54-
unsafe fn abort() -> ! {
55-
unsafe { libc::abort(); }
56-
}
57-
} else if #[cfg(any(target_os = "hermit",
58-
all(target_vendor = "fortanix", target_env = "sgx"),
59-
target_os = "xous",
60-
target_os = "uefi",
61-
))] {
62-
unsafe fn abort() -> ! {
63-
// call std::sys::abort_internal
64-
unsafe extern "C" {
65-
pub fn __rust_abort() -> !;
66-
}
67-
unsafe { __rust_abort(); }
68-
}
69-
} else if #[cfg(all(windows, not(miri)))] {
70-
// On Windows, use the processor-specific __fastfail mechanism. In Windows 8
71-
// and later, this will terminate the process immediately without running any
72-
// in-process exception handlers. In earlier versions of Windows, this
73-
// sequence of instructions will be treated as an access violation,
74-
// terminating the process but without necessarily bypassing all exception
75-
// handlers.
76-
//
77-
// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
78-
//
79-
// Note: this is the same implementation as in std's `abort_internal`
80-
unsafe fn abort() -> ! {
81-
#[allow(unused)]
82-
const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
83-
cfg_if::cfg_if! {
84-
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
85-
unsafe {
86-
core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
87-
}
88-
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
89-
unsafe {
90-
core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
91-
}
92-
} else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
93-
unsafe {
94-
core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
95-
}
96-
} else {
97-
core::intrinsics::abort();
98-
}
99-
}
100-
}
101-
} else if #[cfg(target_os = "teeos")] {
102-
mod teeos {
103-
unsafe extern "C" {
104-
pub fn TEE_Panic(code: u32) -> !;
105-
}
106-
}
107-
108-
unsafe fn abort() -> ! {
109-
unsafe { teeos::TEE_Panic(1); }
110-
}
111-
} else {
112-
unsafe fn abort() -> ! {
113-
core::intrinsics::abort();
114-
}
115-
}
116-
}
50+
__rust_abort()
11751
}
11852

11953
// This... is a bit of an oddity. The tl;dr; is that this is required to link

library/panic_unwind/src/hermit.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,16 @@
55
use alloc::boxed::Box;
66
use core::any::Any;
77

8+
unsafe extern "Rust" {
9+
// This is defined in std::rt
10+
#[rustc_std_internal_symbol]
11+
safe fn __rust_abort() -> !;
12+
}
13+
814
pub(crate) unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
9-
unsafe extern "C" {
10-
fn __rust_abort() -> !;
11-
}
12-
unsafe {
13-
__rust_abort();
14-
}
15+
__rust_abort()
1516
}
1617

1718
pub(crate) unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
18-
unsafe extern "C" {
19-
fn __rust_abort() -> !;
20-
}
21-
unsafe {
22-
__rust_abort();
23-
}
19+
__rust_abort()
2420
}

library/std/src/rt.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ use crate::sync::Once;
2626
use crate::thread::{self, main_thread};
2727
use crate::{mem, panic, sys};
2828

29+
// This function is needed by the panic runtime.
30+
#[cfg(not(test))]
31+
#[rustc_std_internal_symbol]
32+
fn __rust_abort() {
33+
crate::process::abort();
34+
}
35+
2936
// Prints to the "panic output", depending on the platform this may be:
3037
// - the standard error output
3138
// - some dedicated platform specific output
@@ -47,7 +54,7 @@ macro_rules! rtabort {
4754
($($t:tt)*) => {
4855
{
4956
rtprintpanic!("fatal runtime error: {}\n", format_args!($($t)*));
50-
crate::sys::abort_internal();
57+
crate::process::abort();
5158
}
5259
}
5360
}

library/std/src/sys/pal/hermit/mod.rs

-9
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ pub fn abort_internal() -> ! {
4646
unsafe { hermit_abi::abort() }
4747
}
4848

49-
// This function is needed by the panic runtime. The symbol is named in
50-
// pre-link args for the target specification, so keep that in sync.
51-
#[cfg(not(test))]
52-
#[unsafe(no_mangle)]
53-
// NB. used by both libunwind and libpanic_abort
54-
pub extern "C" fn __rust_abort() {
55-
abort_internal();
56-
}
57-
5849
// SAFETY: must be called only once during runtime initialization.
5950
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
6051
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {

library/std/src/sys/pal/sgx/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,14 @@ pub fn abort_internal() -> ! {
115115
abi::usercalls::exit(true)
116116
}
117117

118-
// This function is needed by the panic runtime. The symbol is named in
118+
// This function is needed by libunwind. The symbol is named in
119119
// pre-link args for the target specification, so keep that in sync.
120+
// Note: contrary to the `__rust_abort` in `crate::rt`, this uses `no_mangle`
121+
// because it is actually used from C code. Because symbols annotated with
122+
// #[rustc_std_internal_symbol] get mangled, this will not lead to linker
123+
// conflicts.
120124
#[cfg(not(test))]
121125
#[unsafe(no_mangle)]
122-
// NB. used by both libunwind and libpanic_abort
123126
pub extern "C" fn __rust_abort() {
124127
abort_internal();
125128
}

library/std/src/sys/pal/uefi/mod.rs

-8
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,6 @@ pub fn abort_internal() -> ! {
163163
core::intrinsics::abort();
164164
}
165165

166-
// This function is needed by the panic runtime. The symbol is named in
167-
// pre-link args for the target specification, so keep that in sync.
168-
#[cfg(not(test))]
169-
#[unsafe(no_mangle)]
170-
pub extern "C" fn __rust_abort() {
171-
abort_internal();
172-
}
173-
174166
/// Disable access to BootServices if `EVT_SIGNAL_EXIT_BOOT_SERVICES` is signaled
175167
extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) {
176168
uefi::env::disable_boot_services();

library/std/src/sys/pal/windows/mod.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,13 @@ pub fn dur2timeout(dur: Duration) -> u32 {
330330

331331
/// Use `__fastfail` to abort the process
332332
///
333-
/// This is the same implementation as in libpanic_abort's `__rust_start_panic`. See
334-
/// that function for more information on `__fastfail`
333+
/// In Windows 8 and later, this will terminate the process immediately without
334+
/// running any in-process exception handlers. In earlier versions of Windows,
335+
/// this sequence of instructions will be treated as an access violation,
336+
/// terminating the process but without necessarily bypassing all exception
337+
/// handlers.
338+
///
339+
/// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
335340
#[cfg(not(miri))] // inline assembly does not work in Miri
336341
pub fn abort_internal() -> ! {
337342
unsafe {

library/std/src/sys/pal/xous/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![forbid(unsafe_op_in_unsafe_fn)]
22

3+
use crate::os::xous::ffi::exit;
4+
35
pub mod args;
46
#[path = "../unsupported/env.rs"]
57
pub mod env;
@@ -12,3 +14,7 @@ pub mod time;
1214
#[path = "../unsupported/common.rs"]
1315
mod common;
1416
pub use common::*;
17+
18+
pub fn abort_internal() -> ! {
19+
exit(101);
20+
}

library/std/src/sys/pal/xous/os.rs

-8
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,6 @@ mod c_compat {
6464
}
6565
exit(unsafe { main() });
6666
}
67-
68-
// This function is needed by the panic runtime. The symbol is named in
69-
// pre-link args for the target specification, so keep that in sync.
70-
#[unsafe(no_mangle)]
71-
// NB. used by both libunwind and libpanic_abort
72-
pub extern "C" fn __rust_abort() -> ! {
73-
exit(101);
74-
}
7567
}
7668

7769
pub fn errno() -> i32 {

0 commit comments

Comments
 (0)