Skip to content

Commit 84a554c

Browse files
committed
Auto merge of rust-lang#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.
2 parents 2896841 + 0773afc commit 84a554c

File tree

10 files changed

+164
-8
lines changed

10 files changed

+164
-8
lines changed

Cargo.lock

+12
Original file line numberDiff line numberDiff line change
@@ -5892,6 +5892,18 @@ dependencies = [
58925892
"compiler_builtins",
58935893
"core",
58945894
"libc",
5895+
"unwinding",
5896+
]
5897+
5898+
[[package]]
5899+
name = "unwinding"
5900+
version = "0.2.1"
5901+
source = "registry+https://github.com/rust-lang/crates.io-index"
5902+
checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b"
5903+
dependencies = [
5904+
"compiler_builtins",
5905+
"gimli",
5906+
"rustc-std-workspace-core",
58955907
]
58965908

58975909
[[package]]

compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub fn target() -> Target {
1414
cpu: "generic-rv32".into(),
1515
max_atomic_width: Some(32),
1616
features: "+m,+a,+c".into(),
17-
panic_strategy: PanicStrategy::Abort,
17+
panic_strategy: PanicStrategy::Unwind,
1818
relocation_model: RelocModel::Static,
1919
..Default::default()
2020
},

library/panic_unwind/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ cfg_if::cfg_if! {
4949
} else if #[cfg(any(
5050
all(target_family = "windows", target_env = "gnu"),
5151
target_os = "psp",
52+
target_os = "xous",
5253
target_os = "solid_asp3",
5354
all(target_family = "unix", not(target_os = "espidf")),
5455
all(target_vendor = "fortanix", target_env = "sgx"),

library/std/src/sys/personality/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ cfg_if::cfg_if! {
2828
} else if #[cfg(any(
2929
all(target_family = "windows", target_env = "gnu"),
3030
target_os = "psp",
31+
target_os = "xous",
3132
target_os = "solid_asp3",
3233
all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re")),
3334
all(target_vendor = "fortanix", target_env = "sgx"),

library/std/src/sys/xous/os.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@ use crate::marker::PhantomData;
77
use crate::os::xous::ffi::Error as XousError;
88
use crate::path::{self, PathBuf};
99

