diff options
Diffstat (limited to 'library/unwind/src')
| -rw-r--r-- | library/unwind/src/lib.rs | 61 | ||||
| -rw-r--r-- | library/unwind/src/libunwind.rs | 353 | ||||
| -rw-r--r-- | library/unwind/src/wasm.rs | 7 |
3 files changed, 221 insertions, 200 deletions
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 5451a38a674..cd3a2f33ffa 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] #![unstable(feature = "panic_unwind", issue = "32837")] #![feature(cfg_emscripten_wasm_eh)] +#![feature(cfg_select)] #![feature(link_cfg)] #![feature(staged_api)] #![cfg_attr(not(target_env = "msvc"), feature(libc))] @@ -15,32 +16,37 @@ #[cfg(not(all(windows, target_env = "msvc")))] extern crate libc as _; -cfg_if::cfg_if! { - if #[cfg(target_env = "msvc")] { +cfg_select! { + target_env = "msvc" => { // Windows MSVC no extra unwinder support needed - } else if #[cfg(any( + } + any( target_os = "l4re", target_os = "none", target_os = "espidf", target_os = "nuttx", - ))] { + ) => { // These "unix" family members do not have unwinder. - } else if #[cfg(any( + } + any( unix, windows, target_os = "psp", target_os = "solid_asp3", all(target_vendor = "fortanix", target_env = "sgx"), - ))] { + ) => { mod libunwind; pub use libunwind::*; - } else if #[cfg(target_os = "xous")] { + } + target_os = "xous" => { mod unwinding; pub use unwinding::*; - } else if #[cfg(target_family = "wasm")] { + } + target_family = "wasm" => { mod wasm; pub use wasm::*; - } else { + } + _ => { // no unwinder on the system! // - os=none ("bare metal" targets) // - os=hermit @@ -52,17 +58,20 @@ cfg_if::cfg_if! { } #[cfg(target_env = "musl")] -cfg_if::cfg_if! { - if #[cfg(all(feature = "llvm-libunwind", feature = "system-llvm-libunwind"))] { +cfg_select! { + all(feature = "llvm-libunwind", feature = "system-llvm-libunwind") => { compile_error!("`llvm-libunwind` and `system-llvm-libunwind` cannot be enabled at the same time"); - } else if #[cfg(feature = "llvm-libunwind")] { + } + feature = "llvm-libunwind" => { #[link(name = "unwind", kind = "static", modifiers = "-bundle")] unsafe extern "C" {} - } else if #[cfg(feature = "system-llvm-libunwind")] { + } + feature = "system-llvm-libunwind" => { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] unsafe extern "C" {} - } else { + } + _ => { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] unsafe extern "C" {} @@ -72,13 +81,15 @@ cfg_if::cfg_if! { // This is the same as musl except that we default to using the system libunwind // instead of libgcc. #[cfg(target_env = "ohos")] -cfg_if::cfg_if! { - if #[cfg(all(feature = "llvm-libunwind", feature = "system-llvm-libunwind"))] { +cfg_select! { + all(feature = "llvm-libunwind", feature = "system-llvm-libunwind") => { compile_error!("`llvm-libunwind` and `system-llvm-libunwind` cannot be enabled at the same time"); - } else if #[cfg(feature = "llvm-libunwind")] { + } + feature = "llvm-libunwind" => { #[link(name = "unwind", kind = "static", modifiers = "-bundle")] unsafe extern "C" {} - } else { + } + _ => { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] unsafe extern "C" {} @@ -86,10 +97,11 @@ cfg_if::cfg_if! { } #[cfg(target_os = "android")] -cfg_if::cfg_if! { - if #[cfg(feature = "llvm-libunwind")] { +cfg_select! { + feature = "llvm-libunwind" => { compile_error!("`llvm-libunwind` is not supported for Android targets"); - } else { + } + _ => { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] unsafe extern "C" {} @@ -166,11 +178,12 @@ unsafe extern "C" {} unsafe extern "C" {} #[cfg(target_os = "nto")] -cfg_if::cfg_if! { - if #[cfg(target_env = "nto70")] { +cfg_select! { + target_env = "nto70" => { #[link(name = "gcc")] unsafe extern "C" {} - } else { + } + _ => { #[link(name = "gcc_s")] unsafe extern "C" {} } diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index b350003cbb1..9ac9b54ed4a 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -122,198 +122,205 @@ unsafe extern "C" { pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr; } -cfg_if::cfg_if! { -if #[cfg(any(target_vendor = "apple", target_os = "netbsd", not(target_arch = "arm")))] { - // Not ARM EHABI - // - // 32-bit ARM on iOS/tvOS/watchOS use either DWARF/Compact unwinding or - // "setjmp-longjmp" / SjLj unwinding. - pub type _Unwind_Action = c_int; - - pub const _UA_SEARCH_PHASE: c_int = 1; - pub const _UA_CLEANUP_PHASE: c_int = 2; - pub const _UA_HANDLER_FRAME: c_int = 4; - pub const _UA_FORCE_UNWIND: c_int = 8; - pub const _UA_END_OF_STACK: c_int = 16; - - #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), - link(name = "unwind", kind = "static", modifiers = "-bundle") - )] - unsafe extern "C" { - pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word; - pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word); - pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word; - pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word); - pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int) - -> _Unwind_Word; - pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void; - } +cfg_select! { + any(target_vendor = "apple", target_os = "netbsd", not(target_arch = "arm")) => { + // Not ARM EHABI + // + // 32-bit ARM on iOS/tvOS/watchOS use either DWARF/Compact unwinding or + // "setjmp-longjmp" / SjLj unwinding. + pub type _Unwind_Action = c_int; + + pub const _UA_SEARCH_PHASE: c_int = 1; + pub const _UA_CLEANUP_PHASE: c_int = 2; + pub const _UA_HANDLER_FRAME: c_int = 4; + pub const _UA_FORCE_UNWIND: c_int = 8; + pub const _UA_END_OF_STACK: c_int = 16; + + #[cfg_attr( + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), + link(name = "unwind", kind = "static", modifiers = "-bundle") + )] + unsafe extern "C" { + pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word; + pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word); + pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word; + pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word); + pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int) + -> _Unwind_Word; + pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void; + } -} else { - // ARM EHABI - #[repr(C)] - #[derive(Copy, Clone, PartialEq)] - pub enum _Unwind_State { - _US_VIRTUAL_UNWIND_FRAME = 0, - _US_UNWIND_FRAME_STARTING = 1, - _US_UNWIND_FRAME_RESUME = 2, - _US_ACTION_MASK = 3, - _US_FORCE_UNWIND = 8, - _US_END_OF_STACK = 16, } - pub use _Unwind_State::*; + _ => { + // ARM EHABI + #[repr(C)] + #[derive(Copy, Clone, PartialEq)] + pub enum _Unwind_State { + _US_VIRTUAL_UNWIND_FRAME = 0, + _US_UNWIND_FRAME_STARTING = 1, + _US_UNWIND_FRAME_RESUME = 2, + _US_ACTION_MASK = 3, + _US_FORCE_UNWIND = 8, + _US_END_OF_STACK = 16, + } + pub use _Unwind_State::*; - #[repr(C)] - enum _Unwind_VRS_Result { - _UVRSR_OK = 0, - _UVRSR_NOT_IMPLEMENTED = 1, - _UVRSR_FAILED = 2, - } - #[repr(C)] - enum _Unwind_VRS_RegClass { - _UVRSC_CORE = 0, - _UVRSC_VFP = 1, - _UVRSC_FPA = 2, - _UVRSC_WMMXD = 3, - _UVRSC_WMMXC = 4, - } - use _Unwind_VRS_RegClass::*; - #[repr(C)] - enum _Unwind_VRS_DataRepresentation { - _UVRSD_UINT32 = 0, - _UVRSD_VFPX = 1, - _UVRSD_FPAX = 2, - _UVRSD_UINT64 = 3, - _UVRSD_FLOAT = 4, - _UVRSD_DOUBLE = 5, - } - use _Unwind_VRS_DataRepresentation::*; - - pub const UNWIND_POINTER_REG: c_int = 12; - pub const UNWIND_SP_REG: c_int = 13; - pub const UNWIND_IP_REG: c_int = 15; - - #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), - link(name = "unwind", kind = "static", modifiers = "-bundle") - )] - unsafe extern "C" { - fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context, - regclass: _Unwind_VRS_RegClass, - regno: _Unwind_Word, - repr: _Unwind_VRS_DataRepresentation, - data: *mut c_void) - -> _Unwind_VRS_Result; - - fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context, - regclass: _Unwind_VRS_RegClass, - regno: _Unwind_Word, - repr: _Unwind_VRS_DataRepresentation, - data: *mut c_void) - -> _Unwind_VRS_Result; - } + #[repr(C)] + enum _Unwind_VRS_Result { + _UVRSR_OK = 0, + _UVRSR_NOT_IMPLEMENTED = 1, + _UVRSR_FAILED = 2, + } + #[repr(C)] + enum _Unwind_VRS_RegClass { + _UVRSC_CORE = 0, + _UVRSC_VFP = 1, + _UVRSC_FPA = 2, + _UVRSC_WMMXD = 3, + _UVRSC_WMMXC = 4, + } + use _Unwind_VRS_RegClass::*; + #[repr(C)] + enum _Unwind_VRS_DataRepresentation { + _UVRSD_UINT32 = 0, + _UVRSD_VFPX = 1, + _UVRSD_FPAX = 2, + _UVRSD_UINT64 = 3, + _UVRSD_FLOAT = 4, + _UVRSD_DOUBLE = 5, + } + use _Unwind_VRS_DataRepresentation::*; + + pub const UNWIND_POINTER_REG: c_int = 12; + pub const UNWIND_SP_REG: c_int = 13; + pub const UNWIND_IP_REG: c_int = 15; + + #[cfg_attr( + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), + link(name = "unwind", kind = "static", modifiers = "-bundle") + )] + unsafe extern "C" { + fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context, + regclass: _Unwind_VRS_RegClass, + regno: _Unwind_Word, + repr: _Unwind_VRS_DataRepresentation, + data: *mut c_void) + -> _Unwind_VRS_Result; + + fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context, + regclass: _Unwind_VRS_RegClass, + regno: _Unwind_Word, + repr: _Unwind_VRS_DataRepresentation, + data: *mut c_void) + -> _Unwind_VRS_Result; + } - // On Android or ARM/Linux, these are implemented as macros: + // On Android or ARM/Linux, these are implemented as macros: - pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word { - let mut val: _Unwind_Word = core::ptr::null(); - unsafe { _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32, - (&raw mut val) as *mut c_void); } - val - } + pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word { + let mut val: _Unwind_Word = core::ptr::null(); + unsafe { _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32, + (&raw mut val) as *mut c_void); } + val + } - pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) { - let mut value = value; - unsafe { _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32, - (&raw mut value) as *mut c_void); } - } + pub unsafe fn _Unwind_SetGR( + ctx: *mut _Unwind_Context, + reg_index: c_int, + value: _Unwind_Word + ) { + let mut value = value; + unsafe { _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32, + (&raw mut value) as *mut c_void); } + } - pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) - -> _Unwind_Word { - let val = unsafe { _Unwind_GetGR(ctx, UNWIND_IP_REG) }; - val.map_addr(|v| v & !1) - } + pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) + -> _Unwind_Word { + let val = unsafe { _Unwind_GetGR(ctx, UNWIND_IP_REG) }; + val.map_addr(|v| v & !1) + } - pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context, - value: _Unwind_Word) { - // Propagate thumb bit to instruction pointer - let thumb_state = unsafe { _Unwind_GetGR(ctx, UNWIND_IP_REG).addr() & 1 }; - let value = value.map_addr(|v| v | thumb_state); - unsafe { _Unwind_SetGR(ctx, UNWIND_IP_REG, value); } - } + pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context, + value: _Unwind_Word) { + // Propagate thumb bit to instruction pointer + let thumb_state = unsafe { _Unwind_GetGR(ctx, UNWIND_IP_REG).addr() & 1 }; + let value = value.map_addr(|v| v | thumb_state); + unsafe { _Unwind_SetGR(ctx, UNWIND_IP_REG, value); } + } - pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, - ip_before_insn: *mut c_int) - -> _Unwind_Word { - unsafe { - *ip_before_insn = 0; - _Unwind_GetIP(ctx) + pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, + ip_before_insn: *mut c_int) + -> _Unwind_Word { + unsafe { + *ip_before_insn = 0; + _Unwind_GetIP(ctx) + } } - } - // This function also doesn't exist on Android or ARM/Linux, so make it a no-op - pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void { - pc + // This function also doesn't exist on Android or ARM/Linux, so make it a no-op + pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void { + pc + } } } -} // cfg_if! - -cfg_if::cfg_if! { -if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm"))] { - // 32-bit ARM Apple (except for watchOS armv7k specifically) uses SjLj and - // does not provide _Unwind_Backtrace() - unsafe extern "C-unwind" { - pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; - } - pub use _Unwind_SjLj_RaiseException as _Unwind_RaiseException; -} else { - #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), - link(name = "unwind", kind = "static", modifiers = "-bundle") - )] - unsafe extern "C-unwind" { - pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; +cfg_select! { + all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm") => { + // 32-bit ARM Apple (except for watchOS armv7k specifically) uses SjLj and + // does not provide _Unwind_Backtrace() + unsafe extern "C-unwind" { + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + } + + pub use _Unwind_SjLj_RaiseException as _Unwind_RaiseException; } - #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), - link(name = "unwind", kind = "static", modifiers = "-bundle") - )] - unsafe extern "C" { - pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, - trace_argument: *mut c_void) - -> _Unwind_Reason_Code; + _ => { + #[cfg_attr( + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), + link(name = "unwind", kind = "static", modifiers = "-bundle") + )] + unsafe extern "C-unwind" { + pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + } + #[cfg_attr( + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), + link(name = "unwind", kind = "static", modifiers = "-bundle") + )] + unsafe extern "C" { + pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, + trace_argument: *mut c_void) + -> _Unwind_Reason_Code; + } } } -} // cfg_if! -cfg_if::cfg_if! { -if #[cfg(any( +cfg_select! { + any( all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"), target_os = "cygwin", - ))] { - // We declare these as opaque types. This is fine since you just need to - // pass them to _GCC_specific_handler and forget about them. - pub enum EXCEPTION_RECORD {} - pub type LPVOID = *mut c_void; - pub enum CONTEXT {} - pub enum DISPATCHER_CONTEXT {} - pub type EXCEPTION_DISPOSITION = c_int; - type PersonalityFn = unsafe extern "C" fn(version: c_int, - actions: _Unwind_Action, - exception_class: _Unwind_Exception_Class, - exception_object: *mut _Unwind_Exception, - context: *mut _Unwind_Context) - -> _Unwind_Reason_Code; - - unsafe extern "C" { - pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD, - establisherFrame: LPVOID, - contextRecord: *mut CONTEXT, - dispatcherContext: *mut DISPATCHER_CONTEXT, - personality: PersonalityFn) - -> EXCEPTION_DISPOSITION; + ) => { + // We declare these as opaque types. This is fine since you just need to + // pass them to _GCC_specific_handler and forget about them. + pub enum EXCEPTION_RECORD {} + pub type LPVOID = *mut c_void; + pub enum CONTEXT {} + pub enum DISPATCHER_CONTEXT {} + pub type EXCEPTION_DISPOSITION = c_int; + type PersonalityFn = unsafe extern "C" fn(version: c_int, + actions: _Unwind_Action, + exception_class: _Unwind_Exception_Class, + exception_object: *mut _Unwind_Exception, + context: *mut _Unwind_Context) + -> _Unwind_Reason_Code; + + unsafe extern "C" { + pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: LPVOID, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT, + personality: PersonalityFn) + -> EXCEPTION_DISPOSITION; + } } + _ => {} } -} // cfg_if! diff --git a/library/unwind/src/wasm.rs b/library/unwind/src/wasm.rs index 2d36a8be004..3341e54759a 100644 --- a/library/unwind/src/wasm.rs +++ b/library/unwind/src/wasm.rs @@ -45,18 +45,19 @@ pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwi // via integers, with 0 corresponding to C++ exceptions and 1 to C setjmp()/longjmp(). // Ideally, we'd be able to choose something unique for Rust, but for now, // we pretend to be C++ and implement the Itanium exception-handling ABI. - cfg_if::cfg_if! { + cfg_select! { // panic=abort is default for wasm targets. Because an unknown instruction is a load-time // error on wasm, instead of a runtime error like on traditional architectures, we never // want to codegen a `throw` instruction, as that would break users using runtimes that // don't yet support exceptions. The only time this first branch would be selected is if // the user explicitly opts in to wasm exceptions, via -Zbuild-std with -Cpanic=unwind. - if #[cfg(panic = "unwind")] { + panic = "unwind" => { // corresponds with llvm::WebAssembly::Tag::CPP_EXCEPTION // in llvm-project/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h const CPP_EXCEPTION_TAG: i32 = 0; core::arch::wasm::throw::<CPP_EXCEPTION_TAG>(exception.cast()) - } else { + } + _ => { let _ = exception; core::arch::wasm::unreachable() } |
