Kernel exception: fixed top level finally. (#70) #71

Merged
sb10q merged 1 commits from pca006132/artiq-zynq:exception into master 2020-07-23 14:48:45 +08:00
2 changed files with 18 additions and 8 deletions

View File

@ -551,6 +551,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor
static_cast<void *>(exception_object));
int frame_count = 0;
unw_word_t prev_sp = 0x0;
// Walk each frame until we reach where search phase said to stop.
while (true) {
// Ask libunwind to get next frame (skip over first which is
@ -576,6 +577,10 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor
unw_word_t sp;
unw_proc_info_t frameInfo;
__unw_get_reg(cursor, UNW_REG_SP, &sp);
if (sp == prev_sp) {
return _URC_END_OF_STACK;
}
prev_sp = sp;
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): __unw_get_proc_info "

View File

@ -128,8 +128,15 @@ pub unsafe fn artiq_personality(state: uw::_Unwind_State,
let exception = &exception_info.exception.unwrap();
if search_phase {
match eh_action {
EHAction::None |
EHAction::Cleanup(_) => return continue_unwind(exception_object, context),
EHAction::None => return continue_unwind(exception_object, context),
// Actually, cleanup should not return handler found, this is to workaround
// the issue of terminating directly when no catch cause is found while
// having some cleanup routines defined by finally.
// The best way to handle this is to force unwind the stack in the raise
// function when end of stack is reached, and call terminate at the end of
// the unwind. Unfortunately, there is no forced unwind function defined
// for EHABI, and I have no idea how to implement that, so this is a hack.
EHAction::Cleanup(_) => 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.
@ -195,10 +202,9 @@ static mut INFLIGHT: ExceptionInfo = ExceptionInfo {
};
pub unsafe extern fn raise(exception: *const Exception) -> ! {
// Zing! The Exception<'a> to Exception<'static> transmute is not really sound in case
// the exception is ever captured. Fortunately, they currently aren't, and we save
// on the hassle of having to allocate exceptions somewhere except on stack.
trace!("Trying to raise exception");
// FIXME: unsound transmute
// This would cause stack memory corruption.
INFLIGHT.exception = Some(mem::transmute::<Exception, Exception<'static>>(*exception));
INFLIGHT.handled = false;
@ -219,9 +225,8 @@ pub unsafe extern fn raise(exception: *const Exception) -> ! {
pub unsafe extern fn reraise() -> ! {
use cslice::AsCSlice;
trace!("Re-raise");
// current implementation uses raise as _Unwind_Resume is not working now
// would debug that later.
// Reraise is basically cxa_rethrow, which calls _Unwind_Resume_or_Rethrow,
// which for EHABI would always call _Unwind_RaiseException.
match INFLIGHT.exception {
Some(ref exception) => raise(exception),
None => raise(&Exception {