Commit 8d4d473c authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Russell King

[ARM PATCH] 1565/1: syscall macros clobbering returned error value

Patch from Nicolas Pitre

In both 2.5.70-rmk1 and 2.4.19-rmk7 the syscall macros are clobering
the returned error value when building library code.

Example code:

#include <linux/unistd.h>
#include <errno.h>
extern int fake_syscall(int x, int y, int z);
_syscall3(int, fake_syscall, int, x, int, y, int, z)

Current generated code:

fake_syscall:
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        str     lr, [sp, #-4]!
        swi     __NR_fake_syscall
        cmn     r0, #126
        ldrls   pc, [sp], #4
        bl      __errno_location
        rsb     r3, r0, #0
        str     r3, [r0, #0]
        mvn     r0, #0
        ldr     pc, [sp], #4

In the code above, whenever the return value is an error code, it
is lost due to the call to __errno_location. And because of the
asm("r0") constraint on the variable __res the compiler continues
using r0 for it even if it's now a pointer value.  errno ends up with
a totally bogus value.

With the patch below the above code becomes:

fake_syscall:
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        stmfd   sp!, {r4, lr}
        swi     __NR_fake_syscall
        cmn     r0, #126
        mov     r4, r0
        bls     .L3
        bl      __errno_location
        rsb     r3, r4, #0
        str     r3, [r0, #0]
        mvn     r4, #0
.L3:
        mov     r0, r4
        ldmfd   sp!, {r4, pc}

which is correct.

Oh and added a small estetic change for generated code too.
parent d009a345
...@@ -303,7 +303,7 @@ ...@@ -303,7 +303,7 @@
"swi 0\n\t" \ "swi 0\n\t" \
"pop {r7}" "pop {r7}"
#else #else
#define __syscall(name) "swi\t" __sys1(__NR_##name) "\n\t" #define __syscall(name) "swi\t" __sys1(__NR_##name) ""
#endif #endif
#endif #endif
...@@ -318,24 +318,28 @@ do { \ ...@@ -318,24 +318,28 @@ do { \
#define _syscall0(type,name) \ #define _syscall0(type,name) \
type name(void) { \ type name(void) { \
register long __res __asm__("r0"); \ register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
__syscall(name) \ __syscall(name) \
:"=r" (__res) \ : "=r" (__res_r0) \
: \ : \
: "lr"); \ : "lr"); \
__res = __res_r0; \
__syscall_return(type,__res); \ __syscall_return(type,__res); \
} }
#define _syscall1(type,name,type1,arg1) \ #define _syscall1(type,name,type1,arg1) \
type name(type1 arg1) { \ type name(type1 arg1) { \
register long __r0 __asm__("r0") = (long)arg1; \ register long __r0 __asm__("r0") = (long)arg1; \
register long __res __asm__("r0"); \ register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
__syscall(name) \ __syscall(name) \
: "=r" (__res) \ : "=r" (__res_r0) \
: "r" (__r0) \ : "r" (__r0) \
: "lr"); \ : "lr"); \
__res = __res_r0; \
__syscall_return(type,__res); \ __syscall_return(type,__res); \
} }
...@@ -343,12 +347,14 @@ type name(type1 arg1) { \ ...@@ -343,12 +347,14 @@ type name(type1 arg1) { \
type name(type1 arg1,type2 arg2) { \ type name(type1 arg1,type2 arg2) { \
register long __r0 __asm__("r0") = (long)arg1; \ register long __r0 __asm__("r0") = (long)arg1; \
register long __r1 __asm__("r1") = (long)arg2; \ register long __r1 __asm__("r1") = (long)arg2; \
register long __res __asm__("r0"); \ register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
__syscall(name) \ __syscall(name) \
: "=r" (__res) \ : "=r" (__res_r0) \
: "r" (__r0),"r" (__r1) \ : "r" (__r0),"r" (__r1) \
: "lr"); \ : "lr"); \
__res = __res_r0; \
__syscall_return(type,__res); \ __syscall_return(type,__res); \
} }
...@@ -358,12 +364,14 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \ ...@@ -358,12 +364,14 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \
register long __r0 __asm__("r0") = (long)arg1; \ register long __r0 __asm__("r0") = (long)arg1; \
register long __r1 __asm__("r1") = (long)arg2; \ register long __r1 __asm__("r1") = (long)arg2; \
register long __r2 __asm__("r2") = (long)arg3; \ register long __r2 __asm__("r2") = (long)arg3; \
register long __res __asm__("r0"); \ register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
__syscall(name) \ __syscall(name) \
: "=r" (__res) \ : "=r" (__res_r0) \
: "r" (__r0),"r" (__r1),"r" (__r2) \ : "r" (__r0),"r" (__r1),"r" (__r2) \
: "lr"); \ : "lr"); \
__res = __res_r0; \
__syscall_return(type,__res); \ __syscall_return(type,__res); \
} }
...@@ -374,12 +382,14 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ ...@@ -374,12 +382,14 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
register long __r1 __asm__("r1") = (long)arg2; \ register long __r1 __asm__("r1") = (long)arg2; \
register long __r2 __asm__("r2") = (long)arg3; \ register long __r2 __asm__("r2") = (long)arg3; \
register long __r3 __asm__("r3") = (long)arg4; \ register long __r3 __asm__("r3") = (long)arg4; \
register long __res __asm__("r0"); \ register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
__syscall(name) \ __syscall(name) \
: "=r" (__res) \ : "=r" (__res_r0) \
: "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3) \ : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3) \
: "lr"); \ : "lr"); \
__res = __res_r0; \
__syscall_return(type,__res); \ __syscall_return(type,__res); \
} }
...@@ -391,12 +401,14 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ ...@@ -391,12 +401,14 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
register long __r2 __asm__("r2") = (long)arg3; \ register long __r2 __asm__("r2") = (long)arg3; \
register long __r3 __asm__("r3") = (long)arg4; \ register long __r3 __asm__("r3") = (long)arg4; \
register long __r4 __asm__("r4") = (long)arg5; \ register long __r4 __asm__("r4") = (long)arg5; \
register long __res __asm__("r0"); \ register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
__syscall(name) \ __syscall(name) \
: "=r" (__res) \ : "=r" (__res_r0) \
: "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4) \ : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4) \
: "lr"); \ : "lr"); \
__res = __res_r0; \
__syscall_return(type,__res); \ __syscall_return(type,__res); \
} }
...@@ -408,12 +420,14 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 ...@@ -408,12 +420,14 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
register long __r3 __asm__("r3") = (long)arg4; \ register long __r3 __asm__("r3") = (long)arg4; \
register long __r4 __asm__("r4") = (long)arg5; \ register long __r4 __asm__("r4") = (long)arg5; \
register long __r5 __asm__("r5") = (long)arg6; \ register long __r5 __asm__("r5") = (long)arg6; \
register long __res __asm__("r0"); \ register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
__syscall(name) \ __syscall(name) \
: "=r" (__res) \ : "=r" (__res_r0) \
: "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5) \ : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5) \
: "lr"); \ : "lr"); \
__res = __res_r0; \
__syscall_return(type,__res); \ __syscall_return(type,__res); \
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment