unwinding/
abi.rs

1use core::ffi::c_void;
2use core::ops;
3
4use crate::util::*;
5
6#[cfg(not(feature = "unwinder"))]
7use crate::arch::Arch;
8#[cfg(feature = "unwinder")]
9pub use crate::unwinder::*;
10
11#[repr(transparent)]
12#[derive(Clone, Copy, PartialEq, Eq)]
13pub struct UnwindReasonCode(pub c_int);
14
15#[allow(unused)]
16impl UnwindReasonCode {
17    pub const NO_REASON: Self = Self(0);
18    pub const FOREIGN_EXCEPTION_CAUGHT: Self = Self(1);
19    pub const FATAL_PHASE2_ERROR: Self = Self(2);
20    pub const FATAL_PHASE1_ERROR: Self = Self(3);
21    pub const NORMAL_STOP: Self = Self(4);
22    pub const END_OF_STACK: Self = Self(5);
23    pub const HANDLER_FOUND: Self = Self(6);
24    pub const INSTALL_CONTEXT: Self = Self(7);
25    pub const CONTINUE_UNWIND: Self = Self(8);
26}
27
28#[repr(transparent)]
29#[derive(Clone, Copy, PartialEq, Eq)]
30pub struct UnwindAction(pub c_int);
31
32impl UnwindAction {
33    pub const SEARCH_PHASE: Self = Self(1);
34    pub const CLEANUP_PHASE: Self = Self(2);
35    pub const HANDLER_FRAME: Self = Self(4);
36    pub const FORCE_UNWIND: Self = Self(8);
37    pub const END_OF_STACK: Self = Self(16);
38}
39
40impl ops::BitOr for UnwindAction {
41    type Output = Self;
42
43    #[inline]
44    fn bitor(self, rhs: Self) -> Self {
45        Self(self.0 | rhs.0)
46    }
47}
48
49impl UnwindAction {
50    #[inline]
51    pub const fn empty() -> Self {
52        Self(0)
53    }
54
55    #[inline]
56    pub const fn contains(&self, other: Self) -> bool {
57        self.0 & other.0 != 0
58    }
59}
60
61pub type UnwindExceptionCleanupFn = unsafe extern "C" fn(UnwindReasonCode, *mut UnwindException);
62
63pub type UnwindStopFn = unsafe extern "C" fn(
64    c_int,
65    UnwindAction,
66    u64,
67    *mut UnwindException,
68    &mut UnwindContext<'_>,
69    *mut c_void,
70) -> UnwindReasonCode;
71
72#[cfg(not(feature = "unwinder"))]
73#[repr(C)]
74pub struct UnwindException {
75    pub exception_class: u64,
76    pub exception_cleanup: Option<UnwindExceptionCleanupFn>,
77    private: [usize; Arch::UNWIND_PRIVATE_DATA_SIZE],
78}
79
80pub type UnwindTraceFn =
81    extern "C" fn(ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode;
82
83#[cfg(not(feature = "unwinder"))]
84#[repr(C)]
85pub struct UnwindContext<'a> {
86    opaque: usize,
87    phantom: core::marker::PhantomData<&'a ()>,
88}
89
90pub type PersonalityRoutine = unsafe extern "C" fn(
91    c_int,
92    UnwindAction,
93    u64,
94    *mut UnwindException,
95    &mut UnwindContext<'_>,
96) -> UnwindReasonCode;
97
98#[cfg(not(feature = "unwinder"))]
99macro_rules! binding {
100    () => {};
101    (unsafe extern $abi: literal fn $name: ident ($($arg: ident : $arg_ty: ty),*$(,)?) $(-> $ret: ty)?; $($rest: tt)*) => {
102        unsafe extern $abi {
103            pub unsafe fn $name($($arg: $arg_ty),*) $(-> $ret)?;
104        }
105        binding!($($rest)*);
106    };
107
108    (extern $abi: literal fn $name: ident ($($arg: ident : $arg_ty: ty),*$(,)?) $(-> $ret: ty)?; $($rest: tt)*) => {
109        unsafe extern $abi {
110            pub safe fn $name($($arg: $arg_ty),*) $(-> $ret)?;
111        }
112        binding!($($rest)*);
113    };
114}
115
116#[cfg(feature = "unwinder")]
117macro_rules! binding {
118    () => {};
119    (unsafe extern $abi: literal fn $name: ident ($($arg: ident : $arg_ty: ty),*$(,)?) $(-> $ret: ty)?; $($rest: tt)*) => {
120        const _: unsafe extern $abi fn($($arg_ty),*) $(-> $ret)? = $name;
121    };
122
123    (extern $abi: literal fn $name: ident ($($arg: ident : $arg_ty: ty),*$(,)?) $(-> $ret: ty)?; $($rest: tt)*) => {
124        const _: extern $abi fn($($arg_ty),*) $(-> $ret)? = $name;
125    };
126}
127
128binding! {
129    extern "C" fn _Unwind_GetGR(unwind_ctx: &UnwindContext<'_>, index: c_int) -> usize;
130    extern "C" fn _Unwind_GetCFA(unwind_ctx: &UnwindContext<'_>) -> usize;
131    extern "C" fn _Unwind_SetGR(
132        unwind_ctx: &mut UnwindContext<'_>,
133        index: c_int,
134        value: usize,
135    );
136    extern "C" fn _Unwind_GetIP(unwind_ctx: &UnwindContext<'_>) -> usize;
137    extern "C" fn _Unwind_GetIPInfo(
138        unwind_ctx: &UnwindContext<'_>,
139        ip_before_insn: &mut c_int,
140    ) -> usize;
141    extern "C" fn _Unwind_SetIP(
142        unwind_ctx: &mut UnwindContext<'_>,
143        value: usize,
144    );
145    extern "C" fn _Unwind_GetLanguageSpecificData(unwind_ctx: &UnwindContext<'_>) -> *mut c_void;
146    extern "C" fn _Unwind_GetRegionStart(unwind_ctx: &UnwindContext<'_>) -> usize;
147    extern "C" fn _Unwind_GetTextRelBase(unwind_ctx: &UnwindContext<'_>) -> usize;
148    extern "C" fn _Unwind_GetDataRelBase(unwind_ctx: &UnwindContext<'_>) -> usize;
149    extern "C" fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
150    unsafe extern "C-unwind" fn _Unwind_RaiseException(
151        exception: *mut UnwindException,
152    ) -> UnwindReasonCode;
153    unsafe extern "C-unwind" fn _Unwind_ForcedUnwind(
154        exception: *mut UnwindException,
155        stop: UnwindStopFn,
156        stop_arg: *mut c_void,
157    ) -> UnwindReasonCode;
158    unsafe extern "C-unwind" fn _Unwind_Resume(exception: *mut UnwindException) -> !;
159    unsafe extern "C-unwind" fn _Unwind_Resume_or_Rethrow(
160        exception: *mut UnwindException,
161    ) -> UnwindReasonCode;
162    unsafe extern "C" fn _Unwind_DeleteException(exception: *mut UnwindException);
163    extern "C-unwind" fn _Unwind_Backtrace(
164        trace: UnwindTraceFn,
165        trace_argument: *mut c_void,
166    ) -> UnwindReasonCode;
167}