blob: 12766c1181e3f43f0f6aefbd212959da95a25a2c [file] [log] [blame] [edit]
use core::ffi::c_void;
use core::ops;
use crate::util::*;
#[cfg(not(feature = "unwinder"))]
use crate::arch::Arch;
#[cfg(feature = "unwinder")]
pub use crate::unwinder::*;
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct UnwindReasonCode(pub c_int);
#[allow(unused)]
impl UnwindReasonCode {
pub const NO_REASON: Self = Self(0);
pub const FOREIGN_EXCEPTION_CAUGHT: Self = Self(1);
pub const FATAL_PHASE2_ERROR: Self = Self(2);
pub const FATAL_PHASE1_ERROR: Self = Self(3);
pub const NORMAL_STOP: Self = Self(4);
pub const END_OF_STACK: Self = Self(5);
pub const HANDLER_FOUND: Self = Self(6);
pub const INSTALL_CONTEXT: Self = Self(7);
pub const CONTINUE_UNWIND: Self = Self(8);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct UnwindAction(pub c_int);
impl UnwindAction {
pub const SEARCH_PHASE: Self = Self(1);
pub const CLEANUP_PHASE: Self = Self(2);
pub const HANDLER_FRAME: Self = Self(4);
pub const FORCE_UNWIND: Self = Self(8);
pub const END_OF_STACK: Self = Self(16);
}
impl ops::BitOr for UnwindAction {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
impl UnwindAction {
#[inline]
pub const fn empty() -> Self {
Self(0)
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0 & other.0 != 0
}
}
pub type UnwindExceptionCleanupFn = unsafe extern "C" fn(UnwindReasonCode, *mut UnwindException);
pub type UnwindStopFn = unsafe extern "C" fn(
c_int,
UnwindAction,
u64,
*mut UnwindException,
&mut UnwindContext<'_>,
*mut c_void,
) -> UnwindReasonCode;
#[cfg(not(feature = "unwinder"))]
#[repr(C)]
pub struct UnwindException {
pub exception_class: u64,
pub exception_cleanup: Option<UnwindExceptionCleanupFn>,
private: [usize; Arch::UNWIND_PRIVATE_DATA_SIZE],
}
pub type UnwindTraceFn =
extern "C" fn(ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode;
#[cfg(not(feature = "unwinder"))]
#[repr(C)]
pub struct UnwindContext<'a> {
opaque: usize,
phantom: core::marker::PhantomData<&'a ()>,
}
pub type PersonalityRoutine = unsafe extern "C" fn(
c_int,
UnwindAction,
u64,
*mut UnwindException,
&mut UnwindContext<'_>,
) -> UnwindReasonCode;
#[cfg(not(feature = "unwinder"))]
macro_rules! binding {
() => {};
(unsafe extern $abi: literal fn $name: ident ($($arg: ident : $arg_ty: ty),*$(,)?) $(-> $ret: ty)?; $($rest: tt)*) => {
extern $abi {
pub fn $name($($arg: $arg_ty),*) $(-> $ret)?;
}
binding!($($rest)*);
};
(extern $abi: literal fn $name: ident ($($arg: ident : $arg_ty: ty),*$(,)?) $(-> $ret: ty)?; $($rest: tt)*) => {
#[allow(non_snake_case)]
#[inline]
pub fn $name($($arg: $arg_ty),*) $(-> $ret)? {
extern $abi {
fn $name($($arg: $arg_ty),*) $(-> $ret)?;
}
unsafe { $name($($arg),*) }
}
binding!($($rest)*);
};
}
#[cfg(feature = "unwinder")]
macro_rules! binding {
() => {};
(unsafe extern $abi: literal fn $name: ident ($($arg: ident : $arg_ty: ty),*$(,)?) $(-> $ret: ty)?; $($rest: tt)*) => {
const _: unsafe extern $abi fn($($arg_ty),*) $(-> $ret)? = $name;
};
(extern $abi: literal fn $name: ident ($($arg: ident : $arg_ty: ty),*$(,)?) $(-> $ret: ty)?; $($rest: tt)*) => {
const _: extern $abi fn($($arg_ty),*) $(-> $ret)? = $name;
};
}
binding! {
extern "C" fn _Unwind_GetGR(unwind_ctx: &UnwindContext<'_>, index: c_int) -> usize;
extern "C" fn _Unwind_GetCFA(unwind_ctx: &UnwindContext<'_>) -> usize;
extern "C" fn _Unwind_SetGR(
unwind_ctx: &mut UnwindContext<'_>,
index: c_int,
value: usize,
);
extern "C" fn _Unwind_GetIP(unwind_ctx: &UnwindContext<'_>) -> usize;
extern "C" fn _Unwind_GetIPInfo(
unwind_ctx: &UnwindContext<'_>,
ip_before_insn: &mut c_int,
) -> usize;
extern "C" fn _Unwind_SetIP(
unwind_ctx: &mut UnwindContext<'_>,
value: usize,
);
extern "C" fn _Unwind_GetLanguageSpecificData(unwind_ctx: &UnwindContext<'_>) -> *mut c_void;
extern "C" fn _Unwind_GetRegionStart(unwind_ctx: &UnwindContext<'_>) -> usize;
extern "C" fn _Unwind_GetTextRelBase(unwind_ctx: &UnwindContext<'_>) -> usize;
extern "C" fn _Unwind_GetDataRelBase(unwind_ctx: &UnwindContext<'_>) -> usize;
extern "C" fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
unsafe extern "C-unwind" fn _Unwind_RaiseException(
exception: *mut UnwindException,
) -> UnwindReasonCode;
unsafe extern "C-unwind" fn _Unwind_ForcedUnwind(
exception: *mut UnwindException,
stop: UnwindStopFn,
stop_arg: *mut c_void,
) -> UnwindReasonCode;
unsafe extern "C-unwind" fn _Unwind_Resume(exception: *mut UnwindException) -> !;
unsafe extern "C-unwind" fn _Unwind_Resume_or_Rethrow(
exception: *mut UnwindException,
) -> UnwindReasonCode;
unsafe extern "C" fn _Unwind_DeleteException(exception: *mut UnwindException);
extern "C-unwind" fn _Unwind_Backtrace(
trace: UnwindTraceFn,
trace_argument: *mut c_void,
) -> UnwindReasonCode;
}