diff options
author | Kevin Cernekee <cernekee@gmail.com> | 2012-06-05 15:05:20 -0700 |
---|---|---|
committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2012-06-06 09:36:34 +0200 |
commit | 2952c70804b48bb5c87eea21df5e401969dc4ec1 (patch) | |
tree | 4b76809d374429ba398bb1e266ac02528ebd39f2 /libc/sysdeps/linux | |
parent | 3c58d95d918c7e2fda374c37a52f81b34b81e4ca (diff) |
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>
Diffstat (limited to 'libc/sysdeps/linux')
-rw-r--r-- | libc/sysdeps/linux/mips/syscall_error.S | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/libc/sysdeps/linux/mips/syscall_error.S b/libc/sysdeps/linux/mips/syscall_error.S index 51a8efa5a..0cc20da2f 100644 --- 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 */ |