From 7477bc5b6f4faf276dd444fad98fcdabf8973cf7 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 6 Aug 2023 13:15:09 +0100 Subject: [PATCH] Adjust ABI safety requirement --- src/abi.rs | 22 +++--- src/panic_handler.rs | 5 +- src/unwinder/mod.rs | 158 +++++++++++++++++++++++-------------------- 3 files changed, 97 insertions(+), 88 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 9c89f2c..ff22f47 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -60,11 +60,11 @@ impl UnwindAction { pub type UnwindExceptionCleanupFn = unsafe extern "C" fn(UnwindReasonCode, *mut UnwindException); -pub type UnwindStopFn = extern "C" fn( +pub type UnwindStopFn = unsafe extern "C" fn( c_int, UnwindAction, u64, - &mut UnwindException, + *mut UnwindException, &mut UnwindContext<'_>, *mut c_void, ) -> UnwindReasonCode; @@ -87,11 +87,11 @@ pub struct UnwindContext<'a> { phantom: core::marker::PhantomData<&'a ()>, } -pub type PersonalityRoutine = extern "C" fn( +pub type PersonalityRoutine = unsafe extern "C" fn( c_int, UnwindAction, u64, - &mut UnwindException, + *mut UnwindException, &mut UnwindContext<'_>, ) -> UnwindReasonCode; @@ -134,17 +134,17 @@ binding! { extern "C" fn _Unwind_GetTextRelBase(unwind_ctx: &UnwindContext<'_>) -> usize; extern "C" fn _Unwind_GetDataRelBase(unwind_ctx: &UnwindContext<'_>) -> usize; extern "C" fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void; - extern "C-unwind" fn _Unwind_RaiseException( - exception: &mut UnwindException, + extern "C-unwind" [unsafe] fn _Unwind_RaiseException( + exception: *mut UnwindException, ) -> UnwindReasonCode; - extern "C-unwind" fn _Unwind_ForcedUnwind( - exception: &mut UnwindException, + extern "C-unwind" [unsafe] fn _Unwind_ForcedUnwind( + exception: *mut UnwindException, stop: UnwindStopFn, stop_arg: *mut c_void, ) -> UnwindReasonCode; - extern "C-unwind" fn _Unwind_Resume(exception: &mut UnwindException) -> !; - extern "C-unwind" fn _Unwind_Resume_or_Rethrow( - exception: &mut UnwindException, + extern "C-unwind" [unsafe] fn _Unwind_Resume(exception: *mut UnwindException) -> !; + extern "C-unwind" [unsafe] fn _Unwind_Resume_or_Rethrow( + exception: *mut UnwindException, ) -> UnwindReasonCode; extern "C" [unsafe] fn _Unwind_DeleteException(exception: *mut UnwindException); extern "C-unwind" fn _Unwind_Backtrace( diff --git a/src/panic_handler.rs b/src/panic_handler.rs index 5ba13a6..1d07768 100644 --- a/src/panic_handler.rs +++ b/src/panic_handler.rs @@ -59,10 +59,7 @@ fn stack_trace() { struct CallbackData { counter: usize, } - extern "C" fn callback( - unwind_ctx: &UnwindContext<'_>, - arg: *mut c_void, - ) -> UnwindReasonCode { + extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode { let data = unsafe { &mut *(arg as *mut CallbackData) }; data.counter += 1; eprintln!( diff --git a/src/unwinder/mod.rs b/src/unwinder/mod.rs index d650db7..5bcc383 100644 --- a/src/unwinder/mod.rs +++ b/src/unwinder/mod.rs @@ -149,8 +149,8 @@ macro_rules! try2 { #[inline(never)] #[no_mangle] -pub extern "C-unwind" fn _Unwind_RaiseException( - exception: &mut UnwindException, +pub unsafe extern "C-unwind" fn _Unwind_RaiseException( + exception: *mut UnwindException, ) -> UnwindReasonCode { with_context(|saved_ctx| { // Phase 1: Search for handler @@ -159,17 +159,19 @@ pub extern "C-unwind" fn _Unwind_RaiseException( loop { if let Some(frame) = try1!(Frame::from_context(&ctx, signal)) { if let Some(personality) = frame.personality() { - let result = personality( - 1, - UnwindAction::SEARCH_PHASE, - exception.exception_class, - exception, - &mut UnwindContext { - frame: Some(&frame), - ctx: &mut ctx, - signal, - }, - ); + let result = unsafe { + personality( + 1, + UnwindAction::SEARCH_PHASE, + (*exception).exception_class, + exception, + &mut UnwindContext { + frame: Some(&frame), + ctx: &mut ctx, + signal, + }, + ) + }; match result { UnwindReasonCode::CONTINUE_UNWIND => (), @@ -189,8 +191,10 @@ pub extern "C-unwind" fn _Unwind_RaiseException( // Disambiguate normal frame and signal frame. let handler_cfa = ctx[Arch::SP] - signal as usize; - exception.private_1 = None; - exception.private_2 = handler_cfa; + unsafe { + (*exception).private_1 = None; + (*exception).private_2 = handler_cfa; + } let code = raise_exception_phase2(exception, saved_ctx, handler_cfa); match code { @@ -201,7 +205,7 @@ pub extern "C-unwind" fn _Unwind_RaiseException( } fn raise_exception_phase2( - exception: &mut UnwindException, + exception: *mut UnwindException, ctx: &mut Context, handler_cfa: usize, ) -> UnwindReasonCode { @@ -210,22 +214,24 @@ fn raise_exception_phase2( if let Some(frame) = try2!(Frame::from_context(ctx, signal)) { let frame_cfa = ctx[Arch::SP] - signal as usize; if let Some(personality) = frame.personality() { - let code = personality( - 1, - UnwindAction::CLEANUP_PHASE - | if frame_cfa == handler_cfa { - UnwindAction::HANDLER_FRAME - } else { - UnwindAction::empty() + let code = unsafe { + personality( + 1, + UnwindAction::CLEANUP_PHASE + | if frame_cfa == handler_cfa { + UnwindAction::HANDLER_FRAME + } else { + UnwindAction::empty() + }, + (*exception).exception_class, + exception, + &mut UnwindContext { + frame: Some(&frame), + ctx, + signal, }, - exception.exception_class, - exception, - &mut UnwindContext { - frame: Some(&frame), - ctx, - signal, - }, - ); + ) + }; match code { UnwindReasonCode::CONTINUE_UNWIND => (), @@ -247,14 +253,16 @@ fn raise_exception_phase2( #[inline(never)] #[no_mangle] -pub extern "C-unwind" fn _Unwind_ForcedUnwind( - exception: &mut UnwindException, +pub unsafe extern "C-unwind" fn _Unwind_ForcedUnwind( + exception: *mut UnwindException, stop: UnwindStopFn, stop_arg: *mut c_void, ) -> UnwindReasonCode { with_context(|ctx| { - exception.private_1 = Some(stop); - exception.private_2 = stop_arg as _; + unsafe { + (*exception).private_1 = Some(stop); + (*exception).private_2 = stop_arg as _; + } let code = force_unwind_phase2(exception, ctx, stop, stop_arg); match code { @@ -265,7 +273,7 @@ pub extern "C-unwind" fn _Unwind_ForcedUnwind( } fn force_unwind_phase2( - exception: &mut UnwindException, + exception: *mut UnwindException, ctx: &mut Context, stop: UnwindStopFn, stop_arg: *mut c_void, @@ -274,24 +282,26 @@ fn force_unwind_phase2( loop { let frame = try2!(Frame::from_context(ctx, signal)); - let code = stop( - 1, - UnwindAction::FORCE_UNWIND - | UnwindAction::END_OF_STACK - | if frame.is_none() { - UnwindAction::END_OF_STACK - } else { - UnwindAction::empty() + let code = unsafe { + stop( + 1, + UnwindAction::FORCE_UNWIND + | UnwindAction::END_OF_STACK + | if frame.is_none() { + UnwindAction::END_OF_STACK + } else { + UnwindAction::empty() + }, + (*exception).exception_class, + exception, + &mut UnwindContext { + frame: frame.as_ref(), + ctx, + signal, }, - exception.exception_class, - exception, - &mut UnwindContext { - frame: frame.as_ref(), - ctx, - signal, - }, - stop_arg, - ); + stop_arg, + ) + }; match code { UnwindReasonCode::NO_REASON => (), _ => return UnwindReasonCode::FATAL_PHASE2_ERROR, @@ -299,17 +309,19 @@ fn force_unwind_phase2( if let Some(frame) = frame { if let Some(personality) = frame.personality() { - let code = personality( - 1, - UnwindAction::FORCE_UNWIND | UnwindAction::CLEANUP_PHASE, - exception.exception_class, - exception, - &mut UnwindContext { - frame: Some(&frame), - ctx, - signal, - }, - ); + let code = unsafe { + personality( + 1, + UnwindAction::FORCE_UNWIND | UnwindAction::CLEANUP_PHASE, + (*exception).exception_class, + exception, + &mut UnwindContext { + frame: Some(&frame), + ctx, + signal, + }, + ) + }; match code { UnwindReasonCode::CONTINUE_UNWIND => (), @@ -331,15 +343,15 @@ fn force_unwind_phase2( #[inline(never)] #[no_mangle] -pub extern "C-unwind" fn _Unwind_Resume(exception: &mut UnwindException) -> ! { +pub unsafe extern "C-unwind" fn _Unwind_Resume(exception: *mut UnwindException) -> ! { with_context(|ctx| { - let code = match exception.private_1 { + let code = match unsafe { (*exception).private_1 } { None => { - let handler_cfa = exception.private_2; + let handler_cfa = unsafe { (*exception).private_2 }; raise_exception_phase2(exception, ctx, handler_cfa) } Some(stop) => { - let stop_arg = exception.private_2 as _; + let stop_arg = unsafe { (*exception).private_2 as _ }; force_unwind_phase2(exception, ctx, stop, stop_arg) } }; @@ -351,16 +363,16 @@ pub extern "C-unwind" fn _Unwind_Resume(exception: &mut UnwindException) -> ! { #[inline(never)] #[no_mangle] -pub extern "C-unwind" fn _Unwind_Resume_or_Rethrow( - exception: &mut UnwindException, +pub unsafe extern "C-unwind" fn _Unwind_Resume_or_Rethrow( + exception: *mut UnwindException, ) -> UnwindReasonCode { - let stop = match exception.private_1 { - None => return _Unwind_RaiseException(exception), + let stop = match unsafe { (*exception).private_1 } { + None => return unsafe { _Unwind_RaiseException(exception) }, Some(v) => v, }; with_context(|ctx| { - let stop_arg = exception.private_2 as _; + let stop_arg = unsafe { (*exception).private_2 as _ }; let code = force_unwind_phase2(exception, ctx, stop, stop_arg); assert!(code == UnwindReasonCode::INSTALL_CONTEXT);