void _longjmp (jmp_buf env, int val) { extern int _UI_longjmp_cont; unw_context_t uc; unw_cursor_t c; unw_word_t sp; unw_word_t *wp = (unw_word_t *) env; if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0) abort (); do { if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) abort (); #ifdef __FreeBSD__ if (sp != wp[JB_SP] + sizeof(unw_word_t)) #else if (sp != wp[JB_SP]) #endif continue; if (!bsp_match (&c, wp)) continue; /* found the right frame: */ assert (UNW_NUM_EH_REGS >= 2); if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0 || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0 || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) &_UI_longjmp_cont)) abort (); unw_resume (&c); abort (); } while (unw_step (&c) > 0); abort (); }
void siglongjmp (sigjmp_buf env, int val) { unw_word_t *wp = (unw_word_t *) env; extern int _UI_siglongjmp_cont; extern int _UI_longjmp_cont; unw_context_t uc; unw_cursor_t c; unw_word_t sp; int *cont; if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0) abort (); do { if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) abort (); #ifdef __FreeBSD__ if (sp != wp[JB_SP] + sizeof(unw_word_t)) #else if (sp != wp[JB_SP]) #endif continue; if (!bsp_match (&c, wp)) continue; /* found the right frame: */ /* default to resuming without restoring signal-mask */ cont = &_UI_longjmp_cont; /* Order of evaluation is important here: if unw_resume() restores signal mask, we must set it up appropriately, even if wp[JB_MASK_SAVED] is FALSE. */ if (!resume_restores_sigmask (&c, wp) && wp[JB_MASK_SAVED]) { /* sigmask was saved */ if (UNW_NUM_EH_REGS < 4 || _NSIG >= 16 * sizeof (unw_word_t)) /* signal mask doesn't fit into EH arguments and we can't put it on the stack without overwriting something else... */ abort (); else if (unw_set_reg (&c, UNW_REG_EH + 2, wp[JB_MASK]) < 0 || (_NSIG > 8 * sizeof (unw_word_t) && unw_set_reg (&c, UNW_REG_EH + 3, wp[JB_MASK + 1]) < 0)) abort (); cont = &_UI_siglongjmp_cont; } if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0 || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0 || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont)) abort (); unw_resume (&c); abort (); } while (unw_step (&c) > 0); abort (); }