summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/mips
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2014-01-29 18:58:56 +0100
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2014-02-02 21:35:50 +0100
commit70a04a287a2875c82e6822c36e071afba5b63a62 (patch)
treed7df1a2e331e69fd3e3f306084a1eeea5eb6faf0 /libc/sysdeps/linux/mips
parentd31846a1b993cfe4b7d983db0e5c140dac3b0220 (diff)
libc: mips: Fix setjmp/longjmp for MIPS64 N64 ABI
When booting a Linux system with qemu-system-mips64 the execution of $(pwd) in the ash shell triggers a segmentation fault. Ash uses setjmp/longjmp for exception handling. After looking at the glibc implementation, I found some differences, with this patch tries to resolve. Now the system boots up fine and no segmentation faults occur. The global pointer should be restored and the types for the register values should be wide enough. See: http://www.cygwin.com/ml/libc-alpha/2003-03/msg00363.html Signed-off-by: Waldemar Brodkorb <wbx@openadk.org> Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Diffstat (limited to 'libc/sysdeps/linux/mips')
-rw-r--r--libc/sysdeps/linux/mips/bits/setjmp.h14
-rw-r--r--libc/sysdeps/linux/mips/setjmp.S1
-rw-r--r--libc/sysdeps/linux/mips/setjmp_aux.c8
3 files changed, 15 insertions, 8 deletions
diff --git a/libc/sysdeps/linux/mips/bits/setjmp.h b/libc/sysdeps/linux/mips/bits/setjmp.h
index 4d2a26ea4..375e537ae 100644
--- a/libc/sysdeps/linux/mips/bits/setjmp.h
+++ b/libc/sysdeps/linux/mips/bits/setjmp.h
@@ -25,13 +25,19 @@
#include <sgidefs.h>
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+#define ptrsize void *
+#else
+#define ptrsize long long
+#endif
+
typedef struct
{
/* Program counter. */
- void * __pc;
+ ptrsize __pc;
/* Stack pointer. */
- void * __sp;
+ ptrsize __sp;
/* Callee-saved registers s0 through s7. */
#if _MIPS_SIM == _MIPS_SIM_ABI32
@@ -41,10 +47,10 @@ typedef struct
#endif
/* The frame pointer. */
- void * __fp;
+ ptrsize __fp;
/* The global pointer. */
- void * __gp;
+ ptrsize __gp;
/* Floating point status register. */
int __fpc_csr;
diff --git a/libc/sysdeps/linux/mips/setjmp.S b/libc/sysdeps/linux/mips/setjmp.S
index 6d80a3190..59b76cca6 100644
--- a/libc/sysdeps/linux/mips/setjmp.S
+++ b/libc/sysdeps/linux/mips/setjmp.S
@@ -52,6 +52,7 @@ __sigsetjmp:
PTR_LA t9, __sigsetjmp_aux
#if _MIPS_SIM != _MIPS_SIM_ABI32
.cpreturn
+ move a4, gp
#endif
jr t9
#else
diff --git a/libc/sysdeps/linux/mips/setjmp_aux.c b/libc/sysdeps/linux/mips/setjmp_aux.c
index 559fe4e6c..9cffcc66c 100644
--- a/libc/sysdeps/linux/mips/setjmp_aux.c
+++ b/libc/sysdeps/linux/mips/setjmp_aux.c
@@ -28,7 +28,7 @@
int
#if _MIPS_SIM == _MIPS_SIM_ABI64
-__sigsetjmp_aux (jmp_buf env, int savemask, long sp, long fp)
+__sigsetjmp_aux (jmp_buf env, int savemask, long long sp, long long fp, long long gp)
#else /* O32 || N32 */
__sigsetjmp_aux (jmp_buf env, int savemask, int sp, int fp)
#endif /* O32 || N32 */
@@ -62,14 +62,14 @@ __sigsetjmp_aux (jmp_buf env, int savemask, int sp, int fp)
#endif
/* .. and the stack pointer; */
- env[0].__jmpbuf[0].__sp = (void *) sp;
+ env[0].__jmpbuf[0].__sp = (ptrsize) sp;
/* .. and the FP; it'll be in s8. */
- env[0].__jmpbuf[0].__fp = (void *) fp;
+ env[0].__jmpbuf[0].__fp = (ptrsize) fp;
/* .. and the GP; */
#if _MIPS_SIM == _MIPS_SIM_ABI64
- __asm__ __volatile__ ("sd $gp, %0" : : "m" (env[0].__jmpbuf[0].__gp));
+ env[0].__jmpbuf[0].__gp = (ptrsize) gp;
#else
__asm__ __volatile__ ("sw $gp, %0" : : "m" (env[0].__jmpbuf[0].__gp));
#endif