mirror of
https://github.com/libunwind/libunwind.git
synced 2026-01-12 00:04:03 +08:00
Add setjmp support for aarch64-linux-musl
The MUSL libc setjmp/longjmp handling differs from the GNU libc setjmp/longjmp handling. It may not be possible to properly support sigsetjmp/siglongjmp on MUSL libc.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user