1
Fork 0

std: unsafe-wrap gcc::rust_eh_personality and impl

This commit is contained in:
Jubilee Young 2024-07-24 11:42:31 -07:00
parent 2ccafed862
commit 2c7ae388b3

View file

@ -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,7 +93,11 @@ 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")))] {
if #[cfg(all(
target_arch = "arm",
not(all(target_vendor = "apple", not(target_os = "watchos"))),
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
//
@ -104,6 +109,7 @@ cfg_if::cfg_if! {
exception_object: *mut uw::_Unwind_Exception,
context: *mut uw::_Unwind_Context,
) -> uw::_Unwind_Reason_Code {
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 {
@ -176,12 +182,14 @@ cfg_if::cfg_if! {
exception_object: *mut uw::_Unwind_Exception,
context: *mut uw::_Unwind_Context,
) -> 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(
@ -190,6 +198,7 @@ cfg_if::cfg_if! {
) -> uw::_Unwind_Reason_Code;
}
}
}
} else {
// Default personality routine, which is used directly on most targets
// and indirectly on Windows x86_64 via SEH.
@ -200,6 +209,7 @@ cfg_if::cfg_if! {
exception_object: *mut uw::_Unwind_Exception,
context: *mut uw::_Unwind_Context,
) -> uw::_Unwind_Reason_Code {
unsafe {
if version != 1 {
return uw::_URC_FATAL_PHASE1_ERROR;
}
@ -232,6 +242,7 @@ cfg_if::cfg_if! {
}
}
}
}
cfg_if::cfg_if! {
if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"))] {
@ -245,6 +256,7 @@ cfg_if::cfg_if! {
contextRecord: *mut uw::CONTEXT,
dispatcherContext: *mut uw::DISPATCHER_CONTEXT,
) -> uw::EXCEPTION_DISPOSITION {
unsafe {
uw::_GCC_specific_handler(
exceptionRecord,
establisherFrame,
@ -253,6 +265,7 @@ cfg_if::cfg_if! {
rust_eh_personality_impl,
)
}
}
} else {
// The personality routine for most of our targets.
#[lang = "eh_personality"]
@ -263,6 +276,7 @@ cfg_if::cfg_if! {
exception_object: *mut uw::_Unwind_Exception,
context: *mut uw::_Unwind_Context,
) -> uw::_Unwind_Reason_Code {
unsafe {
rust_eh_personality_impl(
version,
actions,
@ -274,9 +288,11 @@ cfg_if::cfg_if! {
}
}
}
}
}
unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result<EHAction, ()> {
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);
@ -291,4 +307,5 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result<EHAction,
get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
};
eh::find_eh_action(lsda, &eh_context)
}
}