10+
#[cfg(not(test))]
11+
#[cfg(feature = "panic_unwind")]
12+
mod eh_unwinding {
13+
pub(crate) struct EhFrameFinder(usize /* eh_frame */);
14+
pub(crate) static mut EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder(0);
15+
impl EhFrameFinder {
16+
pub(crate) unsafe fn init(&mut self, eh_frame: usize) {
17+
unsafe {
18+
EH_FRAME_SETTINGS.0 = eh_frame;
19+
}
20+
}
21+
}
22+
unsafe impl unwind::EhFrameFinder for EhFrameFinder {
23+
fn find(&self, _pc: usize) -> Option<unwind::FrameInfo> {
24+
Some(unwind::FrameInfo {
25+
text_base: None,
26+
kind: unwind::FrameInfoKind::EhFrame(self.0),
27+
})
28+
}
29+
}
30+
}
31+
1032
#[cfg(not(test))]
1133
mod c_compat {
1234
use crate::os::xous::ffi::exit;
@@ -20,7 +42,12 @@ mod c_compat {
2042
}
2143

2244
#[no_mangle]
23-
pub extern "C" fn _start() {
45+
pub extern "C" fn _start(eh_frame: usize) {
46+
#[cfg(feature = "panic_unwind")]
47+
unsafe {
48+
super::eh_unwinding::EH_FRAME_SETTINGS.init(eh_frame);
49+
unwind::set_custom_eh_frame_finder(&super::eh_unwinding::EH_FRAME_SETTINGS).ok();
50+
}
2451
exit(unsafe { main() });
2552
}
2653

library/unwind/Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ doc = false
1515

1616
[dependencies]
1717
core = { path = "../core" }
18-
libc = { version = "0.2.79", features = ['rustc-dep-of-std'], default-features = false }
18+
libc = { version = "0.2.140", features = ['rustc-dep-of-std'], default-features = false }
1919
compiler_builtins = "0.1.0"
2020
cfg-if = "1.0"
2121

22+
[target.'cfg(target_os = "xous")'.dependencies]
23+
unwinding = { version = "0.2.1", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false }
24+
2225
[features]
2326

2427
# Only applies for Linux and Fuchsia targets

library/unwind/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ cfg_if::cfg_if! {
2626
))] {
2727
mod libunwind;
2828
pub use libunwind::*;
29+
} else if #[cfg(target_os = "xous")] {
30+
mod unwinding;
31+
pub use unwinding::*;
2932
} else {
3033
// no unwinder on the system!
3134
// - wasm32 (not emscripten, which is "unix" family)

library/unwind/src/libunwind.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ pub type _Unwind_Exception_Cleanup_Fn =
103103
// and RFC 2841
104104
#[cfg_attr(
105105
any(
106-
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
106+
all(
107+
feature = "llvm-libunwind",
108+
any(target_os = "fuchsia", target_os = "linux", target_os = "xous")
109+
),
107110
all(target_os = "windows", target_env = "gnu", target_abi = "llvm")
108111
),
109112
link(name = "unwind", kind = "static", modifiers = "-bundle")
@@ -134,7 +137,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe
134137
pub use _Unwind_Action::*;
135138

136139
#[cfg_attr(
137-
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
140+
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
138141
link(name = "unwind", kind = "static", modifiers = "-bundle")
139142
)]
140143
extern "C" {
@@ -192,7 +195,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe
192195
pub const UNWIND_IP_REG: c_int = 15;
193196

194197
#[cfg_attr(
195-
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
198+
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
196199
link(name = "unwind", kind = "static", modifiers = "-bundle")
197200
)]
198201
extern "C" {
@@ -258,14 +261,14 @@ cfg_if::cfg_if! {
258261
if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
259262
// Not 32-bit iOS
260263
#[cfg_attr(
261-
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
264+
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
262265
link(name = "unwind", kind = "static", modifiers = "-bundle")
263266
)]
264267
extern "C-unwind" {
265268
pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
266269
}
267270
#[cfg_attr(
268-
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
271+
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
269272
link(name = "unwind", kind = "static", modifiers = "-bundle")
270273
)]
271274
extern "C" {

library/unwind/src/unwinding.rs

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#![allow(nonstandard_style)]
2+
3+
use libc::{c_int, c_void};
4+
5+
#[repr(C)]
6+
#[derive(Copy, Clone, PartialEq)]
7+
pub enum _Unwind_Action {
8+
_UA_SEARCH_PHASE = 1,
9+
_UA_CLEANUP_PHASE = 2,
10+
_UA_HANDLER_FRAME = 4,
11+
_UA_FORCE_UNWIND = 8,
12+
_UA_END_OF_STACK = 16,
13+
}
14+
pub use _Unwind_Action::*;
15+
16+
#[repr(C)]
17+
#[derive(Debug, Copy, Clone, PartialEq)]
18+
pub enum _Unwind_Reason_Code {
19+
_URC_NO_REASON = 0,
20+
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
21+
_URC_FATAL_PHASE2_ERROR = 2,
22+
_URC_FATAL_PHASE1_ERROR = 3,
23+
_URC_NORMAL_STOP = 4,
24+
_URC_END_OF_STACK = 5,
25+
_URC_HANDLER_FOUND = 6,
26+
_URC_INSTALL_CONTEXT = 7,
27+
_URC_CONTINUE_UNWIND = 8,
28+
_URC_FAILURE = 9, // used only by ARM EHABI
29+
}
30+
pub use _Unwind_Reason_Code::*;
31+
32+
pub use unwinding::abi::UnwindContext;
33+
pub use unwinding::abi::UnwindException;
34+
pub enum _Unwind_Context {}
35+
36+
pub use unwinding::custom_eh_frame_finder::{
37+
set_custom_eh_frame_finder, EhFrameFinder, FrameInfo, FrameInfoKind,
38+
};
39+
40+
pub type _Unwind_Exception_Class = u64;
41+
pub type _Unwind_Word = *const u8;
42+
pub type _Unwind_Ptr = *const u8;
43+
44+
pub const unwinder_private_data_size: usize = core::mem::size_of::<UnwindException>()
45+
- core::mem::size_of::<_Unwind_Exception_Class>()
46+
- core::mem::size_of::<_Unwind_Exception_Cleanup_Fn>();
47+
48+
pub type _Unwind_Exception_Cleanup_Fn =
49+
extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
50+
51+
#[repr(C)]
52+
pub struct _Unwind_Exception {
53+
pub exception_class: _Unwind_Exception_Class,
54+
pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
55+
pub private: [_Unwind_Word; unwinder_private_data_size],
56+
}
57+
58+
pub unsafe fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr {
59+
let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
60+
unwinding::abi::_Unwind_GetDataRelBase(ctx) as _Unwind_Ptr
61+
}
62+
63+
pub unsafe fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr {
64+
let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
65+
unwinding::abi::_Unwind_GetTextRelBase(ctx) as _Unwind_Ptr
66+
}
67+
68+
pub unsafe fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr {
69+
let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
70+
unwinding::abi::_Unwind_GetRegionStart(ctx) as _Unwind_Ptr
71+
}
72+
73+
pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
74+
let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
75+
unwinding::abi::_Unwind_SetGR(ctx, reg_index, value as usize)
76+
}
77+
78+
pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word) {
79+
let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
80+
unwinding::abi::_Unwind_SetIP(ctx, value as usize)
81+
}
82+
83+
pub unsafe fn _Unwind_GetIPInfo(
84+
ctx: *mut _Unwind_Context,
85+
ip_before_insn: *mut c_int,
86+
) -> _Unwind_Word {
87+
let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
88+
let ip_before_insn = unsafe { &mut *(ip_before_insn as *mut c_int) };
89+
unsafe { &*(unwinding::abi::_Unwind_GetIPInfo(ctx, ip_before_insn) as _Unwind_Word) }
90+
}
91+
92+
pub unsafe fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void {
93+
let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
94+
unwinding::abi::_Unwind_GetLanguageSpecificData(ctx)
95+
}
96+
97+
pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
98+
let exception = unsafe { &mut *(exception as *mut UnwindException) };
99+
unsafe { core::mem::transmute(unwinding::abi::_Unwind_RaiseException(exception)) }
100+
}
101+
102+
pub unsafe fn _Unwind_DeleteException(exception: *mut _Unwind_Exception) {
103+
let exception = unsafe { &mut *(exception as *mut UnwindException) };
104+
unsafe { unwinding::abi::_Unwind_DeleteException(exception) }
105+
}

src/tools/tidy/src/deps.rs

+1
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
372372
"unicode-security",
373373
"unicode-width",
374374
"unicode-xid",
375+
"unwinding",
375376
"valuable",
376377
"version_check",
377378
"wasi",

0 commit comments

Comments
 (0)