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}