From ded4c0675d1dd3b6268ac94ff2c99ebb280815f9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 10 Jul 2014 19:28:45 +0000 Subject: uClibc: add a whole bunch of mips64 related fixes Signed-off-by: Felix Fietkau SVN-Revision: 41570 --- .../611-mips_syscall_error_argument.patch | 99 ++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 toolchain/uClibc/patches-0.9.33.2/611-mips_syscall_error_argument.patch (limited to 'toolchain/uClibc/patches-0.9.33.2/611-mips_syscall_error_argument.patch') 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 +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 + Signed-off-by: Bernhard Reutner-Fischer + +commit 3c58d95d918c7e2fda374c37a52f81b34b81e4ca +Author: Kevin Cernekee +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 + Signed-off-by: Bernhard Reutner-Fischer + +--- 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 */ -- cgit v1.1