From fa22863f1b13251014c5cae1532c96582749978f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 28 Apr 2024 18:20:40 +0200 Subject: [PATCH] Fix unwinding on 32-bit watchOS ARM The code is written in a way to support 32-bit iOS and tvOS ARM devices, for future compatibility even though we currently only have a target for 32-bit iOS ARM. --- library/std/src/sys/personality/dwarf/eh.rs | 9 +++++++- library/std/src/sys/personality/gcc.rs | 5 +++-- library/unwind/src/libunwind.rs | 24 ++++++++++----------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs index 3f3615ea3e0a4..ff88ef4e0e1d0 100644 --- a/library/std/src/sys/personality/dwarf/eh.rs +++ b/library/std/src/sys/personality/dwarf/eh.rs @@ -54,7 +54,14 @@ pub enum EHAction { Terminate, } -pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm")); +/// 32-bit Apple ARM uses SjLj exceptions, except for watchOS. +/// +/// I.e. iOS and tvOS, as those are the only Apple OSes that used 32-bit ARM +/// devices. +/// +/// +pub const USING_SJLJ_EXCEPTIONS: bool = + cfg!(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm")); pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result { if lsda.is_null() { diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index b0f744dd96605..0dc53550ca943 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -92,11 +92,12 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c cfg_if::cfg_if! { - if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "visionos"), not(target_os = "netbsd")))] { + if #[cfg(all(not(all(target_vendor = "apple", not(target_os = "watchos"))), target_arch = "arm", not(target_os = "netbsd")))] { // ARM EHABI personality routine. // https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf // - // iOS uses the default routine instead since it uses SjLj unwinding. + // Apple 32-bit ARM (but not watchOS) uses the default routine instead + // since it uses SjLj unwinding. #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( state: uw::_Unwind_State, diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index e34e73a351637..e5e28f32e4dbf 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -33,10 +33,10 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(all(target_arch = "x86_64", target_os = "windows"))] pub const unwinder_private_data_size: usize = 6; -#[cfg(all(target_arch = "arm", not(any(target_os = "ios", target_os = "watchos"))))] +#[cfg(all(target_arch = "arm", not(all(target_vendor = "apple", not(target_os = "watchos")))))] pub const unwinder_private_data_size: usize = 20; -#[cfg(all(target_arch = "arm", any(target_os = "ios", target_os = "watchos")))] +#[cfg(all(target_arch = "arm", all(target_vendor = "apple", not(target_os = "watchos"))))] pub const unwinder_private_data_size: usize = 5; #[cfg(all(target_arch = "aarch64", target_pointer_width = "64", not(target_os = "windows")))] @@ -123,7 +123,7 @@ extern "C" { } cfg_if::cfg_if! { -if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos", target_os = "netbsd", not(target_arch = "arm")))] { +if #[cfg(any(all(target_vendor = "apple", not(target_os = "watchos")), target_os = "netbsd", not(target_arch = "arm")))] { // Not ARM EHABI #[repr(C)] #[derive(Copy, Clone, PartialEq)] @@ -258,8 +258,15 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe } // cfg_if! cfg_if::cfg_if! { -if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { - // Not 32-bit iOS +if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm"))] { + // 32-bit ARM Apple (except for watchOS) uses SjLj and does not provide + // _Unwind_Backtrace() + extern "C-unwind" { + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + } + + pub use _Unwind_SjLj_RaiseException as _Unwind_RaiseException; +} else { #[cfg_attr( all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") @@ -276,13 +283,6 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { trace_argument: *mut c_void) -> _Unwind_Reason_Code; } -} else { - // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace() - extern "C-unwind" { - pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; - } - - pub use _Unwind_SjLj_RaiseException as _Unwind_RaiseException; } } // cfg_if!