On arm and arm64, the setjmp/longjmp implementations (in both msvcrt.dll
and ucrtbase.dll) require binaries to have proper SEH information. On
arm, we can get around this by passing NULL as the frame/ctx parameter
to _setjmp, but that doesn't work on arm64.

Work around it by providing a custom implementation of the functions
in libmingwex instead.

The arm32 implementation is authored by André Hentschel.

Signed-off-by: Martin Storsjö <mar...@martin.st>
Signed-off-by: André Hentschel <n...@dawncrow.de>
---
 mingw-w64-crt/misc/mingw_getsp.S | 99 ++++++++++++++++++++++++++++++++++++++++
 mingw-w64-headers/crt/setjmp.h   |  4 ++
 2 files changed, 103 insertions(+)

diff --git a/mingw-w64-crt/misc/mingw_getsp.S b/mingw-w64-crt/misc/mingw_getsp.S
index 97510c8..5d224d1 100644
--- a/mingw-w64-crt/misc/mingw_getsp.S
+++ b/mingw-w64-crt/misc/mingw_getsp.S
@@ -51,3 +51,102 @@ __MINGW_USYMBOL(longjmp):
   jmp *__imp__longjmp
 #endif
 #endif /* !(defined(_ARM_) || defined(__arm__)) */
+
+#if defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__)
+       .globl __MINGW_USYMBOL(__mingw_setjmp)
+       .def    __MINGW_USYMBOL(__mingw_setjmp);        .scl    2;      .type   
32;     .endef
+__MINGW_USYMBOL(__mingw_setjmp):
+#if defined(_ARM_) || defined(__arm__)
+       mov     r1,  #0
+       str     r1,  [r0]            /* jmp_buf->Frame */
+       str     r4,  [r0, #0x4]      /* jmp_buf->R4 */
+       str     r5,  [r0, #0x8]      /* jmp_buf->R5 */
+       str     r6,  [r0, #0xc]      /* jmp_buf->R6 */
+       str     r7,  [r0, #0x10]     /* jmp_buf->R7 */
+       str     r8,  [r0, #0x14]     /* jmp_buf->R8 */
+       str     r9,  [r0, #0x18]     /* jmp_buf->R9 */
+       str     r10, [r0, #0x1c]     /* jmp_buf->R10 */
+       str     r11, [r0, #0x20]     /* jmp_buf->R11 */
+       str     sp,  [r0, #0x24]     /* jmp_buf->Sp */
+       str     lr,  [r0, #0x28]     /* jmp_buf->Pc */
+       vmrs    r2,  fpscr
+       str     r2,  [r0, #0x2c]     /* jmp_buf->Fpscr */
+       vstr    d8,  [r0, #0x30]     /* jmp_buf->D[0] */
+       vstr    d9,  [r0, #0x38]     /* jmp_buf->D[1] */
+       vstr    d10, [r0, #0x40]     /* jmp_buf->D[2] */
+       vstr    d11, [r0, #0x48]     /* jmp_buf->D[3] */
+       vstr    d12, [r0, #0x50]     /* jmp_buf->D[4] */
+       vstr    d13, [r0, #0x58]     /* jmp_buf->D[5] */
+       vstr    d14, [r0, #0x60]     /* jmp_buf->D[6] */
+       vstr    d15, [r0, #0x68]     /* jmp_buf->D[7] */
+       mov     r0,  #0
+       bx      lr
+#elif defined(_ARM64_) || defined(__aarch64__)
+       str     xzr, [x0]             /* jmp_buf->Frame */
+       stp     x19, x20, [x0, #0x10] /* jmp_buf->X19, X20 */
+       stp     x21, x22, [x0, #0x20] /* jmp_buf->X21, X22 */
+       stp     x23, x24, [x0, #0x30] /* jmp_buf->X23, X24 */
+       stp     x25, x26, [x0, #0x40] /* jmp_buf->X25, X26 */
+       stp     x27, x28, [x0, #0x50] /* jmp_buf->X27, X28 */
+       stp     x29, x30, [x0, #0x60] /* jmp_buf->Fp,  Lr  */
+       mov     x2,  sp
+       str     x2,       [x0, #0x70] /* jmp_buf->Sp */
+       mrs     x2,  fpcr
+       str     w2,       [x0, #0x78] /* jmp_buf->Fpcr */
+       mrs     x2,  fpsr
+       str     w2,       [x0, #0x7c] /* jmp_buf->Fpsr */
+       stp     d8,  d9,  [x0, #0x80] /* jmp_buf->D[0-1] */
+       stp     d10, d11, [x0, #0x90] /* jmp_buf->D[2-3] */
+       stp     d12, d13, [x0, #0xa0] /* jmp_buf->D[4-5] */
+       stp     d14, d15, [x0, #0xb0] /* jmp_buf->D[6-7] */
+       mov     x0,  #0
+       ret
+#endif
+
+       .globl __MINGW_USYMBOL(__mingw_longjmp)
+       .def    __MINGW_USYMBOL(__mingw_longjmp);       .scl    2;      .type   
32;     .endef
+__MINGW_USYMBOL(__mingw_longjmp):
+#if defined(_ARM_) || defined(__arm__)
+       ldr     r4,  [r0, #0x4]      /* jmp_buf->R4 */
+       ldr     r5,  [r0, #0x8]      /* jmp_buf->R5 */
+       ldr     r6,  [r0, #0xc]      /* jmp_buf->R6 */
+       ldr     r7,  [r0, #0x10]     /* jmp_buf->R7 */
+       ldr     r8,  [r0, #0x14]     /* jmp_buf->R8 */
+       ldr     r9,  [r0, #0x18]     /* jmp_buf->R9 */
+       ldr     r10, [r0, #0x1c]     /* jmp_buf->R10 */
+       ldr     r11, [r0, #0x20]     /* jmp_buf->R11 */
+       ldr     sp,  [r0, #0x24]     /* jmp_buf->Sp */
+       ldr     r2,  [r0, #0x28]     /* jmp_buf->Pc */
+       ldr     r3,  [r0, #0x2c]     /* jmp_buf->Fpscr */
+       vmsr    fpscr, r3
+       vldr    d8,  [r0, #0x30]     /* jmp_buf->D[0] */
+       vldr    d9,  [r0, #0x38]     /* jmp_buf->D[1] */
+       vldr    d10, [r0, #0x40]     /* jmp_buf->D[2] */
+       vldr    d11, [r0, #0x48]     /* jmp_buf->D[3] */
+       vldr    d12, [r0, #0x50]     /* jmp_buf->D[4] */
+       vldr    d13, [r0, #0x58]     /* jmp_buf->D[5] */
+       vldr    d14, [r0, #0x60]     /* jmp_buf->D[6] */
+       vldr    d15, [r0, #0x68]     /* jmp_buf->D[7] */
+       mov     r0,  r1              /* retval */
+       bx      r2
+#elif defined(_ARM64_) || defined(__aarch64__)
+       ldp     x19, x20, [x0, #0x10] /* jmp_buf->X19, X20 */
+       ldp     x21, x22, [x0, #0x20] /* jmp_buf->X21, X22 */
+       ldp     x23, x24, [x0, #0x30] /* jmp_buf->X23, X24 */
+       ldp     x25, x26, [x0, #0x40] /* jmp_buf->X25, X26 */
+       ldp     x27, x28, [x0, #0x50] /* jmp_buf->X27, X28 */
+       ldp     x29, x30, [x0, #0x60] /* jmp_buf->Fp,  Lr  */
+       ldr     x2,       [x0, #0x70] /* jmp_buf->Sp */
+       mov     sp,  x2
+       ldr     w2,       [x0, #0x78] /* jmp_buf->Fpcr */
+       msr     fpcr, x2
+       ldr     w2,       [x0, #0x7c] /* jmp_buf->Fpsr */
+       msr     fpsr, x2
+       ldp     d8,  d9,  [x0, #0x80] /* jmp_buf->D[0-1] */
+       ldp     d10, d11, [x0, #0x90] /* jmp_buf->D[2-3] */
+       ldp     d12, d13, [x0, #0xa0] /* jmp_buf->D[4-5] */
+       ldp     d14, d15, [x0, #0xb0] /* jmp_buf->D[6-7] */
+       mov     x0,  x1               /* retval */
+       ret
+#endif
+#endif
diff --git a/mingw-w64-headers/crt/setjmp.h b/mingw-w64-headers/crt/setjmp.h
index ec4b013..fc79f10 100644
--- a/mingw-w64-headers/crt/setjmp.h
+++ b/mingw-w64-headers/crt/setjmp.h
@@ -213,6 +213,10 @@ void * __cdecl __attribute__ ((__nothrow__)) mingw_getsp 
(void);
 #  ifndef _INC_SETJMPEX
 #    if defined(_X86_) || defined(__i386__)
 #      define setjmp(BUF) _setjmp3((BUF), NULL)
+#    elif defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__)
+#      define setjmp(BUF) __mingw_setjmp((BUF))
+#      define longjmp __mingw_longjmp
+  int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) 
__mingw_setjmp(jmp_buf _Buf);
 #    else
 #     if (__MINGW_GCC_VERSION < 40702)
 #      define setjmp(BUF) _setjmp((BUF), mingw_getsp())
-- 
2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to