aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain/uClibc/patches-0.9.33.2/611-mips_syscall_error_argument.patch
blob: 87ef8bae879151f3f8e4bf19f86c90969893c90b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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  */