From 04453c56259c2f167e74cbfa4ce3e3d6b9a289bb Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 21 May 2013 20:27:45 +0000 Subject: Fix MIPS n32 cancellation in static libc (bug 15506). --- ports/ChangeLog.mips | 17 ++++ .../unix/sysv/linux/mips/mips64/n32/sysdep.h | 2 - .../unix/sysv/linux/mips/mips64/n64/sysdep.h | 2 - .../sysv/linux/mips/mips64/nptl/sysdep-cancel.h | 90 +++++++++++++++++++--- 4 files changed, 95 insertions(+), 16 deletions(-) (limited to 'ports') diff --git a/ports/ChangeLog.mips b/ports/ChangeLog.mips index 2441127..df91f5a 100644 --- a/ports/ChangeLog.mips +++ b/ports/ChangeLog.mips @@ -1,3 +1,20 @@ +2013-05-21 Joseph Myers + + [BZ #15506] + * sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h + [!__PIC__] (PSEUDO): Undefine and redefine. + (PSEUDO_END): Undefine and redefine unconditionally. + [!__PIC__] (STK_PAD): Define to 0. + [!__PIC__] (STKOFF_GP): Do not define. + [!__PIC__] (STKSPACE): Define to (STKOFF_SVMSK + SZREG). + (PSEUDO_JMP): Define depending on [__PIC__]. + (CENABLE): Use PSEUDO_JMP in all definitions. + (CDISABLE): Likewise. + * sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h + (SYSCALL_ERROR_LABEL): Define unconditionally. + * sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h + (SYSCALL_ERROR_LABEL): Define unconditionally. + 2013-05-19 Joseph Myers * sysdeps/mips/mips32/libm-test-ulps: Update names of sincos diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h index 452c2c7..b2a9a95 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h @@ -39,9 +39,7 @@ /* We don't want the label for the error handler to be visible in the symbol table when we define it here. */ -#ifdef __PIC__ # define SYSCALL_ERROR_LABEL 99b -#endif #else /* ! __ASSEMBLER__ */ diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h index d16ed69..844a7e8 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h @@ -39,9 +39,7 @@ /* We don't want the label for the error handler to be visible in the symbol table when we define it here. */ -#ifdef __PIC__ # define SYSCALL_ERROR_LABEL 99b -#endif #else /* ! __ASSEMBLER__ */ diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h b/ports/sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h index 6565225..157cc38 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h @@ -101,13 +101,64 @@ cfi_same_value (gp); \ RESTORESTK; \ L(pseudo_end): - +#else +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + L(pseudo_start): \ + cfi_startproc; \ + cfi_adjust_cfa_offset (STKSPACE); \ + 99: RESTORESTK; \ + j __syscall_error; \ + .type __##syscall_name##_nocancel, @function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + SAVESTK; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + RESTORESTK; \ + ret; \ + cfi_endproc; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + ENTRY (name) \ + SAVESTK; \ + SINGLE_THREAD_P(v1); \ + bne zero, v1, L(pseudo_cancel); \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + RESTORESTK; \ + ret; \ + L(pseudo_cancel): \ + cfi_adjust_cfa_offset (STKSPACE); \ + REG_S ra, STKOFF_RA(sp); \ + cfi_rel_offset (ra, STKOFF_RA); \ + PUSHARGS_##args; /* save syscall args */ \ + CENABLE; \ + REG_S v0, STKOFF_SVMSK(sp); /* save mask */ \ + POPARGS_##args; /* restore syscall args */ \ + .set noreorder; \ + li v0, SYS_ify (syscall_name); \ + syscall; \ + .set reorder; \ + REG_S v0, STKOFF_SC_V0(sp); /* save syscall result */ \ + REG_S a3, STKOFF_SC_ERR(sp); /* save syscall error flag */ \ + REG_L a0, STKOFF_SVMSK(sp); /* pass mask as arg1 */ \ + CDISABLE; \ + REG_L a3, STKOFF_SC_ERR(sp); /* restore syscall error flag */ \ + REG_L ra, STKOFF_RA(sp); /* restore return address */ \ + REG_L v0, STKOFF_SC_V0(sp); /* restore syscall result */ \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + RESTORESTK; \ + L(pseudo_end): +#endif # undef PSEUDO_END # define PSEUDO_END(sym) cfi_endproc; .end sym; .size sym,.-sym -#endif - # define PUSHARGS_0 /* nothing to do */ # define PUSHARGS_1 PUSHARGS_0 REG_S a0, STKOFF_A0(sp); cfi_rel_offset (a0, STKOFF_A0); # define PUSHARGS_2 PUSHARGS_1 REG_S a1, STKOFF_A1(sp); cfi_rel_offset (a1, STKOFF_A1); @@ -126,7 +177,11 @@ /* Save an even number of slots. Should be 0 if an even number of slots are used below, or SZREG if an odd number are used. */ -# define STK_PAD SZREG +# ifdef __PIC__ +# define STK_PAD SZREG +# else +# define STK_PAD 0 +# endif /* Place values that we are more likely to use later in this sequence, i.e. closer to the SP at function entry. If you do that, the are more @@ -141,21 +196,32 @@ # define STKOFF_SC_V0 (STKOFF_RA + SZREG) /* Used if MT. */ # define STKOFF_SC_ERR (STKOFF_SC_V0 + SZREG) /* Used if MT. */ # define STKOFF_SVMSK (STKOFF_SC_ERR + SZREG) /* Used if MT. */ -# define STKOFF_GP (STKOFF_SVMSK + SZREG) /* Always used. */ -# define STKSPACE (STKOFF_GP + SZREG) +# ifdef __PIC__ +# define STKOFF_GP (STKOFF_SVMSK + SZREG) /* Always used. */ +# define STKSPACE (STKOFF_GP + SZREG) +# else +# define STKSPACE (STKOFF_SVMSK + SZREG) +# endif + # define SAVESTK PTR_SUBU sp, STKSPACE; cfi_adjust_cfa_offset(STKSPACE) # define RESTORESTK PTR_ADDU sp, STKSPACE; cfi_adjust_cfa_offset(-STKSPACE) +# ifdef __PIC__ +# define PSEUDO_JMP(sym) PTR_LA t9, sym; jalr t9 +# else +# define PSEUDO_JMP(sym) jal sym +# endif + # ifdef IS_IN_libpthread -# define CENABLE PTR_LA t9, __pthread_enable_asynccancel; jalr t9 -# define CDISABLE PTR_LA t9, __pthread_disable_asynccancel; jalr t9 +# define CENABLE PSEUDO_JMP (__pthread_enable_asynccancel) +# define CDISABLE PSEUDO_JMP (__pthread_disable_asynccancel) # elif defined IS_IN_librt -# define CENABLE PTR_LA t9, __librt_enable_asynccancel; jalr t9 -# define CDISABLE PTR_LA t9, __librt_disable_asynccancel; jalr t9 +# define CENABLE PSEUDO_JMP (__librt_enable_asynccancel) +# define CDISABLE PSEUDO_JMP (__librt_disable_asynccancel) # else -# define CENABLE PTR_LA t9, __libc_enable_asynccancel; jalr t9 -# define CDISABLE PTR_LA t9, __libc_disable_asynccancel; jalr t9 +# define CENABLE PSEUDO_JMP (__libc_enable_asynccancel) +# define CDISABLE PSEUDO_JMP (__libc_disable_asynccancel) # endif # ifndef __ASSEMBLER__ -- cgit v1.1