diff --git a/include/tdep-aarch64/jmpbuf.h b/include/tdep-aarch64/jmpbuf.h index 8479bf2b..af033970 100644 --- a/include/tdep-aarch64/jmpbuf.h +++ b/include/tdep-aarch64/jmpbuf.h @@ -35,7 +35,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define _JB_STK_SHIFT 0 #else #define JB_SP 13 -#define JB_RP 14 +# if defined(__GLIBC__) +# define JB_RP 14 +# else /* assume MUSL */ +# define JB_RP 11 +# endif #define JB_MASK_SAVED 15 #define JB_MASK 16 #endif diff --git a/src/aarch64/longjmp.S b/src/aarch64/longjmp.S index a1b73f05..3164d446 100644 --- a/src/aarch64/longjmp.S +++ b/src/aarch64/longjmp.S @@ -25,9 +25,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ .global _UI_longjmp_cont .type _UI_longjmp_cont, @function _UI_longjmp_cont: -#if defined(__linux__) || defined(__QNX__) +#if defined(__GLIBC__) || defined(__QNX__) ret -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__linux__) .cfi_startproc /* * x0 - return address diff --git a/src/setjmp/siglongjmp.c b/src/setjmp/siglongjmp.c index 05e18176..e2813e7f 100644 --- a/src/setjmp/siglongjmp.c +++ b/src/setjmp/siglongjmp.c @@ -90,17 +90,24 @@ siglongjmp (sigjmp_buf env, int val) /* default to resuming without restoring signal-mask */ cont = &_UI_longjmp_cont; +#if defined(__aarch64__) && defined(__linux__) && !defined(__GLIBC__) + if (unw_set_reg (&c, UNW_REG_EH + 0, wp[22]) < 0 + || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0 + || unw_set_reg (&c, UNW_REG_EH + 19, wp[24]) < 0 + || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont)) + abort (); +#else /* !defined(__linux__) || defined(__GLIBC__) */ /* 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. */ -#ifdef __FreeBSD__ +# ifdef __FreeBSD__ if ((wp[JB_MASK_SAVED] & 0x1) == 0x1) -#else +# else if (!resume_restores_sigmask (&c, wp) && wp[JB_MASK_SAVED]) -#endif +# endif { /* sigmask was saved */ -#if defined(__linux__) || defined(__sun) +# if defined(__linux__) || defined(__sun) 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 @@ -111,12 +118,12 @@ siglongjmp (sigjmp_buf env, int val) || (_NSIG > 8 * sizeof (unw_word_t) && unw_set_reg (&c, UNW_REG_EH + 3, wp[JB_MASK + 1]) < 0)) abort (); -#elif defined(__FreeBSD__) +# elif defined(__FreeBSD__) if (unw_set_reg (&c, UNW_REG_EH + 2, (unw_word_t)&wp[JB_MASK]) < 0) abort(); -#else -#error Port me -#endif +# else +# error Port me +# endif cont = &_UI_siglongjmp_cont; } @@ -124,6 +131,7 @@ siglongjmp (sigjmp_buf env, int val) || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0 || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont)) abort (); +#endif /* defined(__linux__) && !defined(__GLIBC__) */ unw_resume (&c); diff --git a/tests/test-setjmp.c b/tests/test-setjmp.c index d2468ff0..51d01757 100644 --- a/tests/test-setjmp.c +++ b/tests/test-setjmp.c @@ -209,6 +209,7 @@ main (int argc, char **argv UNUSED) } /* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */ + memset (sigjbuf, 0, sizeof(*sigjbuf)); sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL); if (sigsetjmp (sigjbuf, 0)) {