#![allow(private_no_mangle_fns)]
+use alloc::boxed::Box;
use core::any::Any;
use core::ptr;
-use alloc::boxed::Box;
-use unwind as uw;
+use crate::dwarf::eh::{self, EHAction, EHContext};
use libc::{c_int, uintptr_t};
-use crate::dwarf::eh::{self, EHContext, EHAction};
+use unwind as uw;
#[repr(C)]
struct Exception {
let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception;
return uw::_Unwind_RaiseException(exception_param) as u32;
- extern "C" fn exception_cleanup(_unwind_code: uw::_Unwind_Reason_Code,
- exception: *mut uw::_Unwind_Exception) {
+ extern "C" fn exception_cleanup(
+ _unwind_code: uw::_Unwind_Reason_Code,
+ exception: *mut uw::_Unwind_Exception,
+ ) {
unsafe {
let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
}
0x4d4f5a_00_52555354
}
-
// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
// and TargetLowering::getExceptionSelectorRegister() for each architecture,
// then mapped to DWARF register numbers via register definition tables
#[cfg(target_arch = "hexagon")]
const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
+#[cfg(target_arch = "riscv64")]
+const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
+
// The following code is based on GCC's C and C++ personality routines. For reference, see:
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
match eh_action {
EHAction::None |
EHAction::Cleanup(_) => return continue_unwind(exception_object, context),
- EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
+ EHAction::Catch(_) => {
+ // EHABI requires the personality routine to update the
+ // SP value in the barrier cache of the exception object.
+ (*exception_object).private[5] =
+ uw::_Unwind_GetGR(context, uw::UNWIND_SP_REG);
+ return uw::_URC_HANDLER_FOUND;
+ }
EHAction::Terminate => return uw::_URC_FAILURE,
}
} else {
}
}
-unsafe fn find_eh_action(context: *mut uw::_Unwind_Context, foreign_exception: bool)
- -> Result<EHAction, ()>
-{
+unsafe fn find_eh_action(
+ context: *mut uw::_Unwind_Context,
+ foreign_exception: bool,
+) -> Result<EHAction, ()> {
let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
let mut ip_before_instr: c_int = 0;
let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
}
// See docs in the `unwind` module.
-#[cfg(all(target_os="windows", any(target_arch = "x86", target_arch = "x86_64"), target_env="gnu"))]
+#[cfg(all(
+ target_os = "windows",
+ any(target_arch = "x86", target_arch = "x86_64"),
+ target_env = "gnu"
+))]
#[lang = "eh_unwind_resume"]
#[unwind(allowed)]
unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! {
// implementation of stack unwinding is (for now) deferred to libgcc_eh, however
// Rust crates use these Rust-specific entry points to avoid potential clashes
// with any GCC runtime.
-#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
+#[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))]
pub mod eh_frame_registry {
extern "C" {
fn __register_frame_info(eh_frame_begin: *const u8, object: *mut u8);
}
#[no_mangle]
- pub unsafe extern "C" fn rust_eh_unregister_frames(eh_frame_begin: *const u8,
- object: *mut u8) {
+ pub unsafe extern "C" fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8) {
__deregister_frame_info(eh_frame_begin, object);
}
}