summaryrefslogtreecommitdiff
path: root/toolchain/uClibc/patches-0.9.33.2/611-mips_syscall_error_argument.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain/uClibc/patches-0.9.33.2/611-mips_syscall_error_argument.patch')
-rw-r--r--toolchain/uClibc/patches-0.9.33.2/611-mips_syscall_error_argument.patch99
1 files changed, 99 insertions, 0 deletions
diff --git a/toolchain/uClibc/patches-0.9.33.2/611-mips_syscall_error_argument.patch b/toolchain/uClibc/patches-0.9.33.2/611-mips_syscall_error_argument.patch
new file mode 100644
index 0000000..87ef8ba
--- /dev/null
+++ b/toolchain/uClibc/patches-0.9.33.2/611-mips_syscall_error_argument.patch
@@ -0,0 +1,99 @@
+commit 2952c70804b48bb5c87eea21df5e401969dc4ec1
+Author: Kevin Cernekee <cernekee@gmail.com>
+Date: Tue Jun 5 15:05:20 2012 -0700
+
+ MIPS: Use $a0 instead of $v0 for __syscall_error() argument
+
+ $a0 is saved across _dl_runtime_resolve(); $v0 is not. Unfortunately,
+ __syscall_error() uses $v0 for its argument, not $a0 as is the MIPS ABI
+ standard. This means that if lazy binding was used for __syscall_error(),
+ the errno value in $v0 could get corrupted.
+
+ The problem can be easily seen in testcases where syscalls in librt fail;
+ when librt tries to call __syscall_error() in libc, the argument gets
+ lost and errno gets set to a bogus value:
+
+ # ./tst-mqueue1 ; echo $?
+ mq_receive on O_WRONLY mqd_t did not fail with EBADF: Unknown error 2004684208
+ 1
+ # ./tst-mqueue2 ; echo $?
+ mq_timedreceive with too small msg_len did not fail with EMSGSIZE: Unknown error 1997360560
+ 1
+ # ./tst-mqueue4 ; echo $?
+ mq_timedsend did not fail with ETIMEDOUT: Unknown error 2008747440
+ 1
+
+ When _dl_runtime_resolve() was taken out of the equation, the same test
+ cases passed:
+
+ # LD_BIND_NOW=y ./tst-mqueue1 ; echo $?
+ 0
+ # LD_BIND_NOW=y ./tst-mqueue2 ; echo $?
+ 0
+ # LD_BIND_NOW=y ./tst-mqueue4 ; echo $?
+ 0
+
+ Changing __syscall_error() to look at $a0 instead of $v0 fixed the
+ problem.
+
+ (Note that there is also a "__syscall_error.c" file which presumably
+ uses the standard C calling conventions, but I do not think it is used
+ on MIPS.)
+
+ Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
+ Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
+
+commit 3c58d95d918c7e2fda374c37a52f81b34b81e4ca
+Author: Kevin Cernekee <cernekee@gmail.com>
+Date: Tue Jun 5 15:05:19 2012 -0700
+
+ MIPS: Convert __syscall_error() callers to use $a0 for argument
+
+ Some callers passed the first argument in $v0, while others used $a0.
+ Change the callers to use $a0 consistently.
+
+ Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
+ Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
+
+--- a/libc/sysdeps/linux/mips/vfork.S
++++ b/libc/sysdeps/linux/mips/vfork.S
+@@ -84,6 +84,7 @@ NESTED(__vfork,FRAMESZ,sp)
+
+ /* Something bad happened -- no child created. */
+ L(error):
++ move a0, v0
+ #ifdef __PIC__
+ PTR_LA t9, __syscall_error
+ RESTORE_GP64
+--- a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h
++++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h
+@@ -31,7 +31,7 @@
+ # undef PSEUDO
+ # define PSEUDO(name, syscall_name, args) \
+ .align 2; \
+- 99: \
++ 99: move a0, v0; \
+ PTR_LA t9,__syscall_error; \
+ /* manual cpreturn. */ \
+ REG_L gp, STKOFF_GP(sp); \
+--- a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S
++++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S
+@@ -80,6 +80,7 @@ NESTED(__vfork,FRAMESZ,sp)
+
+ /* Something bad happened -- no child created. */
+ L(error):
++ move a0, v0
+ #ifdef __PIC__
+ PTR_LA t9, __syscall_error
+ RESTORE_GP64
+--- a/libc/sysdeps/linux/mips/syscall_error.S
++++ b/libc/sysdeps/linux/mips/syscall_error.S
+@@ -43,7 +43,7 @@ ENTRY(__syscall_error)
+ #ifdef __PIC__
+ SAVE_GP(GPOFF)
+ #endif
+- REG_S v0, V0OFF(sp)
++ REG_S a0, V0OFF(sp)
+ REG_S ra, RAOFF(sp)
+
+ /* Find our per-thread errno address */