Skip to content

Commit 9fb091d

Browse files
committed
Auto merge of rust-lang#86155 - alexcrichton:abort-on-unwind, r=nikomatsakis
rustc: Fill out remaining parts of C-unwind ABI This commit intends to fill out some of the remaining pieces of the C-unwind ABI. This has a number of other changes with it though to move this design space forward a bit. Notably contained within here is: * On `panic=unwind`, the `extern "C"` ABI is now considered as "may unwind". This fixes a longstanding soundness issue where if you `panic!()` in an `extern "C"` function defined in Rust that's actually UB because the LLVM representation for the function has the `nounwind` attribute, but then you unwind. * Whether or not a function unwinds now mainly considers the ABI of the function instead of first checking the panic strategy. This fixes a miscompile of `extern "C-unwind"` with `panic=abort` because that ABI can still unwind. * The aborting stub for non-unwinding ABIs with `panic=unwind` has been reimplemented. Previously this was done as a small tweak during MIR generation, but this has been moved to a separate and dedicated MIR pass. This new pass will, for appropriate functions and function calls, insert a `cleanup` landing pad for any function call that may unwind within a function that is itself not allowed to unwind. Note that this subtly changes some behavior from before where previously on an unwind which was caught-to-abort it would run active destructors in the function, and now it simply immediately aborts the process. * The `#[unwind]` attribute has been removed and all users in tests and such are now using `C-unwind` and `#![feature(c_unwind)]`. I think this is largely the last piece of the RFC to implement. Unfortunately I believe this is still not stabilizable as-is because activating the feature gate changes the behavior of the existing `extern "C"` ABI in a way that has no replacement. My thinking for how to enable this is that we add support for the `C-unwind` ABI on stable Rust first, and then after it hits stable we change the behavior of the `C` ABI. That way anyone straddling stable/beta/nightly can switch to `C-unwind` safely.
2 parents 9971e56 + cb57a68 commit 9fb091d

File tree

7 files changed

+19
-21
lines changed

7 files changed

+19
-21
lines changed

core/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@
147147
#![feature(try_blocks)]
148148
#![feature(unboxed_closures)]
149149
#![feature(unsized_fn_params)]
150-
#![feature(unwind_attributes)]
151150
#![feature(variant_count)]
152151
#![feature(tbm_target_feature)]
153152
#![feature(sse4a_target_feature)]

panic_unwind/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
#![feature(panic_unwind)]
2121
#![feature(staged_api)]
2222
#![feature(std_internals)]
23-
#![feature(unwind_attributes)]
2423
#![feature(abi_thiscall)]
2524
#![feature(rustc_attrs)]
2625
#![panic_runtime]
2726
#![feature(panic_runtime)]
27+
#![feature(c_unwind)]
2828
// `real_imp` is unused with Miri, so silence warnings.
2929
#![cfg_attr(miri, allow(dead_code))]
3030

