Adjust ABI safety requirement

This commit is contained in:
Gary Guo 2023-08-06 13:15:09 +01:00
parent f5ef1d145e
commit 7477bc5b6f
3 changed files with 97 additions and 88 deletions

View File

@ -60,11 +60,11 @@ impl UnwindAction {
pub type UnwindExceptionCleanupFn = unsafe extern "C" fn(UnwindReasonCode, *mut UnwindException); 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, c_int,
UnwindAction, UnwindAction,
u64, u64,
&mut UnwindException, *mut UnwindException,
&mut UnwindContext<'_>, &mut UnwindContext<'_>,
*mut c_void, *mut c_void,
) -> UnwindReasonCode; ) -> UnwindReasonCode;
@ -87,11 +87,11 @@ pub struct UnwindContext<'a> {
phantom: core::marker::PhantomData<&'a ()>, phantom: core::marker::PhantomData<&'a ()>,
} }
pub type PersonalityRoutine = extern "C" fn( pub type PersonalityRoutine = unsafe extern "C" fn(
c_int, c_int,
UnwindAction, UnwindAction,
u64, u64,
&mut UnwindException, *mut UnwindException,
&mut UnwindContext<'_>, &mut UnwindContext<'_>,
) -> UnwindReasonCode; ) -> UnwindReasonCode;
@ -134,17 +134,17 @@ binding! {
extern "C" fn _Unwind_GetTextRelBase(unwind_ctx: &UnwindContext<'_>) -> usize; extern "C" fn _Unwind_GetTextRelBase(unwind_ctx: &UnwindContext<'_>) -> usize;
extern "C" fn _Unwind_GetDataRelBase(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" fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
extern "C-unwind" fn _Unwind_RaiseException( extern "C-unwind" [unsafe] fn _Unwind_RaiseException(
exception: &mut UnwindException, exception: *mut UnwindException,
) -> UnwindReasonCode; ) -> UnwindReasonCode;
extern "C-unwind" fn _Unwind_ForcedUnwind( extern "C-unwind" [unsafe] fn _Unwind_ForcedUnwind(
exception: &mut UnwindException, exception: *mut UnwindException,
stop: UnwindStopFn, stop: UnwindStopFn,
stop_arg: *mut c_void, stop_arg: *mut c_void,
) -> UnwindReasonCode; ) -> UnwindReasonCode;
extern "C-unwind" fn _Unwind_Resume(exception: &mut UnwindException) -> !; extern "C-unwind" [unsafe] fn _Unwind_Resume(exception: *mut UnwindException) -> !;
extern "C-unwind" fn _Unwind_Resume_or_Rethrow( extern "C-unwind" [unsafe] fn _Unwind_Resume_or_Rethrow(
exception: &mut UnwindException, exception: *mut UnwindException,
) -> UnwindReasonCode; ) -> UnwindReasonCode;
extern "C" [unsafe] fn _Unwind_DeleteException(exception: *mut UnwindException); extern "C" [unsafe] fn _Unwind_DeleteException(exception: *mut UnwindException);
extern "C-unwind" fn _Unwind_Backtrace( extern "C-unwind" fn _Unwind_Backtrace(

View File

@ -59,10 +59,7 @@ fn stack_trace() {
struct CallbackData { struct CallbackData {
counter: usize, counter: usize,
} }
extern "C" fn callback( extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode {
unwind_ctx: &UnwindContext<'_>,
arg: *mut c_void,
) -> UnwindReasonCode {
let data = unsafe { &mut *(arg as *mut CallbackData) }; let data = unsafe { &mut *(arg as *mut CallbackData) };
data.counter += 1; data.counter += 1;
eprintln!( eprintln!(

View File

@ -149,8 +149,8 @@ macro_rules! try2 {
#[inline(never)] #[inline(never)]
#[no_mangle] #[no_mangle]
pub extern "C-unwind" fn _Unwind_RaiseException( pub unsafe extern "C-unwind" fn _Unwind_RaiseException(
exception: &mut UnwindException, exception: *mut UnwindException,
) -> UnwindReasonCode { ) -> UnwindReasonCode {
with_context(|saved_ctx| { with_context(|saved_ctx| {
// Phase 1: Search for handler // Phase 1: Search for handler
@ -159,17 +159,19 @@ pub extern "C-unwind" fn _Unwind_RaiseException(
loop { loop {
if let Some(frame) = try1!(Frame::from_context(&ctx, signal)) { if let Some(frame) = try1!(Frame::from_context(&ctx, signal)) {
if let Some(personality) = frame.personality() { if let Some(personality) = frame.personality() {
let result = personality( let result = unsafe {
1, personality(
UnwindAction::SEARCH_PHASE, 1,
exception.exception_class, UnwindAction::SEARCH_PHASE,
exception, (*exception).exception_class,
&mut UnwindContext { exception,
frame: Some(&frame), &mut UnwindContext {
ctx: &mut ctx, frame: Some(&frame),
signal, ctx: &mut ctx,
}, signal,
); },
)
};
match result { match result {
UnwindReasonCode::CONTINUE_UNWIND => (), UnwindReasonCode::CONTINUE_UNWIND => (),
@ -189,8 +191,10 @@ pub extern "C-unwind" fn _Unwind_RaiseException(
// Disambiguate normal frame and signal frame. // Disambiguate normal frame and signal frame.
let handler_cfa = ctx[Arch::SP] - signal as usize; let handler_cfa = ctx[Arch::SP] - signal as usize;
exception.private_1 = None; unsafe {
exception.private_2 = handler_cfa; (*exception).private_1 = None;
(*exception).private_2 = handler_cfa;
}
let code = raise_exception_phase2(exception, saved_ctx, handler_cfa); let code = raise_exception_phase2(exception, saved_ctx, handler_cfa);
match code { match code {
@ -201,7 +205,7 @@ pub extern "C-unwind" fn _Unwind_RaiseException(
} }
fn raise_exception_phase2( fn raise_exception_phase2(
exception: &mut UnwindException, exception: *mut UnwindException,
ctx: &mut Context, ctx: &mut Context,
handler_cfa: usize, handler_cfa: usize,
) -> UnwindReasonCode { ) -> UnwindReasonCode {
@ -210,22 +214,24 @@ fn raise_exception_phase2(
if let Some(frame) = try2!(Frame::from_context(ctx, signal)) { if let Some(frame) = try2!(Frame::from_context(ctx, signal)) {
let frame_cfa = ctx[Arch::SP] - signal as usize; let frame_cfa = ctx[Arch::SP] - signal as usize;
if let Some(personality) = frame.personality() { if let Some(personality) = frame.personality() {
let code = personality( let code = unsafe {
1, personality(
UnwindAction::CLEANUP_PHASE 1,
| if frame_cfa == handler_cfa { UnwindAction::CLEANUP_PHASE
UnwindAction::HANDLER_FRAME | if frame_cfa == handler_cfa {
} else { UnwindAction::HANDLER_FRAME
UnwindAction::empty() } 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 { match code {
UnwindReasonCode::CONTINUE_UNWIND => (), UnwindReasonCode::CONTINUE_UNWIND => (),
@ -247,14 +253,16 @@ fn raise_exception_phase2(
#[inline(never)] #[inline(never)]
#[no_mangle] #[no_mangle]
pub extern "C-unwind" fn _Unwind_ForcedUnwind( pub unsafe extern "C-unwind" fn _Unwind_ForcedUnwind(
exception: &mut UnwindException, exception: *mut UnwindException,
stop: UnwindStopFn, stop: UnwindStopFn,
stop_arg: *mut c_void, stop_arg: *mut c_void,
) -> UnwindReasonCode { ) -> UnwindReasonCode {
with_context(|ctx| { with_context(|ctx| {
exception.private_1 = Some(stop); unsafe {
exception.private_2 = stop_arg as _; (*exception).private_1 = Some(stop);
(*exception).private_2 = stop_arg as _;
}
let code = force_unwind_phase2(exception, ctx, stop, stop_arg); let code = force_unwind_phase2(exception, ctx, stop, stop_arg);
match code { match code {
@ -265,7 +273,7 @@ pub extern "C-unwind" fn _Unwind_ForcedUnwind(
} }
fn force_unwind_phase2( fn force_unwind_phase2(
exception: &mut UnwindException, exception: *mut UnwindException,
ctx: &mut Context, ctx: &mut Context,
stop: UnwindStopFn, stop: UnwindStopFn,
stop_arg: *mut c_void, stop_arg: *mut c_void,
@ -274,24 +282,26 @@ fn force_unwind_phase2(
loop { loop {
let frame = try2!(Frame::from_context(ctx, signal)); let frame = try2!(Frame::from_context(ctx, signal));
let code = stop( let code = unsafe {
1, stop(
UnwindAction::FORCE_UNWIND 1,
| UnwindAction::END_OF_STACK UnwindAction::FORCE_UNWIND
| if frame.is_none() { | UnwindAction::END_OF_STACK
UnwindAction::END_OF_STACK | if frame.is_none() {
} else { UnwindAction::END_OF_STACK
UnwindAction::empty() } else {
UnwindAction::empty()
},
(*exception).exception_class,
exception,
&mut UnwindContext {
frame: frame.as_ref(),
ctx,
signal,
}, },
exception.exception_class, stop_arg,
exception, )
&mut UnwindContext { };
frame: frame.as_ref(),
ctx,
signal,
},
stop_arg,
);
match code { match code {
UnwindReasonCode::NO_REASON => (), UnwindReasonCode::NO_REASON => (),
_ => return UnwindReasonCode::FATAL_PHASE2_ERROR, _ => return UnwindReasonCode::FATAL_PHASE2_ERROR,
@ -299,17 +309,19 @@ fn force_unwind_phase2(
if let Some(frame) = frame { if let Some(frame) = frame {
if let Some(personality) = frame.personality() { if let Some(personality) = frame.personality() {
let code = personality( let code = unsafe {
1, personality(
UnwindAction::FORCE_UNWIND | UnwindAction::CLEANUP_PHASE, 1,
exception.exception_class, UnwindAction::FORCE_UNWIND | UnwindAction::CLEANUP_PHASE,
exception, (*exception).exception_class,
&mut UnwindContext { exception,
frame: Some(&frame), &mut UnwindContext {
ctx, frame: Some(&frame),
signal, ctx,
}, signal,
); },
)
};
match code { match code {
UnwindReasonCode::CONTINUE_UNWIND => (), UnwindReasonCode::CONTINUE_UNWIND => (),
@ -331,15 +343,15 @@ fn force_unwind_phase2(
#[inline(never)] #[inline(never)]
#[no_mangle] #[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| { with_context(|ctx| {
let code = match exception.private_1 { let code = match unsafe { (*exception).private_1 } {
None => { None => {
let handler_cfa = exception.private_2; let handler_cfa = unsafe { (*exception).private_2 };
raise_exception_phase2(exception, ctx, handler_cfa) raise_exception_phase2(exception, ctx, handler_cfa)
} }
Some(stop) => { 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) force_unwind_phase2(exception, ctx, stop, stop_arg)
} }
}; };
@ -351,16 +363,16 @@ pub extern "C-unwind" fn _Unwind_Resume(exception: &mut UnwindException) -> ! {
#[inline(never)] #[inline(never)]
#[no_mangle] #[no_mangle]
pub extern "C-unwind" fn _Unwind_Resume_or_Rethrow( pub unsafe extern "C-unwind" fn _Unwind_Resume_or_Rethrow(
exception: &mut UnwindException, exception: *mut UnwindException,
) -> UnwindReasonCode { ) -> UnwindReasonCode {
let stop = match exception.private_1 { let stop = match unsafe { (*exception).private_1 } {
None => return _Unwind_RaiseException(exception), None => return unsafe { _Unwind_RaiseException(exception) },
Some(v) => v, Some(v) => v,
}; };
with_context(|ctx| { 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); let code = force_unwind_phase2(exception, ctx, stop, stop_arg);
assert!(code == UnwindReasonCode::INSTALL_CONTEXT); assert!(code == UnwindReasonCode::INSTALL_CONTEXT);