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