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>
This commit is contained in:
parent
57fb1e643a
commit
ee870d6c82
@ -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
|
||||
|
@ -26,6 +26,9 @@
|
||||
))] {
|
||||
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)
|
||||
|
@ -103,7 +103,10 @@ pub enum _Unwind_Context {}
|
||||
// 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 @@ pub enum _Unwind_Action {
|
||||
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 @@ enum _Unwind_VRS_DataRepresentation {
|
||||
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 @@ pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
|
||||
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" {
|
||||
|
105
library/unwind/src/unwinding.rs
Normal file
105
library/unwind/src/unwinding.rs
Normal file
@ -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) }
|
||||
}
|
Loading…
Reference in New Issue
Block a user