Skip to content

Commit 10757c7

Browse files
committed
Auto merge of #117332 - saethlin:panic-immediate-abort, r=<try>
Increase the reach of panic_immediate_abort I wanted to use/abuse this recently as part of another project, and I was surprised how many panic-related things were left in my binaries if I built a large crate with the feature enabled along with LTO. These changes get all the panic-related symbols that I could find out of my set of locally installed Rust utilities.
2 parents 7cc36de + 9faccd1 commit 10757c7

File tree

9 files changed

+84
-11
lines changed

9 files changed

+84
-11
lines changed

library/alloc/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,5 @@ compiler-builtins-c = ["compiler_builtins/c"]
3636
compiler-builtins-no-asm = ["compiler_builtins/no-asm"]
3737
compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"]
3838
compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"]
39+
# Make panics and failed asserts immediately abort without formatting any message
40+
panic_immediate_abort = []

library/alloc/src/alloc.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -377,13 +377,20 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
377377
panic!("allocation failed");
378378
}
379379

380+
#[inline]
380381
fn rt_error(layout: Layout) -> ! {
381382
unsafe {
382383
__rust_alloc_error_handler(layout.size(), layout.align());
383384
}
384385
}
385386

386-
unsafe { core::intrinsics::const_eval_select((layout,), ct_error, rt_error) }
387+
#[cfg(not(feature = "panic_immediate_abort"))]
388+
unsafe {
389+
core::intrinsics::const_eval_select((layout,), ct_error, rt_error)
390+
}
391+
392+
#[cfg(feature = "panic_immediate_abort")]
393+
ct_error(layout)
387394
}
388395

389396
// For alloc test `std::alloc::handle_alloc_error` can be used directly.

library/alloc/src/raw_vec.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
530530
// ensure that the code generation related to these panics is minimal as there's
531531
// only one location which panics rather than a bunch throughout the module.
532532
#[cfg(not(no_global_oom_handling))]
533-
#[inline(never)]
533+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
534534
fn capacity_overflow() -> ! {
535535
panic!("capacity overflow");
536536
}

