Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use unwinding crate for unwinding on Xous platform #117072

Merged
merged 7 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5914,6 +5914,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]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
},
Expand Down
1 change: 1 addition & 0 deletions library/panic_unwind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
1 change: 1 addition & 0 deletions library/std/src/sys/personality/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
29 changes: 28 additions & 1 deletion library/std/src/sys/xous/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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() });
}

Expand Down
5 changes: 4 additions & 1 deletion library/unwind/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions library/unwind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 8 additions & 5 deletions library/unwind/src/libunwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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" {
Expand Down Expand Up @@ -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" {
Expand Down Expand Up @@ -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" {
Expand Down
105 changes: 105 additions & 0 deletions library/unwind/src/unwinding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#![allow(nonstandard_style)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of these are available from unwinding::abi, can this be used instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that the callee uses raw pointers, so most of the functions here are casting pointers to references. The calling code could be modified to use references rather than pointers, but I didn't want to touch such fundamental structures.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine then. But at least change the pub fn to pub unsafe fn since they accept raw pointers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I've changed the signatures and verified that it still works.


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) }
}
1 change: 1 addition & 0 deletions src/tools/tidy/src/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"unicode-security",
"unicode-width",
"unicode-xid",
"unwinding",
"valuable",
"version_check",
"wasi",
Expand Down
Loading