diff options
| author | Sean Cross <sean@xobs.io> | 2023-11-05 21:33:43 +0800 |
|---|---|---|
| committer | Sean Cross <sean@xobs.io> | 2023-11-16 15:23:09 +0800 |
| commit | ee870d6c8262cf58e203cc144e228a42072abb79 (patch) | |
| tree | 68a08303d812660e880f58dccd7f88976261896c | |
| parent | 57fb1e643aa96da3c7024ff5a45859647f39ad5b (diff) | |
| download | rust-ee870d6c8262cf58e203cc144e228a42072abb79.tar.gz rust-ee870d6c8262cf58e203cc144e228a42072abb79.zip | |
unwind: add support for using `unwinding` crate
The `unwinding` crate supports processing unwinding data, and is written entirely in Rust. This allows it to be ported to new platforms more easily than using the llvm-based `libunwind`. While `libunwind` is very well supported on major targets, it is difficult to use on other targets. SGX is an example of this where Rust carries custom patches in order to enable backtrace support. This adds an alternative for supported architectures. Rather than providing a custom target, `unwinding` allows for a solution that is completely written in Rust. This adds `xous` as the first consumer, and forthcoming patches will modify libstd to take advantage of this. Signed-off-by: Sean Cross <sean@xobs.io>
| -rw-r--r-- | library/unwind/Cargo.toml | 5 | ||||
| -rw-r--r-- | library/unwind/src/lib.rs | 3 | ||||
| -rw-r--r-- | library/unwind/src/libunwind.rs | 13 | ||||
| -rw-r--r-- | library/unwind/src/unwinding.rs | 105 |
4 files changed, 120 insertions, 6 deletions
diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index 9aa552ed81a..b7418d1189c 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -15,10 +15,13 @@ doc = false [dependencies] core = { path = "../core" } -libc = { version = "0.2.79", features = ['rustc-dep-of-std'], default-features = false } +libc = { version = "0.2.140", features = ['rustc-dep-of-std'], default-features = false } compiler_builtins = "0.1.0" cfg-if = "1.0" +[target.'cfg(target_os = "xous")'.dependencies] +unwinding = { version = "0.2.1", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false } + [features] # Only applies for Linux and Fuchsia targets diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 335bded71c1..eeee98f754e 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -26,6 +26,9 @@ cfg_if::cfg_if! { ))] { mod libunwind; pub use libunwind::*; + } else if #[cfg(target_os = "xous")] { + mod unwinding; + pub use unwinding::*; } else { // no unwinder on the system! // - wasm32 (not emscripten, which is "unix" family) diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index dba64aa74ce..1b5f6f9dde3 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -103,7 +103,10 @@ pub type _Unwind_Exception_Cleanup_Fn = // and RFC 2841 #[cfg_attr( any( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + all( + feature = "llvm-libunwind", + any(target_os = "fuchsia", target_os = "linux", target_os = "xous") + ), all(target_os = "windows", target_env = "gnu", target_abi = "llvm") ), link(name = "unwind", kind = "static", modifiers = "-bundle") @@ -134,7 +137,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe pub use _Unwind_Action::*; #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] extern "C" { @@ -192,7 +195,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe pub const UNWIND_IP_REG: c_int = 15; #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] extern "C" { @@ -258,14 +261,14 @@ cfg_if::cfg_if! { if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { // Not 32-bit iOS #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] 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")), + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] extern "C" { diff --git a/library/unwind/src/unwinding.rs b/library/unwind/src/unwinding.rs new file mode 100644 index 00000000000..1a4187b2220 --- /dev/null +++ b/library/unwind/src/unwinding.rs @@ -0,0 +1,105 @@ +#![allow(nonstandard_style)] + +use libc::{c_int, c_void}; + +#[repr(C)] +#[derive(Copy, Clone, PartialEq)] +pub enum _Unwind_Action { + _UA_SEARCH_PHASE = 1, + _UA_CLEANUP_PHASE = 2, + _UA_HANDLER_FRAME = 4, + _UA_FORCE_UNWIND = 8, + _UA_END_OF_STACK = 16, +} +pub use _Unwind_Action::*; + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum _Unwind_Reason_Code { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8, + _URC_FAILURE = 9, // used only by ARM EHABI +} +pub use _Unwind_Reason_Code::*; + +pub use unwinding::abi::UnwindContext; +pub use unwinding::abi::UnwindException; +pub enum _Unwind_Context {} + +pub use unwinding::custom_eh_frame_finder::{ + set_custom_eh_frame_finder, EhFrameFinder, FrameInfo, FrameInfoKind, +}; + +pub type _Unwind_Exception_Class = u64; +pub type _Unwind_Word = *const u8; +pub type _Unwind_Ptr = *const u8; + +pub const unwinder_private_data_size: usize = core::mem::size_of::<UnwindException>() + - core::mem::size_of::<_Unwind_Exception_Class>() + - core::mem::size_of::<_Unwind_Exception_Cleanup_Fn>(); + +pub type _Unwind_Exception_Cleanup_Fn = + extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception); + +#[repr(C)] +pub struct _Unwind_Exception { + pub exception_class: _Unwind_Exception_Class, + pub exception_cleanup: _Unwind_Exception_Cleanup_Fn, + pub private: [_Unwind_Word; unwinder_private_data_size], +} + +pub unsafe fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_GetDataRelBase(ctx) as _Unwind_Ptr +} + +pub unsafe fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_GetTextRelBase(ctx) as _Unwind_Ptr +} + +pub unsafe fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_GetRegionStart(ctx) as _Unwind_Ptr +} + +pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_SetGR(ctx, reg_index, value as usize) +} + +pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word) { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_SetIP(ctx, value as usize) +} + +pub unsafe fn _Unwind_GetIPInfo( + ctx: *mut _Unwind_Context, + ip_before_insn: *mut c_int, +) -> _Unwind_Word { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + let ip_before_insn = unsafe { &mut *(ip_before_insn as *mut c_int) }; + unsafe { &*(unwinding::abi::_Unwind_GetIPInfo(ctx, ip_before_insn) as _Unwind_Word) } +} + +pub unsafe fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_GetLanguageSpecificData(ctx) +} + +pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code { + let exception = unsafe { &mut *(exception as *mut UnwindException) }; + unsafe { core::mem::transmute(unwinding::abi::_Unwind_RaiseException(exception)) } +} + +pub unsafe fn _Unwind_DeleteException(exception: *mut _Unwind_Exception) { + let exception = unsafe { &mut *(exception as *mut UnwindException) }; + unsafe { unwinding::abi::_Unwind_DeleteException(exception) } +} |
