From 319cbbf633ae60d7b4b89fcbb11a734f4d7d22f0 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Tue, 29 Aug 2017 18:31:08 +0100 Subject: MIPS/o32: Fix internal_syscall5/6/7 Fix a commit cc25c8b4c119 ("New pthread rwlock that is more scalable.") regression and prevent uncontrolled stack space usage from happening when a 5-, 6- or 7-argument syscall wrapper is placed in a loop. The cause of the problem is the use of `alloca' in regular MIPS/Linux wrappers to force the use of the frame pointer register in any function using one or more of these wrappers. Using the frame pointer register is required so as not to break frame unwinding as the the stack pointer is lowered within the inline asm used by these wrappers to make room for the stack arguments, which 5-, 6- and 7-argument syscalls use with the o32 ABI. The regular MIPS/Linux wrappers are macros however, expanded inline, and stack allocations made with `alloca' are not discarded until the return of the function they are made in. Consequently if called in a loop, then virtual memory is wasted, and if the loop goes through enough iterations, then ultimately available memory can get exhausted causing the program to crash. Address the issue by replacing the inline code with standalone assembly functions, which rely on the compiler arranging syscall arguments according to the o32 function calling convention, which MIPS/Linux syscalls also use, except for the syscall number passed and the error flag returned. This way there is no need to fiddle with the stack pointer anymore and all that has to be handled in the new standalone functions is the special handling of the syscall number and the error flag. Redirect 5-, 6- or 7-argument MIPS16/Linux syscall wrappers to these new functions as well, so as to avoid an unnecessary double call the existing wrappers would cause with the new arrangement. [BZ #21956] * sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile [subdir = misc] (sysdep_routines): Remove `mips16-syscall5', `mips16-syscall6' and `mips16-syscall7'. (CFLAGS-mips16-syscall5.c, CFLAGS-mips16-syscall6.c) (CFLAGS-mips16-syscall7.c): Remove. * sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions (libc): Remove `__mips16_syscall5', `__mips16_syscall6' and `__mips16_syscall7'. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c (__mips16_syscall0): Rename `__mips16_syscall_return' to `__mips_syscall_return'. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c (__mips16_syscall1): Likewise. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c (__mips16_syscall2): Likewise. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c (__mips16_syscall3): Likewise. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c (__mips16_syscall4): Likewise. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c: Remove. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c: Remove. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c: Remove. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h (__mips16_syscall5): Expand to `__mips_syscall5' rather than `__mips16_syscall5'. Remove prototype. (__mips16_syscall6): Expand to `__mips_syscall6' rather than `__mips16_syscall6'. Remove prototype. (__mips16_syscall7): Expand to `__mips_syscall7' rather than `__mips16_syscall7'. Remove prototype. (__nomips16, __mips16_syscall_return): Move to... * sysdeps/unix/sysv/linux/mips/mips32/sysdep.h (__nomips16, __mips_syscall_return): ... here. [__mips16] (INTERNAL_SYSCALL_NCS): Rename `__mips16_syscall_return' to `__mips_syscall_return'. [__mips16] (INTERNAL_SYSCALL_MIPS16): Pass `number' to `internal_syscall##nr'. [!__mips16] (INTERNAL_SYSCALL): Pass `SYS_ify (name)' to `internal_syscall##nr'. (FORCE_FRAME_POINTER): Remove. (__mips_syscall5): New prototype. (internal_syscall5): Rewrite to call `__mips_syscall5'. (__mips_syscall6): New prototype. (internal_syscall6): Rewrite to call `__mips_syscall6'. (__mips_syscall7): New prototype. (internal_syscall7): Rewrite to call `__mips_syscall7'. * sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S: New file. * sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S: New file. * sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S: New file. * sysdeps/unix/sysv/linux/mips/mips32/Makefile [subdir = misc] (sysdep_routines): Add libc-do-syscall. * sysdeps/unix/sysv/linux/mips/mips32/Versions (libc): Add `__mips_syscall5', `__mips_syscall6' and `__mips_syscall7'. --- .../unix/sysv/linux/mips/mips32/mips16/Makefile | 6 +-- .../unix/sysv/linux/mips/mips32/mips16/Versions | 2 +- .../sysv/linux/mips/mips32/mips16/mips16-syscall.h | 44 ++++++---------------- .../linux/mips/mips32/mips16/mips16-syscall0.c | 3 +- .../linux/mips/mips32/mips16/mips16-syscall1.c | 3 +- .../linux/mips/mips32/mips16/mips16-syscall2.c | 3 +- .../linux/mips/mips32/mips16/mips16-syscall3.c | 3 +- .../linux/mips/mips32/mips16/mips16-syscall4.c | 3 +- .../linux/mips/mips32/mips16/mips16-syscall5.c | 33 ---------------- .../linux/mips/mips32/mips16/mips16-syscall6.c | 33 ---------------- .../linux/mips/mips32/mips16/mips16-syscall7.c | 33 ---------------- 11 files changed, 19 insertions(+), 147 deletions(-) delete mode 100644 sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c delete mode 100644 sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c delete mode 100644 sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c (limited to 'sysdeps/unix/sysv/linux/mips/mips32/mips16') diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile b/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile index fa9fcb7e6f..6869bf4f7c 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile @@ -1,13 +1,9 @@ ifeq ($(subdir),misc) sysdep_routines += mips16-syscall0 mips16-syscall1 mips16-syscall2 -sysdep_routines += mips16-syscall3 mips16-syscall4 mips16-syscall5 -sysdep_routines += mips16-syscall6 mips16-syscall7 +sysdep_routines += mips16-syscall3 mips16-syscall4 CFLAGS-mips16-syscall0.c += -fexceptions CFLAGS-mips16-syscall1.c += -fexceptions CFLAGS-mips16-syscall2.c += -fexceptions CFLAGS-mips16-syscall3.c += -fexceptions CFLAGS-mips16-syscall4.c += -fexceptions -CFLAGS-mips16-syscall5.c += -fexceptions -CFLAGS-mips16-syscall6.c += -fexceptions -CFLAGS-mips16-syscall7.c += -fexceptions endif diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions b/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions index 73bcfb566c..bb21747f44 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions @@ -1,6 +1,6 @@ libc { GLIBC_PRIVATE { __mips16_syscall0; __mips16_syscall1; __mips16_syscall2; __mips16_syscall3; - __mips16_syscall4; __mips16_syscall5; __mips16_syscall6; __mips16_syscall7; + __mips16_syscall4; } } diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h index 880e9908e8..2ade219c6e 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h @@ -19,19 +19,6 @@ #ifndef MIPS16_SYSCALL_H #define MIPS16_SYSCALL_H 1 -#define __nomips16 __attribute__ ((nomips16)) - -union __mips16_syscall_return - { - long long val; - struct - { - long v0; - long v1; - } - reg; - }; - long long __nomips16 __mips16_syscall0 (long number); #define __mips16_syscall0(dummy, number) \ __mips16_syscall0 ((long) (number)) @@ -61,29 +48,22 @@ long long __nomips16 __mips16_syscall4 (long a0, long a1, long a2, long a3, (long) (a3), \ (long) (number)) -long long __nomips16 __mips16_syscall5 (long a0, long a1, long a2, long a3, - long a4, - long number); +/* The remaining ones use regular MIPS wrappers. */ + #define __mips16_syscall5(a0, a1, a2, a3, a4, number) \ - __mips16_syscall5 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), (long) (a4), \ - (long) (number)) + __mips_syscall5 ((long) (a0), (long) (a1), (long) (a2), \ + (long) (a3), (long) (a4), \ + (long) (number)) -long long __nomips16 __mips16_syscall6 (long a0, long a1, long a2, long a3, - long a4, long a5, - long number); #define __mips16_syscall6(a0, a1, a2, a3, a4, a5, number) \ - __mips16_syscall6 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), (long) (a4), (long) (a5), \ - (long) (number)) + __mips_syscall6 ((long) (a0), (long) (a1), (long) (a2), \ + (long) (a3), (long) (a4), (long) (a5), \ + (long) (number)) -long long __nomips16 __mips16_syscall7 (long a0, long a1, long a2, long a3, - long a4, long a5, long a6, - long number); #define __mips16_syscall7(a0, a1, a2, a3, a4, a5, a6, number) \ - __mips16_syscall7 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), (long) (a4), (long) (a5), \ - (long) (a6), \ - (long) (number)) + __mips_syscall7 ((long) (a0), (long) (a1), (long) (a2), \ + (long) (a3), (long) (a4), (long) (a5), \ + (long) (a6), \ + (long) (number)) #endif diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c index 490245b34e..51d9469282 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c @@ -17,14 +17,13 @@ . */ #include -#include #undef __mips16_syscall0 long long __nomips16 __mips16_syscall0 (long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 0); return ret.val; } diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c index 3061e8accb..13d57a78aa 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c @@ -17,7 +17,6 @@ . */ #include -#include #undef __mips16_syscall1 @@ -25,7 +24,7 @@ long long __nomips16 __mips16_syscall1 (long a0, long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 1, a0); return ret.val; diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c index 440a4ed285..6e0e8d5bb5 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c @@ -17,7 +17,6 @@ . */ #include -#include #undef __mips16_syscall2 @@ -25,7 +24,7 @@ long long __nomips16 __mips16_syscall2 (long a0, long a1, long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 2, a0, a1); return ret.val; diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c index c3f83fc1f6..6bd6b8222b 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c @@ -17,7 +17,6 @@ . */ #include -#include #undef __mips16_syscall3 @@ -25,7 +24,7 @@ long long __nomips16 __mips16_syscall3 (long a0, long a1, long a2, long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 3, a0, a1, a2); return ret.val; diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c index 496297d296..3847e4bc25 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c @@ -17,7 +17,6 @@ . */ #include -#include #undef __mips16_syscall4 @@ -25,7 +24,7 @@ long long __nomips16 __mips16_syscall4 (long a0, long a1, long a2, long a3, long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 4, a0, a1, a2, a3); return ret.val; diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c deleted file mode 100644 index ad265d88e2..0000000000 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c +++ /dev/null @@ -1,33 +0,0 @@ -/* MIPS16 syscall wrappers. - Copyright (C) 2013-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include - -#undef __mips16_syscall5 - -long long __nomips16 -__mips16_syscall5 (long a0, long a1, long a2, long a3, - long a4, - long number) -{ - union __mips16_syscall_return ret; - ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 5, - a0, a1, a2, a3, a4); - return ret.val; -} diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c deleted file mode 100644 index bfbd395ed3..0000000000 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c +++ /dev/null @@ -1,33 +0,0 @@ -/* MIPS16 syscall wrappers. - Copyright (C) 2013-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include - -#undef __mips16_syscall6 - -long long __nomips16 -__mips16_syscall6 (long a0, long a1, long a2, long a3, - long a4, long a5, - long number) -{ - union __mips16_syscall_return ret; - ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 6, - a0, a1, a2, a3, a4, a5); - return ret.val; -} diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c deleted file mode 100644 index e1267616dc..0000000000 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c +++ /dev/null @@ -1,33 +0,0 @@ -/* MIPS16 syscall wrappers. - Copyright (C) 2013-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include - -#undef __mips16_syscall7 - -long long __nomips16 -__mips16_syscall7 (long a0, long a1, long a2, long a3, - long a4, long a5, long a6, - long number) -{ - union __mips16_syscall_return ret; - ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 7, - a0, a1, a2, a3, a4, a5, a6); - return ret.val; -} -- cgit v1.2.1