100 lines
3.4 KiB
Diff
100 lines
3.4 KiB
Diff
|
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 */
|