library/alloc/src/vec/mod.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ impl<T, A: Allocator> Vec<T, A> {
14471447
#[stable(feature = "rust1", since = "1.0.0")]
14481448
pub fn swap_remove(&mut self, index: usize) -> T {
14491449
#[cold]
1450-
#[inline(never)]
1450+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
14511451
fn assert_failed(index: usize, len: usize) -> ! {
14521452
panic!("swap_remove index (is {index}) should be < len (is {len})");
14531453
}
@@ -1488,7 +1488,7 @@ impl<T, A: Allocator> Vec<T, A> {
14881488
#[stable(feature = "rust1", since = "1.0.0")]
14891489
pub fn insert(&mut self, index: usize, element: T) {
14901490
#[cold]
1491-
#[inline(never)]
1491+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
14921492
fn assert_failed(index: usize, len: usize) -> ! {
14931493
panic!("insertion index (is {index}) should be <= len (is {len})");
14941494
}
@@ -1549,8 +1549,7 @@ impl<T, A: Allocator> Vec<T, A> {
15491549
#[track_caller]
15501550
pub fn remove(&mut self, index: usize) -> T {
15511551
#[cold]
1552-
#[inline(never)]
1553-
#[track_caller]
1552+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
15541553
fn assert_failed(index: usize, len: usize) -> ! {
15551554
panic!("removal index (is {index}) should be < len (is {len})");
15561555
}
@@ -2148,7 +2147,7 @@ impl<T, A: Allocator> Vec<T, A> {
21482147
A: Clone,
21492148
{
21502149
#[cold]
2151-
#[inline(never)]
2150+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
21522151
fn assert_failed(at: usize, len: usize) -> ! {
21532152
panic!("`at` split index (is {at}) should be <= len (is {len})");
21542153
}

library/core/src/cell.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -755,15 +755,15 @@ impl Display for BorrowMutError {
755755
}
756756

757757
// This ensures the panicking code is outlined from `borrow_mut` for `RefCell`.
758-
#[inline(never)]
758+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
759759
#[track_caller]
760760
#[cold]
761761
fn panic_already_borrowed(err: BorrowMutError) -> ! {
762762
panic!("already borrowed: {:?}", err)
763763
}
764764

765765
// This ensures the panicking code is outlined from `borrow` for `RefCell`.
766-
#[inline(never)]
766+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
767767
#[track_caller]
768768
#[cold]
769769
fn panic_already_mutably_borrowed(err: BorrowError) -> ! {

library/core/src/panic/unwind_safe.rs

+1
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ impl<T> DerefMut for AssertUnwindSafe<T> {
267267
impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
268268
type Output = R;
269269

270+
#[inline]
270271
extern "rust-call" fn call_once(self, _args: ()) -> R {
271272
(self.0)()
272273
}

library/core/src/str/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ use iter::{MatchesInternal, SplitNInternal};
8181
#[cold]
8282
#[track_caller]
8383
#[rustc_allow_const_fn_unstable(const_eval_select)]
84+
#[cfg(not(feature = "panic_immediate_abort"))]
8485
const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
8586
// SAFETY: panics for both branches
8687
unsafe {
@@ -92,6 +93,11 @@ const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
9293
}
9394
}
9495

96+
#[cfg(feature = "panic_immediate_abort")]
97+
const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
98+
slice_error_fail_ct(s, begin, end)
99+
}
100+
95101
#[track_caller]
96102
const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! {
97103
panic!("failed to slice string");

library/std/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ llvm-libunwind = ["unwind/llvm-libunwind"]
7272
system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
7373

7474
# Make panics and failed asserts immediately abort without formatting any message
75-
panic_immediate_abort = ["core/panic_immediate_abort"]
75+
panic_immediate_abort = ["core/panic_immediate_abort", "alloc/panic_immediate_abort"]
7676

7777
# Enable std_detect default features for stdarch/crates/std_detect:
7878
# https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml

library/std/src/panicking.rs

+59-1
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,53 @@ fn default_hook(info: &PanicInfo<'_>) {
295295

296296
#[cfg(not(test))]
297297
#[doc(hidden)]
298+
#[cfg(feature = "panic_immediate_abort")]
299+
#[unstable(feature = "update_panic_count", issue = "none")]
300+
pub mod panic_count {
301+
/// A reason for forcing an immediate abort on panic.
302+
#[derive(Debug)]
303+
pub enum MustAbort {
304+
AlwaysAbort,
305+
PanicInHook,
306+
}
307+
308+
#[inline]
309+
pub fn increase(run_panic_hook: bool) -> Option<MustAbort> {
310+
None
311+
}
312+
313+
#[inline]
314+
pub fn finished_panic_hook() {}
315+
316+
#[inline]
317+
pub fn decrease() {}
318+
319+
#[inline]
320+
pub fn set_always_abort() {}
321+
322+
// Disregards ALWAYS_ABORT_FLAG
323+
#[inline]
324+
#[must_use]
325+
pub fn get_count() -> usize {
326+
0
327+
}
328+
329+
#[must_use]
330+
#[inline]
331+
pub fn count_is_zero() -> bool {
332+
true
333+
}
334+
}
335+
336+
#[cfg(not(test))]
337+
#[doc(hidden)]
338+
#[cfg(not(feature = "panic_immediate_abort"))]
298339
#[unstable(feature = "update_panic_count", issue = "none")]
299340
pub mod panic_count {
300341
use crate::cell::Cell;
301342
use crate::sync::atomic::{AtomicUsize, Ordering};
302343

303-
pub const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1);
344+
const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1);
304345

305346
/// A reason for forcing an immediate abort on panic.
306347
#[derive(Debug)]
@@ -421,6 +462,13 @@ pub mod panic_count {
421462
pub use realstd::rt::panic_count;
422463

423464
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
465+
#[cfg(feature = "panic_immediate_abort")]
466+
pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
467+
Ok(f())
468+
}
469+
470+
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
471+
#[cfg(not(feature = "panic_immediate_abort"))]
424472
pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
425473
union Data<F, R> {
426474
f: ManuallyDrop<F>,
@@ -755,6 +803,7 @@ fn rust_panic_with_hook(
755803

756804
/// This is the entry point for `resume_unwind`.
757805
/// It just forwards the payload to the panic runtime.
806+
#[cfg_attr(feature = "panic_immediate_abort", inline)]
758807
pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
759808
panic_count::increase(false);
760809

@@ -777,7 +826,16 @@ pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
777826
/// yer breakpoints.
778827
#[inline(never)]
779828
#[cfg_attr(not(test), rustc_std_internal_symbol)]
829+
#[cfg(not(feature = "panic_immediate_abort"))]
780830
fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
781831
let code = unsafe { __rust_start_panic(msg) };
782832
rtabort!("failed to initiate panic, error {code}")
783833
}
834+
835+
#[cfg_attr(not(test), rustc_std_internal_symbol)]
836+
#[cfg(feature = "panic_immediate_abort")]
837+
fn rust_panic(_: &mut dyn PanicPayload) -> ! {
838+
unsafe {
839+
crate::intrinsics::abort();
840+
}
841+
}

0 commit comments

Comments
 (0)