1//! Implementation of Rust panics via process aborts
2//!
3//! When compared to the implementation via unwinding, this crate is *much*
4//! simpler! That being said, it's not quite as versatile, but here goes!
5
6#![no_std]
7#![unstable(feature = "panic_abort", issue = "32837")]
8#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
9#![panic_runtime]
10#![feature(panic_runtime)]
11#![feature(std_internals)]
12#![feature(staged_api)]
13#![feature(rustc_attrs)]
14#![allow(internal_features)]
15
16#[cfg(target_os = "android")]
17mod android;
18
19#[cfg(target_os = "zkvm")]
20mod zkvm;
21
22use core::any::Any;
23use core::panic::PanicPayload;
24
25#[rustc_std_internal_symbol]
26#[allow(improper_ctypes_definitions)]
27pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) {
28 unreachable!()
29}
30
31// "Leak" the payload and shim to the relevant abort on the platform in question.
32#[rustc_std_internal_symbol]
33pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
34 // Android has the ability to attach a message as part of the abort.
35 #[cfg(target_os = "android")]
36 unsafe {
37 android::android_set_abort_message(_payload);
38 }
39 #[cfg(target_os = "zkvm")]
40 unsafe {
41 zkvm::zkvm_set_abort_message(_payload);
42 }
43
44 unsafe extern "Rust" {
45 // This is defined in std::rt.
46 #[rustc_std_internal_symbol]
47 safe fn __rust_abort() -> !;
48 }
49
50 __rust_abort()
51}
52
53// This... is a bit of an oddity. The tl;dr; is that this is required to link
54// correctly, the longer explanation is below.
55//
56// Right now the binaries of core/std that we ship are all compiled with
57// `-C panic=unwind`. This is done to ensure that the binaries are maximally
58// compatible with as many situations as possible. The compiler, however,
59// requires a "personality function" for all functions compiled with `-C
60// panic=unwind`. This personality function is hardcoded to the symbol
61// `rust_eh_personality` and is defined by the `eh_personality` lang item.
62//
63// So... why not just define that lang item here? Good question! The way that
64// panic runtimes are linked in is actually a little subtle in that they're
65// "sort of" in the compiler's crate store, but only actually linked if another
66// isn't actually linked. This ends up meaning that both this crate and the
67// panic_unwind crate can appear in the compiler's crate store, and if both
68// define the `eh_personality` lang item then that'll hit an error.
69//
70// To handle this the compiler only requires the `eh_personality` is defined if
71// the panic runtime being linked in is the unwinding runtime, and otherwise
72// it's not required to be defined (rightfully so). In this case, however, this
73// library just defines this symbol so there's at least some personality
74// somewhere.
75//
76// Essentially this symbol is just defined to get wired up to core/std
77// binaries, but it should never be called as we don't link in an unwinding
78// runtime at all.
79pub mod personalities {
80 // In the past this module used to contain stubs for the personality
81 // functions of various platforms, but these where removed when personality
82 // functions were moved to std.
83
84 // This corresponds to the `eh_catch_typeinfo` lang item
85 // that's only used on Emscripten currently.
86 //
87 // Since panics don't generate exceptions and foreign exceptions are
88 // currently UB with -C panic=abort (although this may be subject to
89 // change), any catch_unwind calls will never use this typeinfo.
90 #[rustc_std_internal_symbol]
91 #[allow(non_upper_case_globals)]
92 #[cfg(target_os = "emscripten")]
93 static rust_eh_catch_typeinfo: [usize; 2] = [0; 2];
94}
95