diff --git a/core/src/char/mod.rs b/core/src/char/mod.rs index 3c641a2e01c93..37c27ecb8c4d6 100644 --- a/core/src/char/mod.rs +++ b/core/src/char/mod.rs @@ -24,6 +24,8 @@ mod convert; mod decode; mod methods; +// stable re-exports +#[rustfmt::skip] #[stable(feature = "try_from", since = "1.34.0")] pub use self::convert::CharTryFromError; #[stable(feature = "char_from_str", since = "1.20.0")] @@ -31,11 +33,14 @@ pub use self::convert::ParseCharError; #[stable(feature = "decode_utf16", since = "1.9.0")] pub use self::decode::{DecodeUtf16, DecodeUtf16Error}; +// perma-unstable re-exports +#[rustfmt::skip] #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] pub use self::methods::encode_utf16_raw; // perma-unstable #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] pub use self::methods::encode_utf8_raw; // perma-unstable +#[rustfmt::skip] use crate::ascii; use crate::error::Error; use crate::escape; diff --git a/core/src/ffi/c_str.rs b/core/src/ffi/c_str.rs index c9111254082da..ae42ae3baf418 100644 --- a/core/src/ffi/c_str.rs +++ b/core/src/ffi/c_str.rs @@ -94,7 +94,7 @@ use crate::str; /// ``` /// /// [str]: prim@str "str" -#[derive(Hash)] +#[derive(PartialEq, Eq, Hash)] #[stable(feature = "core_c_str", since = "1.64.0")] #[rustc_has_incoherent_inherent_impls] #[lang = "CStr"] @@ -104,7 +104,6 @@ use crate::str; // want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under // `cfg(doc)`. This is an ad-hoc implementation of attribute privacy. #[repr(transparent)] -#[allow(clippy::derived_hash_with_manual_eq)] pub struct CStr { // FIXME: this should not be represented with a DST slice but rather with // just a raw `c_char` along with some form of marker to make @@ -678,15 +677,9 @@ impl CStr { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for CStr { - #[inline] - fn eq(&self, other: &CStr) -> bool { - self.to_bytes().eq(other.to_bytes()) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for CStr {} +// `.to_bytes()` representations are compared instead of the inner `[c_char]`s, +// because `c_char` is `i8` (not `u8`) on some platforms. +// That is why this is implemented manually and not derived. #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for CStr { #[inline] diff --git a/core/src/intrinsics/simd.rs b/core/src/intrinsics/simd.rs index 30734c020b39b..0c21e6f31a827 100644 --- a/core/src/intrinsics/simd.rs +++ b/core/src/intrinsics/simd.rs @@ -243,18 +243,6 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn simd_shuffle(x: T, y: T, idx: U) -> V; - /// Shuffle two vectors by const indices. - /// - /// `T` must be a vector. - /// - /// `U` must be a vector with the same element type as `T` and the same length as `IDX`. - /// - /// Returns a new vector such that element `i` is selected from `xy[IDX[i]]`, where `xy` - /// is the concatenation of `x` and `y`. It is a compile-time error if `IDX[i]` is out-of-bounds - /// of `xy`. - #[rustc_nounwind] - pub fn simd_shuffle_generic(x: T, y: T) -> U; - /// Read a vector of pointers. /// /// `T` must be a vector. diff --git a/core/src/lib.rs b/core/src/lib.rs index 0ec46412e9522..02cb02dce1d87 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -249,7 +249,6 @@ #![feature(transparent_unions)] #![feature(try_blocks)] #![feature(unboxed_closures)] -#![feature(unsized_const_params)] #![feature(unsized_fn_params)] #![feature(with_negative_coherence)] // tidy-alphabetical-end diff --git a/core/src/marker.rs b/core/src/marker.rs index a87528033c03b..cf428e36ea7a0 100644 --- a/core/src/marker.rs +++ b/core/src/marker.rs @@ -42,6 +42,8 @@ use crate::hash::Hasher; /// } /// ``` #[unstable(feature = "internal_impls_macro", issue = "none")] +// Allow implementations of `UnsizedConstParamTy` even though std cannot use that feature. +#[allow_internal_unstable(unsized_const_params)] macro marker_impls { ( $(#[$($meta:tt)*])* $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => { $(#[$($meta)*])* impl< $($($bounds)*)? > $Trait for $T {} diff --git a/core/src/unicode/mod.rs b/core/src/unicode/mod.rs index 5ddd9f7476dd8..6066aa9921607 100644 --- a/core/src/unicode/mod.rs +++ b/core/src/unicode/mod.rs @@ -1,13 +1,15 @@ #![unstable(feature = "unicode_internals", issue = "none")] #![allow(missing_docs)] -// The `pub use` ones are for use in alloc, and are not re-exported in std. - -pub(crate) use unicode_data::alphabetic::lookup as Alphabetic; +// for use in alloc, not re-exported in std. +#[rustfmt::skip] pub use unicode_data::case_ignorable::lookup as Case_Ignorable; pub use unicode_data::cased::lookup as Cased; -pub(crate) use unicode_data::cc::lookup as Cc; pub use unicode_data::conversions; + +#[rustfmt::skip] +pub(crate) use unicode_data::alphabetic::lookup as Alphabetic; +pub(crate) use unicode_data::cc::lookup as Cc; pub(crate) use unicode_data::grapheme_extend::lookup as Grapheme_Extend; pub(crate) use unicode_data::lowercase::lookup as Lowercase; pub(crate) use unicode_data::n::lookup as N; diff --git a/core/tests/ffi.rs b/core/tests/ffi.rs new file mode 100644 index 0000000000000..2b33fbd95f073 --- /dev/null +++ b/core/tests/ffi.rs @@ -0,0 +1 @@ +mod cstr; diff --git a/core/tests/ffi/cstr.rs b/core/tests/ffi/cstr.rs new file mode 100644 index 0000000000000..9bf4c21a9ab97 --- /dev/null +++ b/core/tests/ffi/cstr.rs @@ -0,0 +1,15 @@ +use core::ffi::CStr; + +#[test] +fn compares_as_u8s() { + let a: &CStr = c"Hello!"; // Starts with ascii + let a_bytes: &[u8] = a.to_bytes(); + assert!((..0b1000_0000).contains(&a_bytes[0])); + + let b: &CStr = c"こんにちは!"; // Starts with non ascii + let b_bytes: &[u8] = b.to_bytes(); + assert!((0b1000_0000..).contains(&b_bytes[0])); + + assert_eq!(Ord::cmp(a, b), Ord::cmp(a_bytes, b_bytes)); + assert_eq!(PartialOrd::partial_cmp(a, b), PartialOrd::partial_cmp(a_bytes, b_bytes)); +} diff --git a/core/tests/lib.rs b/core/tests/lib.rs index 83a615fcd8be3..04aaa3f35b7ae 100644 --- a/core/tests/lib.rs +++ b/core/tests/lib.rs @@ -132,6 +132,7 @@ mod clone; mod cmp; mod const_ptr; mod convert; +mod ffi; mod fmt; mod future; mod hash; diff --git a/std/src/rt.rs b/std/src/rt.rs index deb4a8fa7eed0..307a543c9d215 100644 --- a/std/src/rt.rs +++ b/std/src/rt.rs @@ -16,9 +16,11 @@ #![deny(unsafe_op_in_unsafe_fn)] #![allow(unused_macros)] +#[rustfmt::skip] pub use crate::panicking::{begin_panic, panic_count}; pub use core::panicking::{panic_display, panic_fmt}; +#[rustfmt::skip] use crate::sync::Once; use crate::sys; use crate::thread::{self, Thread}; diff --git a/std/src/sys/pal/unix/net.rs b/std/src/sys/pal/unix/net.rs index bedb06043a7b4..eafde51c6088b 100644 --- a/std/src/sys/pal/unix/net.rs +++ b/std/src/sys/pal/unix/net.rs @@ -214,16 +214,25 @@ impl Socket { } 0 => {} _ => { - // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look - // for POLLHUP rather than read readiness - if pollfd.revents & libc::POLLHUP != 0 { - let e = self.take_error()?.unwrap_or_else(|| { - io::const_io_error!( - io::ErrorKind::Uncategorized, - "no error set after POLLHUP", - ) - }); - return Err(e); + if cfg!(target_os = "vxworks") { + // VxWorks poll does not return POLLHUP or POLLERR in revents. Check if the + // connnection actually succeeded and return ok only when the socket is + // ready and no errors were found. + if let Some(e) = self.take_error()? { + return Err(e); + } + } else { + // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look + // for POLLHUP or POLLERR rather than read readiness + if pollfd.revents & (libc::POLLHUP | libc::POLLERR) != 0 { + let e = self.take_error()?.unwrap_or_else(|| { + io::const_io_error!( + io::ErrorKind::Uncategorized, + "no error set after POLLHUP", + ) + }); + return Err(e); + } } return Ok(()); diff --git a/std/src/sys/pal/windows/fs.rs b/std/src/sys/pal/windows/fs.rs index 15d446786addc..ea19bd1e96193 100644 --- a/std/src/sys/pal/windows/fs.rs +++ b/std/src/sys/pal/windows/fs.rs @@ -416,8 +416,8 @@ impl File { dwHighDateTime: (info.LastWriteTime >> 32) as u32, }, change_time: Some(c::FILETIME { - dhLowDateTime: info.ChangeTime as c::DWORD, - dhHighDateTime: (info.ChangeTime >> 32) as c::DWORD, + dwLowDateTime: info.ChangeTime as u32, + dwHighDateTime: (info.ChangeTime >> 32) as u32, }), file_size: 0, reparse_tag: 0, diff --git a/std/src/sys/personality/gcc.rs b/std/src/sys/personality/gcc.rs index 0dc53550ca943..1fb85a10179c5 100644 --- a/std/src/sys/personality/gcc.rs +++ b/std/src/sys/personality/gcc.rs @@ -35,6 +35,7 @@ //! //! Once stack has been unwound down to the handler frame level, unwinding stops //! and the last personality routine transfers control to the catch block. +#![forbid(unsafe_op_in_unsafe_fn)] use super::dwarf::eh::{self, EHAction, EHContext}; use crate::ffi::c_int; @@ -92,107 +93,116 @@ 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(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 - // - // Apple 32-bit ARM (but not watchOS) uses the default routine instead - // since it uses SjLj unwinding. + if #[cfg(all( + target_arch = "arm", + not(all(target_vendor = "apple", not(target_os = "watchos"))), + not(target_os = "netbsd"), + ))] { + /// personality fn called by [ARM EHABI][armeabi-eh] + /// + /// Apple 32-bit ARM (but not watchOS) uses the default routine instead + /// since it uses "setjmp-longjmp" unwinding. + /// + /// [armeabi-eh]: https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( state: uw::_Unwind_State, exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code { - let state = state as c_int; - let action = state & uw::_US_ACTION_MASK as c_int; - let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { - // Backtraces on ARM will call the personality routine with - // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases - // we want to continue unwinding the stack, otherwise all our backtraces - // would end at __rust_try - if state & uw::_US_FORCE_UNWIND as c_int != 0 { + unsafe { + let state = state as c_int; + let action = state & uw::_US_ACTION_MASK as c_int; + let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { + // Backtraces on ARM will call the personality routine with + // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases + // we want to continue unwinding the stack, otherwise all our backtraces + // would end at __rust_try + if state & uw::_US_FORCE_UNWIND as c_int != 0 { + return continue_unwind(exception_object, context); + } + true + } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int { + false + } else if action == uw::_US_UNWIND_FRAME_RESUME as c_int { return continue_unwind(exception_object, context); - } - true - } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int { - false - } else if action == uw::_US_UNWIND_FRAME_RESUME as c_int { - return continue_unwind(exception_object, context); - } else { - return uw::_URC_FAILURE; - }; + } else { + return uw::_URC_FAILURE; + }; - // The DWARF unwinder assumes that _Unwind_Context holds things like the function - // and LSDA pointers, however ARM EHABI places them into the exception object. - // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which - // take only the context pointer, GCC personality routines stash a pointer to - // exception_object in the context, using location reserved for ARM's - // "scratch register" (r12). - uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr); - // ...A more principled approach would be to provide the full definition of ARM's - // _Unwind_Context in our libunwind bindings and fetch the required data from there - // directly, bypassing DWARF compatibility functions. + // The DWARF unwinder assumes that _Unwind_Context holds things like the function + // and LSDA pointers, however ARM EHABI places them into the exception object. + // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which + // take only the context pointer, GCC personality routines stash a pointer to + // exception_object in the context, using location reserved for ARM's + // "scratch register" (r12). + uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr); + // ...A more principled approach would be to provide the full definition of ARM's + // _Unwind_Context in our libunwind bindings and fetch the required data from there + // directly, bypassing DWARF compatibility functions. - let eh_action = match find_eh_action(context) { - Ok(action) => action, - Err(_) => return uw::_URC_FAILURE, - }; - if search_phase { - match eh_action { - EHAction::None | EHAction::Cleanup(_) => { - return continue_unwind(exception_object, context); - } - EHAction::Catch(_) | EHAction::Filter(_) => { - // EHABI requires the personality routine to update the - // SP value in the barrier cache of the exception object. - (*exception_object).private[5] = - uw::_Unwind_GetGR(context, uw::UNWIND_SP_REG); - return uw::_URC_HANDLER_FOUND; + let eh_action = match find_eh_action(context) { + Ok(action) => action, + Err(_) => return uw::_URC_FAILURE, + }; + if search_phase { + match eh_action { + EHAction::None | EHAction::Cleanup(_) => { + return continue_unwind(exception_object, context); + } + EHAction::Catch(_) | EHAction::Filter(_) => { + // EHABI requires the personality routine to update the + // SP value in the barrier cache of the exception object. + (*exception_object).private[5] = + uw::_Unwind_GetGR(context, uw::UNWIND_SP_REG); + return uw::_URC_HANDLER_FOUND; + } + EHAction::Terminate => return uw::_URC_FAILURE, } - EHAction::Terminate => return uw::_URC_FAILURE, - } - } else { - match eh_action { - EHAction::None => return continue_unwind(exception_object, context), - EHAction::Filter(_) if state & uw::_US_FORCE_UNWIND as c_int != 0 => return continue_unwind(exception_object, context), - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { - uw::_Unwind_SetGR( - context, - UNWIND_DATA_REG.0, - exception_object as uw::_Unwind_Ptr, - ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); - uw::_Unwind_SetIP(context, lpad); - return uw::_URC_INSTALL_CONTEXT; + } else { + match eh_action { + EHAction::None => return continue_unwind(exception_object, context), + EHAction::Filter(_) if state & uw::_US_FORCE_UNWIND as c_int != 0 => return continue_unwind(exception_object, context), + EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { + uw::_Unwind_SetGR( + context, + UNWIND_DATA_REG.0, + exception_object as uw::_Unwind_Ptr, + ); + uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); + uw::_Unwind_SetIP(context, lpad); + return uw::_URC_INSTALL_CONTEXT; + } + EHAction::Terminate => return uw::_URC_FAILURE, } - EHAction::Terminate => return uw::_URC_FAILURE, } - } - // On ARM EHABI the personality routine is responsible for actually - // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). - unsafe fn continue_unwind( - exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code { - if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON { - uw::_URC_CONTINUE_UNWIND - } else { - uw::_URC_FAILURE - } - } - // defined in libgcc - extern "C" { - fn __gnu_unwind_frame( + // On ARM EHABI the personality routine is responsible for actually + // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). + unsafe fn continue_unwind( exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code; + ) -> uw::_Unwind_Reason_Code { + unsafe { + if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON { + uw::_URC_CONTINUE_UNWIND + } else { + uw::_URC_FAILURE + } + } + } + // defined in libgcc + extern "C" { + fn __gnu_unwind_frame( + exception_object: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context, + ) -> uw::_Unwind_Reason_Code; + } } } } else { - // Default personality routine, which is used directly on most targets - // and indirectly on Windows x86_64 via SEH. + /// Default personality routine, which is used directly on most targets + /// and indirectly on Windows x86_64 and AArch64 via SEH. unsafe extern "C" fn rust_eh_personality_impl( version: c_int, actions: uw::_Unwind_Action, @@ -200,43 +210,49 @@ cfg_if::cfg_if! { exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code { - if version != 1 { - return uw::_URC_FATAL_PHASE1_ERROR; - } - let eh_action = match find_eh_action(context) { - Ok(action) => action, - Err(_) => return uw::_URC_FATAL_PHASE1_ERROR, - }; - if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { - match eh_action { - EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, - EHAction::Catch(_) | EHAction::Filter(_) => uw::_URC_HANDLER_FOUND, - EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR, + unsafe { + if version != 1 { + return uw::_URC_FATAL_PHASE1_ERROR; } - } else { - match eh_action { - EHAction::None => uw::_URC_CONTINUE_UNWIND, - // Forced unwinding hits a terminate action. - EHAction::Filter(_) if actions as i32 & uw::_UA_FORCE_UNWIND as i32 != 0 => uw::_URC_CONTINUE_UNWIND, - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { - uw::_Unwind_SetGR( - context, - UNWIND_DATA_REG.0, - exception_object.cast(), - ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); - uw::_Unwind_SetIP(context, lpad); - uw::_URC_INSTALL_CONTEXT + let eh_action = match find_eh_action(context) { + Ok(action) => action, + Err(_) => return uw::_URC_FATAL_PHASE1_ERROR, + }; + if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { + match eh_action { + EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, + EHAction::Catch(_) | EHAction::Filter(_) => uw::_URC_HANDLER_FOUND, + EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR, + } + } else { + match eh_action { + EHAction::None => uw::_URC_CONTINUE_UNWIND, + // Forced unwinding hits a terminate action. + EHAction::Filter(_) if actions as i32 & uw::_UA_FORCE_UNWIND as i32 != 0 => uw::_URC_CONTINUE_UNWIND, + EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { + uw::_Unwind_SetGR( + context, + UNWIND_DATA_REG.0, + exception_object.cast(), + ); + uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); + uw::_Unwind_SetIP(context, lpad); + uw::_URC_INSTALL_CONTEXT + } + EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR, } - EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR, } } } cfg_if::cfg_if! { if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"))] { - // On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind - // handler data (aka LSDA) uses GCC-compatible encoding. + /// personality fn called by [Windows Structured Exception Handling][windows-eh] + /// + /// On x86_64 and AArch64 MinGW targets, the unwinding mechanism is SEH, + /// however the unwind handler data (aka LSDA) uses GCC-compatible encoding + /// + /// [windows-eh]: https://learn.microsoft.com/en-us/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170 #[lang = "eh_personality"] #[allow(nonstandard_style)] unsafe extern "C" fn rust_eh_personality( @@ -245,16 +261,33 @@ cfg_if::cfg_if! { contextRecord: *mut uw::CONTEXT, dispatcherContext: *mut uw::DISPATCHER_CONTEXT, ) -> uw::EXCEPTION_DISPOSITION { - uw::_GCC_specific_handler( - exceptionRecord, - establisherFrame, - contextRecord, - dispatcherContext, - rust_eh_personality_impl, - ) + // SAFETY: the cfg is still target_os = "windows" and target_env = "gnu", + // which means that this is the correct function to call, passing our impl fn + // as the callback which gets actually used + unsafe { + uw::_GCC_specific_handler( + exceptionRecord, + establisherFrame, + contextRecord, + dispatcherContext, + rust_eh_personality_impl, + ) + } } } else { - // The personality routine for most of our targets. + /// personality fn called by [Itanium C++ ABI Exception Handling][itanium-eh] + /// + /// The personality routine for most non-Windows targets. This will be called by + /// the unwinding library: + /// - "In the search phase, the framework repeatedly calls the personality routine, + /// with the _UA_SEARCH_PHASE flag as described below, first for the current PC + /// and register state, and then unwinding a frame to a new PC at each step..." + /// - "If the search phase reports success, the framework restarts in the cleanup + /// phase. Again, it repeatedly calls the personality routine, with the + /// _UA_CLEANUP_PHASE flag as described below, first for the current PC and + /// register state, and then unwinding a frame to a new PC at each step..."i + /// + /// [itanium-eh]: https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( version: c_int, @@ -263,13 +296,17 @@ cfg_if::cfg_if! { exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code { - rust_eh_personality_impl( - version, - actions, - exception_class, - exception_object, - context, - ) + // SAFETY: the platform support must modify the cfg for the inner fn + // if it needs something different than what is currently invoked. + unsafe { + rust_eh_personality_impl( + version, + actions, + exception_class, + exception_object, + context, + ) + } } } } @@ -277,18 +314,20 @@ cfg_if::cfg_if! { } unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result { - let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8; - let mut ip_before_instr: c_int = 0; - let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr); - let eh_context = EHContext { - // The return address points 1 byte past the call instruction, - // which could be in the next IP range in LSDA range table. - // - // `ip = -1` has special meaning, so use wrapping sub to allow for that - ip: if ip_before_instr != 0 { ip } else { ip.wrapping_sub(1) }, - func_start: uw::_Unwind_GetRegionStart(context), - get_text_start: &|| uw::_Unwind_GetTextRelBase(context), - get_data_start: &|| uw::_Unwind_GetDataRelBase(context), - }; - eh::find_eh_action(lsda, &eh_context) + unsafe { + let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8; + let mut ip_before_instr: c_int = 0; + let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr); + let eh_context = EHContext { + // The return address points 1 byte past the call instruction, + // which could be in the next IP range in LSDA range table. + // + // `ip = -1` has special meaning, so use wrapping sub to allow for that + ip: if ip_before_instr != 0 { ip } else { ip.wrapping_sub(1) }, + func_start: uw::_Unwind_GetRegionStart(context), + get_text_start: &|| uw::_Unwind_GetTextRelBase(context), + get_data_start: &|| uw::_Unwind_GetDataRelBase(context), + }; + eh::find_eh_action(lsda, &eh_context) + } }