Просмотр исходного кода

mips: fix setjmp() on n32/n64 (.cpreturn, not .cprestore)

The setjmp() entry point (bsd-setjmp.S) tail-calls __sigsetjmp.  For
n32/n64 it set up the GOT pointer with .cpsetup but then used .cprestore
before the jump.  .cprestore is the o32 mechanism (it emits an
sw $gp,offset($sp) against a cprestore slot that was never established
here, clobbering the caller's stack); the n32/n64 counterpart that
restores $gp for a tail-call is .cpreturn, which is what the sibling
_setjmp entry point (bsd-_setjmp.S) correctly uses.

The result was that setjmp() (the function entry, as opposed to the
__sigsetjmp macro) corrupted state on n32/n64, and a later libc call
faulted - tst-setjmp crashed with SIGSEGV/SIGILL on all mips64 variants
while o32 (which takes the .cpload path) passed.

Use .cpreturn, matching bsd-_setjmp.S.  Verified on qemu-system-mips64
(mips64-be-n32): tst-setjmp passes.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
ramin 4 дней назад
Родитель
Сommit
7c10829ea6
1 измененных файлов с 1 добавлено и 1 удалено
  1. 1 1
      libc/sysdeps/linux/mips/bsd-setjmp.S

+ 1 - 1
libc/sysdeps/linux/mips/bsd-setjmp.S

@@ -43,7 +43,7 @@ setjmp:
 #else	/* N32 */
 	.cpsetup t9, v0, setjmp
 	PTR_LA	t9, __sigsetjmp
-	.cprestore
+	.cpreturn
 #endif	/* N32 */
 #endif
 	li	a1, 1		/* Pass a second argument of one.  */