diff --git a/ChangeLog.arm b/ChangeLog.arm index d13f4a3c35..363b86521a 100644 --- a/ChangeLog.arm +++ b/ChangeLog.arm @@ -1,3 +1,12 @@ +2010-04-08 Daniel Jacobowitz + + * sysdeps/unix/sysv/linux/arm/eabi/libc-do-syscall.S: New file. + * sysdeps/unix/sysv/linux/arm/eabi/sysdep.h [__thumb__] + (INTERNAL_SYSCALL_RAW): Rewrite to use __libc_do_syscall. + * sysdeps/unix/sysv/linux/arm/eabi/Makefile: Add libc-do-syscall + to libraries and tests that require it. + * sysdeps/unix/sysv/linux/arm/eabi/nptl/aio_misc.h: Delete. + 2010-03-30 Joseph Myers * sysdeps/arm/dl-machine.h (VALID_ELF_ABIVERSION, VALID_ELF_OSABI, diff --git a/sysdeps/unix/sysv/linux/arm/eabi/Makefile b/sysdeps/unix/sysv/linux/arm/eabi/Makefile index 9f2b0fe8f4..761c96406d 100644 --- a/sysdeps/unix/sysv/linux/arm/eabi/Makefile +++ b/sysdeps/unix/sysv/linux/arm/eabi/Makefile @@ -7,3 +7,34 @@ ifeq ($(subdir),csu) # unwind tables for __libc_start_main. CFLAGS-libc-start.c += -fexceptions endif + +# Add a syscall function to each library that needs one. + +ifeq ($(subdir),rt) +librt-sysdep_routines += libc-do-syscall +librt-shared-only-routines += libc-do-syscall +endif + +ifeq ($(subdir),nptl) +libpthread-sysdep_routines += libc-do-syscall +libpthread-shared-only-routines += libc-do-syscall +endif + +ifeq ($(subdir),resolv) +libanl-sysdep_routines += libc-do-syscall +libanl-shared-only-routines += libc-do-syscall +endif + +ifeq ($(subdir),csu) +sysdep_routines += libc-do-syscall +endif + +ifeq ($(subdir),nscd) +nscd-modules += libc-do-syscall +endif + +ifeq ($(subdir),posix) +LDFLAGS-tst-rfc3484 += $(common-objpfx)csu/libc-do-syscall.o +LDFLAGS-tst-rfc3484-2 += $(common-objpfx)csu/libc-do-syscall.o +LDFLAGS-tst-rfc3484-3 += $(common-objpfx)csu/libc-do-syscall.o +endif diff --git a/sysdeps/unix/sysv/linux/arm/eabi/libc-do-syscall.S b/sysdeps/unix/sysv/linux/arm/eabi/libc-do-syscall.S new file mode 100644 index 0000000000..d461712af0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/eabi/libc-do-syscall.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2010 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Out-of-line syscall stub. We expect the system call number in ip + and return the raw result in r0. No registers are clobbered. + We could avoid using the stack for this, but the goal is accurate + unwind information - and while there is a reserved prefix in the + ARM unwind tables for register to register moves, the actual opcodes + are not defined. */ + + .thumb + .syntax unified + .hidden __libc_do_syscall + +ENTRY (__libc_do_syscall) + .fnstart + push {r7, lr} + .save {r7, lr} + cfi_adjust_cfa_offset (8) + cfi_rel_offset (r7, 0) + cfi_rel_offset (lr, 4) + mov r7, ip + swi 0x0 + pop {r7, pc} + .fnend +END (__libc_do_syscall) diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/aio_misc.h b/sysdeps/unix/sysv/linux/arm/eabi/nptl/aio_misc.h deleted file mode 100644 index 3fb1ec95fd..0000000000 --- a/sysdeps/unix/sysv/linux/arm/eabi/nptl/aio_misc.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2008 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include_next - -#ifdef __thumb2__ - -#include - -/* The Thumb-2 definition of INTERNAL_SYSCALL_RAW has to hide the use - of r7 from the compiler because it cannot handle asm clobbering the - hard frame pointer. In aio_suspend, GCC does not eliminate the - hard frame pointer because the function uses variable-length - arrays, so it generates unwind information using r7 as virtual - stack pointer. During system calls, when r7 has been saved on the - stack, this means the unwind information is invalid. Without extra - unwind directives, which would need to cause unwind information for - the asm to be generated separately from that for the parts of the - function before and after the asm (with three index table entries), - it is not possible to represent any temporary change to the virtual - stack pointer. Instead, we move the problematic system calls out - of line into a function that does not require a frame pointer. */ - -static __attribute_noinline__ void -aio_misc_wait (int *resultp, - volatile int *futexp, - const struct timespec *timeout, - int cancel) -{ - AIO_MISC_WAIT (*resultp, *futexp, timeout, cancel); -} - -#undef AIO_MISC_WAIT -#define AIO_MISC_WAIT(result, futex, timeout, cancel) \ - aio_misc_wait (&result, &futex, timeout, cancel) - -#endif diff --git a/sysdeps/unix/sysv/linux/arm/eabi/sysdep.h b/sysdeps/unix/sysv/linux/arm/eabi/sysdep.h index 9d90f3e35f..b7815babf4 100644 --- a/sysdeps/unix/sysv/linux/arm/eabi/sysdep.h +++ b/sysdeps/unix/sysv/linux/arm/eabi/sysdep.h @@ -44,30 +44,34 @@ argument; otherwise the (optional) compatibility code for APCS binaries may be invoked. */ -#ifdef __thumb__ -/* Hide the use of r7 from the compiler, this would be a lot - easier but for the fact that the syscalls can exceed 255. - For the moment the LOAD_ARGS_7 is sacrificed. +#if defined(__thumb__) +/* We can not expose the use of r7 to the compiler. GCC (as + of 4.5) uses r7 as the hard frame pointer for Thumb - although + for Thumb-2 it isn't obviously a better choice than r11. + And GCC does not support asms that conflict with the frame + pointer. + + This would be easier if syscall numbers never exceeded 255, + but they do. For the moment the LOAD_ARGS_7 is sacrificed. We can't use push/pop inside the asm because that breaks - unwinding (ie. thread cancellation). */ -/* FIXME: the str / ldr of r7 are not covered by CFI information. */ + unwinding (i.e. thread cancellation) for this frame. We can't + locally save and restore r7, because we do not know if this + function uses r7 or if it is our caller's r7; if it is our caller's, + then unwinding will fail higher up the stack. So we move the + syscall out of line and provide its own unwind information. */ #undef LOAD_ARGS_7 #undef INTERNAL_SYSCALL_RAW #define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \ ({ \ - int _sys_buf[2]; \ register int _a1 asm ("a1"); \ - register int *_r6 asm ("r6") = _sys_buf; \ - *_r6 = name; \ + int _nametmp = name; \ LOAD_ARGS_##nr (args) \ - asm volatile ("str r7, [r6, #4]\n\t" \ - "ldr r7, [r6]\n\t" \ - "swi 0 @ syscall " #name "\n\t" \ - "ldr r7, [r6, #4]" \ - : "=r" (_a1) \ - : "r" (_r6) ASM_ARGS_##nr \ - : "memory"); \ - _a1; }) + register int _name asm ("ip") = _nametmp; \ + asm volatile ("bl __libc_do_syscall" \ + : "=r" (_a1) \ + : "r" (_name) ASM_ARGS_##nr \ + : "memory", "lr"); \ + _a1; }) #else /* ARM */ #undef INTERNAL_SYSCALL_RAW #define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \