mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 20:46:48 +00:00
Auto merge of #117072 - betrusted-io:unwinding-crate-support, r=cuviper
Use `unwinding` crate for unwinding on Xous platform This patch adds support for using [unwinding](https://github.com/nbdd0121/unwinding) on platforms where libunwinding isn't viable. An example of such a platform is `riscv32imac-unknown-xous-elf`. ### Background The Rust project maintains a fork of llvm at [llvm-project](https://github.com/rust-lang/llvm-project/) where it applies patches on top of the llvm project. This mostly seems to be to get unwinding support for the SGX project, and there may be other patches that I'm unaware of. There is a lot of machinery in the build system to support compiling `libunwind` on other platforms, and I needed to add additional patches to llvm in order to add support for Xous. Rather than continuing down this path, it seemed much easier to use a Rust-based library. The `unwinding` crate by `@nbdd0121` fits this description perfectly. ### Future work This could potentially replace the custom patches for `libunwind` on other platforms such as SGX, and could enable unwinding support on many more exotic platforms. ### Anti-goals This is not designed to replace `libunwind` on tier-one platforms or those where unwinding support already exists. There is already a well-established approach for unwinding there. Instead, this aims to enable unwinding on new platforms where C++ code may be difficult to compile.
This commit is contained in:
commit
84a554cda9
12
Cargo.lock
12
Cargo.lock
@ -5892,6 +5892,18 @@ dependencies = [
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
"unwinding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unwinding"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -14,7 +14,7 @@ pub fn target() -> Target {
|
||||
cpu: "generic-rv32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
features: "+m,+a,+c".into(),
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
panic_strategy: PanicStrategy::Unwind,
|
||||
relocation_model: RelocModel::Static,
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -49,6 +49,7 @@ cfg_if::cfg_if! {
|
||||
} else if #[cfg(any(
|
||||
all(target_family = "windows", target_env = "gnu"),
|
||||
target_os = "psp",
|
||||
target_os = "xous",
|
||||
target_os = "solid_asp3",
|
||||
all(target_family = "unix", not(target_os = "espidf")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
|
@ -28,6 +28,7 @@ cfg_if::cfg_if! {
|
||||
} else if #[cfg(any(
|
||||
all(target_family = "windows", target_env = "gnu"),
|
||||
target_os = "psp",
|
||||
target_os = "xous",
|
||||
target_os = "solid_asp3",
|
||||
all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
|
@ -7,6 +7,28 @@ use crate::marker::PhantomData;
|
||||
use crate::os::xous::ffi::Error as XousError;
|
||||
use crate::path::{self, PathBuf};
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[cfg(feature = "panic_unwind")]
|
||||
mod eh_unwinding {
|
||||
pub(crate) struct EhFrameFinder(usize /* eh_frame */);
|
||||
pub(crate) static mut EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder(0);
|
||||
impl EhFrameFinder {
|
||||
pub(crate) unsafe fn init(&mut self, eh_frame: usize) {
|
||||
unsafe {
|
||||
EH_FRAME_SETTINGS.0 = eh_frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe impl unwind::EhFrameFinder for EhFrameFinder {
|
||||
fn find(&self, _pc: usize) -> Option<unwind::FrameInfo> {
|
||||
Some(unwind::FrameInfo {
|
||||
text_base: None,
|
||||
kind: unwind::FrameInfoKind::EhFrame(self.0),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
mod c_compat {
|
||||
use crate::os::xous::ffi::exit;
|
||||
@ -20,7 +42,12 @@ mod c_compat {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _start() {
|
||||
pub extern "C" fn _start(eh_frame: usize) {
|
||||
#[cfg(feature = "panic_unwind")]
|
||||
unsafe {
|
||||
super::eh_unwinding::EH_FRAME_SETTINGS.init(eh_frame);
|
||||
unwind::set_custom_eh_frame_finder(&super::eh_unwinding::EH_FRAME_SETTINGS).ok();
|
||||
}
|
||||
exit(unsafe { main() });
|
||||
}
|
||||
|
||||
|
@ -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 @@ 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)
|
||||
|
@ -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" {
|
||||
|
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) }
|
||||
}
|
@ -372,6 +372,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
|
||||
"unicode-security",
|
||||
"unicode-width",
|
||||
"unicode-xid",
|
||||
"unwinding",
|
||||
"valuable",
|
||||
"version_check",
|
||||
"wasi",
|
||||
|
Loading…
Reference in New Issue
Block a user