@@ -98,8 +98,7 @@ pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any
9898
// Entry point for raising an exception, just delegates to the platform-specific
9999
// implementation.
100100
#[rustc_std_internal_symbol]
101-
#[unwind(allowed)]
102-
pub unsafe extern "C" fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 {
101+
pub unsafe extern "C-unwind" fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 {
103102
let payload = Box::from_raw((*payload).take_box());
104103

105104
imp::panic(payload)

panic_unwind/src/seh.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,14 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
233233
// support capturing exceptions with std::exception_ptr, which we can't support
234234
// because Box<dyn Any> isn't clonable.
235235
macro_rules! define_cleanup {
236-
($abi:tt) => {
236+
($abi:tt $abi2:tt) => {
237237
unsafe extern $abi fn exception_cleanup(e: *mut Exception) {
238238
if let Exception { data: Some(b) } = e.read() {
239239
drop(b);
240240
super::__rust_drop_panic();
241241
}
242242
}
243-
#[unwind(allowed)]
244-
unsafe extern $abi fn exception_copy(_dest: *mut Exception,
243+
unsafe extern $abi2 fn exception_copy(_dest: *mut Exception,
245244
_src: *mut Exception)
246245
-> *mut Exception {
247246
panic!("Rust panics cannot be copied");
@@ -250,9 +249,9 @@ macro_rules! define_cleanup {
250249
}
251250
cfg_if::cfg_if! {
252251
if #[cfg(target_arch = "x86")] {
253-
define_cleanup!("thiscall");
252+
define_cleanup!("thiscall" "thiscall-unwind");
254253
} else {
255-
define_cleanup!("C");
254+
define_cleanup!("C" "C-unwind");
256255
}
257256
}
258257

@@ -307,8 +306,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
307306
ptr!(exception_copy) as u32,
308307
);
309308

310-
extern "system" {
311-
#[unwind(allowed)]
309+
extern "system-unwind" {
312310
fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8) -> !;
313311
}
314312

std/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@
235235
#![feature(auto_traits)]
236236
#![feature(bench_black_box)]
237237
#![feature(box_syntax)]
238+
#![feature(c_unwind)]
238239
#![feature(c_variadic)]
239240
#![feature(cfg_accessible)]
240241
#![feature(cfg_eval)]
@@ -327,7 +328,6 @@
327328
#![feature(try_reserve)]
328329
#![feature(unboxed_closures)]
329330
#![feature(unsafe_cell_raw_get)]
330-
#![feature(unwind_attributes)]
331331
#![feature(unwrap_infallible)]
332332
#![feature(vec_into_raw_parts)]
333333
#![feature(vec_spare_capacity)]

std/src/panicking.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ use realstd::io::set_output_capture;
4343
#[allow(improper_ctypes)]
4444
extern "C" {
4545
fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
46+
}
4647

48+
#[allow(improper_ctypes)]
49+
extern "C-unwind" {
4750
/// `payload` is passed through another layer of raw pointers as `&mut dyn Trait` is not
4851
/// FFI-safe. `BoxMeUp` lazily performs allocation only when needed (this avoids allocations
4952
/// when using the "abort" panic runtime).
50-
#[unwind(allowed)]
5153
fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32;
5254
}
5355

@@ -460,7 +462,6 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>) -> ! {
460462

461463
/// Entry point of panics from the libcore crate (`panic_impl` lang item).
462464
#[cfg_attr(not(test), panic_handler)]
463-
#[unwind(allowed)]
464465
pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
465466
struct PanicPayload<'a> {
466467
inner: &'a fmt::Arguments<'a>,

unwind/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#![feature(link_cfg)]
44
#![feature(nll)]
55
#![feature(staged_api)]
6-
#![feature(unwind_attributes)]
76
#![feature(static_nobundle)]
7+
#![feature(c_unwind)]
88
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
99

1010
cfg_if::cfg_if! {

unwind/src/libunwind.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,10 @@ pub type _Unwind_Exception_Cleanup_Fn =
8181
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
8282
link(name = "unwind", kind = "static")
8383
)]
84-
extern "C" {
85-
#[unwind(allowed)]
84+
extern "C-unwind" {
8685
pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
86+
}
87+
extern "C" {
8788
pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
8889
pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
8990
pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
@@ -230,9 +231,10 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
230231
#[cfg_attr(all(feature = "llvm-libunwind",
231232
any(target_os = "fuchsia", target_os = "linux")),
232233
link(name = "unwind", kind = "static"))]
233-
extern "C" {
234-
#[unwind(allowed)]
234+
extern "C-unwind" {
235235
pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
236+
}
237+
extern "C" {
236238
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
237239
trace_argument: *mut c_void)
238240
-> _Unwind_Reason_Code;
@@ -242,8 +244,7 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
242244
#[cfg_attr(all(feature = "llvm-libunwind",
243245
any(target_os = "fuchsia", target_os = "linux")),
244246
link(name = "unwind", kind = "static"))]
245-
extern "C" {
246-
#[unwind(allowed)]
247+
extern "C-unwind" {
247248
pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
248249
}
249250

0 commit comments

Comments
 (0)