This is the mail archive of the libc-ports@sources.redhat.com mailing list for the libc-ports project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix MIPS n32 cancellation in static libc (bug 15506)


Bug 15506 is missing cancellation wrappers in static MIPS n32 glibc
when GCC is configured with --with-mips-plt, as referred to by
<http://sourceware.org/ml/libc-ports/2012-02/msg00056.html> but with
apparently no bug report filed in Bugzilla at that time.

This patch fixes this by creating a non-PIC version of the n32/n64
sysdep-cancel.h PSEUDO macro.  Tested with NPTL tests for n32 (GCC
--with-mips-plt), where it fixes failures of tst-cancel21-static and
tst-cancel-wrappers.  Maciej, does this patch seem sane to you?

2013-05-20  Joseph Myers  <joseph@codesourcery.com>

	[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.

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__

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]