1#![allow(nonstandard_style)]
2
3use core::ffi::{c_int, c_void};
4
5#[repr(C)]
6#[derive(Debug, Copy, Clone, PartialEq)]
7pub enum _Unwind_Reason_Code {
8 _URC_NO_REASON = 0,
9 _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
10 _URC_FATAL_PHASE2_ERROR = 2,
11 _URC_FATAL_PHASE1_ERROR = 3,
12 _URC_NORMAL_STOP = 4,
13 _URC_END_OF_STACK = 5,
14 _URC_HANDLER_FOUND = 6,
15 _URC_INSTALL_CONTEXT = 7,
16 _URC_CONTINUE_UNWIND = 8,
17 _URC_FAILURE = 9, // used only by ARM EHABI
18}
19pub use _Unwind_Reason_Code::*;
20
21pub type _Unwind_Exception_Class = u64;
22pub type _Unwind_Word = *const u8;
23pub type _Unwind_Ptr = *const u8;
24pub type _Unwind_Trace_Fn =
25 extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code;
26
27#[cfg(target_arch = "x86")]
28pub const unwinder_private_data_size: usize = 5;
29
30#[cfg(all(target_arch = "x86_64", not(any(target_os = "windows", target_os = "cygwin"))))]
31pub const unwinder_private_data_size: usize = 2;
32
33#[cfg(all(target_arch = "x86_64", any(target_os = "windows", target_os = "cygwin")))]
34pub const unwinder_private_data_size: usize = 6;
35
36#[cfg(all(target_arch = "arm", not(target_vendor = "apple")))]
37pub const unwinder_private_data_size: usize = 20;
38
39#[cfg(all(target_arch = "arm", target_vendor = "apple"))]
40pub const unwinder_private_data_size: usize = 5;
41
42#[cfg(all(target_arch = "aarch64", target_pointer_width = "64", not(target_os = "windows")))]
43pub const unwinder_private_data_size: usize = 2;
44
45#[cfg(all(target_arch = "aarch64", target_pointer_width = "64", target_os = "windows"))]
46pub const unwinder_private_data_size: usize = 6;
47
48#[cfg(all(target_arch = "aarch64", target_pointer_width = "32"))]
49pub const unwinder_private_data_size: usize = 5;
50
51#[cfg(target_arch = "m68k")]
52pub const unwinder_private_data_size: usize = 2;
53
54#[cfg(any(target_arch = "mips", target_arch = "mips32r6"))]
55pub const unwinder_private_data_size: usize = 2;
56
57#[cfg(target_arch = "csky")]
58pub const unwinder_private_data_size: usize = 2;
59
60#[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))]
61pub const unwinder_private_data_size: usize = 2;
62
63#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
64pub const unwinder_private_data_size: usize = 2;
65
66#[cfg(target_arch = "s390x")]
67pub const unwinder_private_data_size: usize = 2;
68
69#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
70pub const unwinder_private_data_size: usize = 2;
71
72#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
73pub const unwinder_private_data_size: usize = 2;
74
75#[cfg(all(target_arch = "wasm32", target_os = "emscripten"))]
76pub const unwinder_private_data_size: usize = 20;
77
78#[cfg(all(target_arch = "wasm32", target_os = "linux"))]
79pub const unwinder_private_data_size: usize = 2;
80
81#[cfg(all(target_arch = "hexagon", target_os = "linux"))]
82pub const unwinder_private_data_size: usize = 35;
83
84#[cfg(any(target_arch = "loongarch32", target_arch = "loongarch64"))]
85pub const unwinder_private_data_size: usize = 2;
86
87#[repr(C)]
88pub struct _Unwind_Exception {
89 pub exception_class: _Unwind_Exception_Class,
90 pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
91 pub private: [_Unwind_Word; unwinder_private_data_size],
92}
93
94pub enum _Unwind_Context {}
95
96pub type _Unwind_Exception_Cleanup_Fn =
97 Option<extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception)>;
98
99// FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in
100// the block are reexported in dylib build of std. This is needed when build rustc with
101// feature `llvm-libunwind`, as no other cdylib will provided those _Unwind_* symbols.
102// However the `link` attribute is duplicated multiple times and does not just export symbol,
103// a better way to manually export symbol would be another attribute like `#[export]`.
104// See the logic in function rustc_codegen_ssa::src::back::exported_symbols, module
105// rustc_codegen_ssa::src::back::symbol_export, rustc_middle::middle::exported_symbols
106// and RFC 2841
107#[cfg_attr(
108 all(
109 feature = "llvm-libunwind",
110 any(target_os = "fuchsia", target_os = "linux", target_os = "xous")
111 ),
112 link(name = "unwind", kind = "static", modifiers = "-bundle")
113)]
114unsafe extern "C-unwind" {
115 pub unsafefn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
116}
117unsafe extern "C" {
118 pub unsafefn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
119 pub unsafefn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
120 pub unsafefn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
121 pub unsafefn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
122 pub unsafefn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
123}
124
125cfg_select! {
126 any(target_vendor = "apple", target_os = "netbsd", not(target_arch = "arm")) => {
127 // Not ARM EHABI
128 //
129 // 32-bit ARM on iOS/tvOS/watchOS use either DWARF/Compact unwinding or
130 // "setjmp-longjmp" / SjLj unwinding.
131 pub type _Unwind_Action = c_int;
132
133 pub const _UA_SEARCH_PHASE: c_int = 1;
134 pub const _UA_CLEANUP_PHASE: c_int = 2;
135 pub const _UA_HANDLER_FRAME: c_int = 4;
136 pub const _UA_FORCE_UNWIND: c_int = 8;
137 pub const _UA_END_OF_STACK: c_int = 16;
138
139 #[cfg_attr(
140 all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
141 link(name = "unwind", kind = "static", modifiers = "-bundle")
142 )]
143 unsafe extern "C" {
144 pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
145 pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
146 pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word;
147 pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word);
148 pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int)
149 -> _Unwind_Word;
150 pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
151 }
152
153 }
154 _ => {
155 // ARM EHABI
156 #[repr(C)]
157 #[derive(Copy, Clone, PartialEq)]
158 pub enum _Unwind_State {
159 _US_VIRTUAL_UNWIND_FRAME = 0,
160 _US_UNWIND_FRAME_STARTING = 1,
161 _US_UNWIND_FRAME_RESUME = 2,
162 _US_ACTION_MASK = 3,
163 _US_FORCE_UNWIND = 8,
164 _US_END_OF_STACK = 16,
165 }
166 pub use _Unwind_State::*;
167
168 #[repr(C)]
169 enum _Unwind_VRS_Result {
170 _UVRSR_OK = 0,
171 _UVRSR_NOT_IMPLEMENTED = 1,
172 _UVRSR_FAILED = 2,
173 }
174 #[repr(C)]
175 enum _Unwind_VRS_RegClass {
176 _UVRSC_CORE = 0,
177 _UVRSC_VFP = 1,
178 _UVRSC_FPA = 2,
179 _UVRSC_WMMXD = 3,
180 _UVRSC_WMMXC = 4,
181 }
182 use _Unwind_VRS_RegClass::*;
183 #[repr(C)]
184 enum _Unwind_VRS_DataRepresentation {
185 _UVRSD_UINT32 = 0,
186 _UVRSD_VFPX = 1,
187 _UVRSD_FPAX = 2,
188 _UVRSD_UINT64 = 3,
189 _UVRSD_FLOAT = 4,
190 _UVRSD_DOUBLE = 5,
191 }
192 use _Unwind_VRS_DataRepresentation::*;
193
194 pub const UNWIND_POINTER_REG: c_int = 12;
195 pub const UNWIND_SP_REG: c_int = 13;
196 pub const UNWIND_IP_REG: c_int = 15;
197
198 #[cfg_attr(
199 all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
200 link(name = "unwind", kind = "static", modifiers = "-bundle")
201 )]
202 unsafe extern "C" {
203 fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
204 regclass: _Unwind_VRS_RegClass,
205 regno: _Unwind_Word,
206 repr: _Unwind_VRS_DataRepresentation,
207 data: *mut c_void)
208 -> _Unwind_VRS_Result;
209
210 fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context,
211 regclass: _Unwind_VRS_RegClass,
212 regno: _Unwind_Word,
213 repr: _Unwind_VRS_DataRepresentation,
214 data: *mut c_void)
215 -> _Unwind_VRS_Result;
216 }
217
218 // On Android or ARM/Linux, these are implemented as macros:
219
220 pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
221 let mut val: _Unwind_Word = core::ptr::null();
222 unsafe { _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
223 (&raw mut val) as *mut c_void); }
224 val
225 }
226
227 pub unsafe fn _Unwind_SetGR(
228 ctx: *mut _Unwind_Context,
229 reg_index: c_int,
230 value: _Unwind_Word
231 ) {
232 let mut value = value;
233 unsafe { _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
234 (&raw mut value) as *mut c_void); }
235 }
236
237 pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
238 -> _Unwind_Word {
239 let val = unsafe { _Unwind_GetGR(ctx, UNWIND_IP_REG) };
240 val.map_addr(|v| v & !1)
241 }
242
243 pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
244 value: _Unwind_Word) {
245 // Propagate thumb bit to instruction pointer
246 let thumb_state = unsafe { _Unwind_GetGR(ctx, UNWIND_IP_REG).addr() & 1 };
247 let value = value.map_addr(|v| v | thumb_state);
248 unsafe { _Unwind_SetGR(ctx, UNWIND_IP_REG, value); }
249 }
250
251 pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
252 ip_before_insn: *mut c_int)
253 -> _Unwind_Word {
254 unsafe {
255 *ip_before_insn = 0;
256 _Unwind_GetIP(ctx)
257 }
258 }
259
260 // This function also doesn't exist on Android or ARM/Linux, so make it a no-op
261 pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
262 pc
263 }
264 }
265}
266
267cfg_select! {
268 all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm") => {
269 // 32-bit ARM Apple (except for watchOS armv7k specifically) uses SjLj and
270 // does not provide _Unwind_Backtrace()
271 unsafe extern "C-unwind" {
272 pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
273 }
274
275 pub use _Unwind_SjLj_RaiseException as _Unwind_RaiseException;
276 }
277 _ => {
278 #[cfg_attr(
279 all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
280 link(name = "unwind", kind = "static", modifiers = "-bundle")
281 )]
282 unsafe extern "C-unwind" {
283 pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
284 }
285 #[cfg_attr(
286 all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
287 link(name = "unwind", kind = "static", modifiers = "-bundle")
288 )]
289 unsafe extern "C" {
290 pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
291 trace_argument: *mut c_void)
292 -> _Unwind_Reason_Code;
293 }
294 }
295}
296
297cfg_select! {
298 any(
299 all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"),
300 target_os = "cygwin",
301 ) => {
302 // We declare these as opaque types. This is fine since you just need to
303 // pass them to _GCC_specific_handler and forget about them.
304 pub enum EXCEPTION_RECORD {}
305 pub type LPVOID = *mut c_void;
306 pub enum CONTEXT {}
307 pub enum DISPATCHER_CONTEXT {}
308 pub type EXCEPTION_DISPOSITION = c_int;
309 type PersonalityFn = unsafe extern "C" fn(version: c_int,
310 actions: _Unwind_Action,
311 exception_class: _Unwind_Exception_Class,
312 exception_object: *mut _Unwind_Exception,
313 context: *mut _Unwind_Context)
314 -> _Unwind_Reason_Code;
315
316 unsafe extern "C" {
317 pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD,
318 establisherFrame: LPVOID,
319 contextRecord: *mut CONTEXT,
320 dispatcherContext: *mut DISPATCHER_CONTEXT,
321 personality: PersonalityFn)
322 -> EXCEPTION_DISPOSITION;
323 }
324 }
325 _ => {}
326}
327