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_if::cfg_if! {
126if #[cfg(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} else {
154 // ARM EHABI
155 #[repr(C)]
156 #[derive(Copy, Clone, PartialEq)]
157 pub enum _Unwind_State {
158 _US_VIRTUAL_UNWIND_FRAME = 0,
159 _US_UNWIND_FRAME_STARTING = 1,
160 _US_UNWIND_FRAME_RESUME = 2,
161 _US_ACTION_MASK = 3,
162 _US_FORCE_UNWIND = 8,
163 _US_END_OF_STACK = 16,
164 }
165 pub use _Unwind_State::*;
166
167 #[repr(C)]
168 enum _Unwind_VRS_Result {
169 _UVRSR_OK = 0,
170 _UVRSR_NOT_IMPLEMENTED = 1,
171 _UVRSR_FAILED = 2,
172 }
173 #[repr(C)]
174 enum _Unwind_VRS_RegClass {
175 _UVRSC_CORE = 0,
176 _UVRSC_VFP = 1,
177 _UVRSC_FPA = 2,
178 _UVRSC_WMMXD = 3,
179 _UVRSC_WMMXC = 4,
180 }
181 use _Unwind_VRS_RegClass::*;
182 #[repr(C)]
183 enum _Unwind_VRS_DataRepresentation {
184 _UVRSD_UINT32 = 0,
185 _UVRSD_VFPX = 1,
186 _UVRSD_FPAX = 2,
187 _UVRSD_UINT64 = 3,
188 _UVRSD_FLOAT = 4,
189 _UVRSD_DOUBLE = 5,
190 }
191 use _Unwind_VRS_DataRepresentation::*;
192
193 pub const UNWIND_POINTER_REG: c_int = 12;
194 pub const UNWIND_SP_REG: c_int = 13;
195 pub const UNWIND_IP_REG: c_int = 15;
196
197 #[cfg_attr(
198 all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
199 link(name = "unwind", kind = "static", modifiers = "-bundle")
200 )]
201 unsafe extern "C" {
202 fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
203 regclass: _Unwind_VRS_RegClass,
204 regno: _Unwind_Word,
205 repr: _Unwind_VRS_DataRepresentation,
206 data: *mut c_void)
207 -> _Unwind_VRS_Result;
208
209 fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context,
210 regclass: _Unwind_VRS_RegClass,
211 regno: _Unwind_Word,
212 repr: _Unwind_VRS_DataRepresentation,
213 data: *mut c_void)
214 -> _Unwind_VRS_Result;
215 }
216
217 // On Android or ARM/Linux, these are implemented as macros:
218
219 pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
220 let mut val: _Unwind_Word = core::ptr::null();
221 unsafe { _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
222 (&raw mut val) as *mut c_void); }
223 val
224 }
225
226 pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
227 let mut value = value;
228 unsafe { _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
229 (&raw mut value) as *mut c_void); }
230 }
231
232 pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
233 -> _Unwind_Word {
234 let val = unsafe { _Unwind_GetGR(ctx, UNWIND_IP_REG) };
235 val.map_addr(|v| v & !1)
236 }
237
238 pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
239 value: _Unwind_Word) {
240 // Propagate thumb bit to instruction pointer
241 let thumb_state = unsafe { _Unwind_GetGR(ctx, UNWIND_IP_REG).addr() & 1 };
242 let value = value.map_addr(|v| v | thumb_state);
243 unsafe { _Unwind_SetGR(ctx, UNWIND_IP_REG, value); }
244 }
245
246 pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
247 ip_before_insn: *mut c_int)
248 -> _Unwind_Word {
249 unsafe {
250 *ip_before_insn = 0;
251 _Unwind_GetIP(ctx)
252 }
253 }
254
255 // This function also doesn't exist on Android or ARM/Linux, so make it a no-op
256 pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
257 pc
258 }
259}
260} // cfg_if!
261
262cfg_if::cfg_if! {
263if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm"))] {
264 // 32-bit ARM Apple (except for watchOS armv7k specifically) uses SjLj and
265 // does not provide _Unwind_Backtrace()
266 unsafe extern "C-unwind" {
267 pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
268 }
269
270 pub use _Unwind_SjLj_RaiseException as _Unwind_RaiseException;
271} else {
272 #[cfg_attr(
273 all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
274 link(name = "unwind", kind = "static", modifiers = "-bundle")
275 )]
276 unsafe extern "C-unwind" {
277 pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
278 }
279 #[cfg_attr(
280 all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
281 link(name = "unwind", kind = "static", modifiers = "-bundle")
282 )]
283 unsafe extern "C" {
284 pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
285 trace_argument: *mut c_void)
286 -> _Unwind_Reason_Code;
287 }
288}
289} // cfg_if!
290
291cfg_if::cfg_if! {
292if #[cfg(any(
293 all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"),
294 target_os = "cygwin",
295 ))] {
296 // We declare these as opaque types. This is fine since you just need to
297 // pass them to _GCC_specific_handler and forget about them.
298 pub enum EXCEPTION_RECORD {}
299 pub type LPVOID = *mut c_void;
300 pub enum CONTEXT {}
301 pub enum DISPATCHER_CONTEXT {}
302 pub type EXCEPTION_DISPOSITION = c_int;
303 type PersonalityFn = unsafe extern "C" fn(version: c_int,
304 actions: _Unwind_Action,
305 exception_class: _Unwind_Exception_Class,
306 exception_object: *mut _Unwind_Exception,
307 context: *mut _Unwind_Context)
308 -> _Unwind_Reason_Code;
309
310 unsafe extern "C" {
311 pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD,
312 establisherFrame: LPVOID,
313 contextRecord: *mut CONTEXT,
314 dispatcherContext: *mut DISPATCHER_CONTEXT,
315 personality: PersonalityFn)
316 -> EXCEPTION_DISPOSITION;
317 }
318}
319} // cfg_if!
320

Provided by KDAB

Privacy Policy
Learn Rust with the experts
Find out more