diff options
Diffstat (limited to 'libc/sysdeps/linux/arm')
68 files changed, 1681 insertions, 794 deletions
diff --git a/libc/sysdeps/linux/arm/Makefile.arch b/libc/sysdeps/linux/arm/Makefile.arch index a3b6fc4d8..cda3db206 100644 --- a/libc/sysdeps/linux/arm/Makefile.arch +++ b/libc/sysdeps/linux/arm/Makefile.arch @@ -5,31 +5,42 @@ # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. # -CSRC := brk.c ioperm.c iopl.c mmap.c posix_fadvise.c posix_fadvise64.c \ - sigaction.c __syscall_error.c +CSRC-y := brk.c ioperm.c iopl.c __syscall_error.c sigaction.c -SSRC := \ - __longjmp.S vfork.S clone.S setjmp.S bsd-setjmp.S \ - bsd-_setjmp.S sigrestorer.S mmap64.S +SSRC-y := \ + __longjmp.S setjmp.S bsd-setjmp.S \ + bsd-_setjmp.S sigrestorer.S \ + vfork.S clone.S -ifeq ($(CONFIG_ARM_EABI),y) -CSRC += aeabi_assert.c aeabi_atexit.c aeabi_errno_addr.c \ +SSRC-$(UCLIBC_HAS_LFS) += mmap64.S +SSRC-$(UCLIBC_HAS_THREADS_NATIVE) += libc-thumb_atomics.S +libc-nonshared-$(UCLIBC_HAS_THREADS_NATIVE) += $(ARCH_OUT)/libc-aeabi_read_tp.os +libc-static-$(UCLIBC_HAS_THREADS_NATIVE) += $(ARCH_OUT)/libc-aeabi_read_tp.o +CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c +SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += getcontext.S setcontext.S swapcontext.S + +# Is our compiler set up for EABI ? +CC_IS_EABI_CHECK = $(filter-out -include libc-symbols.h,$(CC) $(CFLAGS)) +$(eval $(call cache-output-var,IS_EABI,$(CC_IS_EABI_CHECK) -x c - -E -dM </dev/null 2>/dev/null | grep __ARM_EABI__ 2>&1 >/dev/null && echo 'y')) + +CSRC-$(IS_EABI) += aeabi_assert.c aeabi_atexit.c aeabi_errno_addr.c \ aeabi_localeconv.c aeabi_memclr.c aeabi_memcpy.c \ aeabi_memmove.c aeabi_memset.c find_exidx.c -SSRC += syscall-eabi.S -ifeq ($(UCLIBC_HAS_WCHAR),y) -CSRC += aeabi_mb_cur_max.c -endif -else -CSRC += syscall.c +SSRC-$(IS_EABI) += syscall-eabi.S +CSRC-$(if $(IS_EABI),,y)) += syscall.c +ARCH_OBJ_FILTEROUT-$(IS_EABI) := syscall.c +ifeq ($(IS_EABI),y) +CSRC-$(UCLIBC_HAS_WCHAR) += aeabi_mb_cur_max.c endif -include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch - -ifeq ($(CONFIG_ARM_EABI),y) -libc-static-y += $(ARCH_OUT)/aeabi_lcsts.o $(ARCH_OUT)/aeabi_math.o \ - $(ARCH_OUT)/aeabi_sighandlers.o -libc-nonshared-y += $(ARCH_OUT)/aeabi_lcsts.os $(ARCH_OUT)/aeabi_math.os \ - $(ARCH_OUT)/aeabi_sighandlers.os -libc-shared-y += $(ARCH_OUT)/aeabi_unwind_cpp_pr1.os -endif +libc-static-$(IS_EABI) += $(addprefix $(ARCH_OUT)/, \ + aeabi_lcsts.o \ + aeabi_math.o \ + aeabi_sighandlers.o \ + ) +libc-nonshared-$(IS_EABI) += $(addprefix $(ARCH_OUT)/, \ + aeabi_lcsts.os \ + aeabi_math.os \ + aeabi_sighandlers.os \ + aeabi_unwind_cpp_pr1.o \ + ) diff --git a/libc/sysdeps/linux/arm/__longjmp.S b/libc/sysdeps/linux/arm/__longjmp.S index 5faf4ece9..58ae8ab58 100644 --- a/libc/sysdeps/linux/arm/__longjmp.S +++ b/libc/sysdeps/linux/arm/__longjmp.S @@ -13,16 +13,12 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <features.h> #include <bits/arm_asm.h> -#define _SETJMP_H -#define _ASM -#include <bits/setjmp.h> - +#include <bits/arm_bx.h> .global __longjmp .type __longjmp,%function @@ -102,12 +98,7 @@ __longjmp: ldcl p1, cr14, [r12], #8 ldcl p1, cr15, [r12], #8 #endif - -#if defined(__USE_BX__) - bx lr -#else - mov pc, lr -#endif + BX(lr) #endif .size __longjmp,.-__longjmp diff --git a/libc/sysdeps/linux/arm/aeabi_assert.c b/libc/sysdeps/linux/arm/aeabi_assert.c index e0985b446..1f91e26c9 100644 --- a/libc/sysdeps/linux/arm/aeabi_assert.c +++ b/libc/sysdeps/linux/arm/aeabi_assert.c @@ -12,19 +12,16 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #undef NDEBUG #include <assert.h> #include <stdlib.h> -libc_hidden_proto(__assert) -void -__aeabi_assert (const char *assertion, const char *file, - unsigned int line) +void __aeabi_assert(const char *assertion, const char *file, unsigned int line) attribute_noreturn; +void __aeabi_assert(const char *assertion, const char *file, unsigned int line) { __assert (assertion, file, line, NULL); } diff --git a/libc/sysdeps/linux/arm/aeabi_atexit.c b/libc/sysdeps/linux/arm/aeabi_atexit.c index 4a7a6f1dc..190ed461a 100644 --- a/libc/sysdeps/linux/arm/aeabi_atexit.c +++ b/libc/sysdeps/linux/arm/aeabi_atexit.c @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <stdlib.h> @@ -24,8 +23,8 @@ libc_hidden_proto(__cxa_atexit) /* Register a function to be called by exit or when a shared library is unloaded. This routine is like __cxa_atexit, but uses the calling sequence required by the ARM EABI. */ -int -__aeabi_atexit (void *arg, void (*func) (void *), void *d) +int __aeabi_atexit (void *arg, void (*func) (void *), void *d); +int __aeabi_atexit (void *arg, void (*func) (void *), void *d) { return __cxa_atexit (func, arg, d); } diff --git a/libc/sysdeps/linux/arm/aeabi_errno_addr.c b/libc/sysdeps/linux/arm/aeabi_errno_addr.c index 09bdc1efe..aa36bde39 100644 --- a/libc/sysdeps/linux/arm/aeabi_errno_addr.c +++ b/libc/sysdeps/linux/arm/aeabi_errno_addr.c @@ -12,14 +12,13 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <errno.h> -volatile int * -__aeabi_errno_addr (void) +volatile int * __aeabi_errno_addr (void); +volatile int * __aeabi_errno_addr (void) { return &errno; } diff --git a/libc/sysdeps/linux/arm/aeabi_lcsts.c b/libc/sysdeps/linux/arm/aeabi_lcsts.c index 99c79851e..746c0ffe1 100644 --- a/libc/sysdeps/linux/arm/aeabi_lcsts.c +++ b/libc/sysdeps/linux/arm/aeabi_lcsts.c @@ -30,9 +30,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* The ARM EABI requires that we provide ISO compile-time constants as link-time constants. Some portable applications may reference these. */ @@ -79,6 +78,23 @@ eabi_constant (BUFSIZ); eabi_constant (FOPEN_MAX); eabi_constant (TMP_MAX); eabi_constant (FILENAME_MAX); +#ifdef __UCLIBC_SUSV4_LEGACY__ eabi_constant (L_tmpnam); +#endif + +FILE *__aeabi_stdin attribute_hidden; +FILE *__aeabi_stdout attribute_hidden; +FILE *__aeabi_stderr attribute_hidden; + +static void __attribute__ ((used)) +setup_aeabi_stdio (void) +{ + __aeabi_stdin = stdin; + __aeabi_stdout = stdout; + __aeabi_stderr = stderr; +} + +static void (*fp) (void) __attribute__ ((used, section (".preinit_array"))) + = setup_aeabi_stdio; eabi_constant (CLOCKS_PER_SEC); diff --git a/libc/sysdeps/linux/arm/aeabi_localeconv.c b/libc/sysdeps/linux/arm/aeabi_localeconv.c index c9e9dd23f..53f03ae09 100644 --- a/libc/sysdeps/linux/arm/aeabi_localeconv.c +++ b/libc/sysdeps/linux/arm/aeabi_localeconv.c @@ -12,16 +12,14 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <locale.h> -libc_hidden_proto(localeconv) -struct lconv * -__aeabi_localeconv (void) +struct lconv * __aeabi_localeconv (void); +struct lconv * __aeabi_localeconv (void) { return localeconv (); } diff --git a/libc/sysdeps/linux/arm/aeabi_math.c b/libc/sysdeps/linux/arm/aeabi_math.c index e7f1dbf5f..151125246 100644 --- a/libc/sysdeps/linux/arm/aeabi_math.c +++ b/libc/sysdeps/linux/arm/aeabi_math.c @@ -29,9 +29,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <math.h> diff --git a/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c b/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c index 937a7fffb..9966e5840 100644 --- a/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c +++ b/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c @@ -12,24 +12,15 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <langinfo.h> #include <locale.h> #include <stdlib.h> -#ifdef __UCLIBC_HAS_WCHAR__ -libc_hidden_proto(_stdlib_mb_cur_max) -#endif - -int -__aeabi_MB_CUR_MAX (void) +int __aeabi_MB_CUR_MAX (void); +int __aeabi_MB_CUR_MAX (void) { -#ifdef __UCLIBC_HAS_WCHAR__ return MB_CUR_MAX; -#else - return 1; -#endif } diff --git a/libc/sysdeps/linux/arm/aeabi_memclr.c b/libc/sysdeps/linux/arm/aeabi_memclr.c index c0f90216c..9bfe86e8a 100644 --- a/libc/sysdeps/linux/arm/aeabi_memclr.c +++ b/libc/sysdeps/linux/arm/aeabi_memclr.c @@ -12,18 +12,16 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <string.h> -/* Experimentally off - libc_hidden_proto(memset) */ /* Clear memory. Can't alias to bzero because it's not defined in the same translation unit. */ -void -__aeabi_memclr (void *dest, size_t n) +void __aeabi_memclr (void *dest, size_t n); +void __aeabi_memclr (void *dest, size_t n) { memset (dest, 0, n); } diff --git a/libc/sysdeps/linux/arm/aeabi_memcpy.c b/libc/sysdeps/linux/arm/aeabi_memcpy.c index 83eac0b67..a84d9f4f7 100644 --- a/libc/sysdeps/linux/arm/aeabi_memcpy.c +++ b/libc/sysdeps/linux/arm/aeabi_memcpy.c @@ -12,19 +12,17 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <string.h> -/* Experimentally off - libc_hidden_proto(memcpy) */ /* Copy memory like memcpy, but no return value required. Can't alias to memcpy because it's not defined in the same translation unit. */ -void -__aeabi_memcpy (void *dest, const void *src, size_t n) +void __aeabi_memcpy (void *dest, const void *src, size_t n); +void __aeabi_memcpy (void *dest, const void *src, size_t n) { memcpy (dest, src, n); } diff --git a/libc/sysdeps/linux/arm/aeabi_memmove.c b/libc/sysdeps/linux/arm/aeabi_memmove.c index 164d72bc9..adb69c787 100644 --- a/libc/sysdeps/linux/arm/aeabi_memmove.c +++ b/libc/sysdeps/linux/arm/aeabi_memmove.c @@ -12,19 +12,17 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <string.h> -/* Experimentally off - libc_hidden_proto(memmove) */ /* Copy memory like memmove, but no return value required. Can't alias to memmove because it's not defined in the same translation unit. */ -void -__aeabi_memmove (void *dest, const void *src, size_t n) +void __aeabi_memmove (void *dest, const void *src, size_t n); +void __aeabi_memmove (void *dest, const void *src, size_t n) { memmove (dest, src, n); } diff --git a/libc/sysdeps/linux/arm/aeabi_memset.c b/libc/sysdeps/linux/arm/aeabi_memset.c index f1c366f27..183454a25 100644 --- a/libc/sysdeps/linux/arm/aeabi_memset.c +++ b/libc/sysdeps/linux/arm/aeabi_memset.c @@ -12,18 +12,16 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <string.h> -/* Experimentally off - libc_hidden_proto(memset) */ /* Set memory like memset, but different argument order and no return value required. */ -void -__aeabi_memset (void *dest, size_t n, int c) +void __aeabi_memset (void *dest, size_t n, int c); +void __aeabi_memset (void *dest, size_t n, int c) { memset (dest, c, n); } diff --git a/libc/sysdeps/linux/arm/aeabi_sighandlers.S b/libc/sysdeps/linux/arm/aeabi_sighandlers.S index ba9769fd0..f30f5878e 100644 --- a/libc/sysdeps/linux/arm/aeabi_sighandlers.S +++ b/libc/sysdeps/linux/arm/aeabi_sighandlers.S @@ -30,9 +30,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* The ARM EABI defines these as "functions". */ diff --git a/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c b/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c index e657d3836..a5cd73faf 100644 --- a/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c +++ b/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* Because some objects in ld.so and libc.so are built with -fexceptions, we end up with references to this personality @@ -24,20 +23,17 @@ #include <stdlib.h> -attribute_hidden -void -__aeabi_unwind_cpp_pr0 (void) +attribute_hidden void __aeabi_unwind_cpp_pr0 (void); +attribute_hidden void __aeabi_unwind_cpp_pr0 (void) { } -attribute_hidden -void -__aeabi_unwind_cpp_pr1 (void) +attribute_hidden void __aeabi_unwind_cpp_pr1 (void); +attribute_hidden void __aeabi_unwind_cpp_pr1 (void) { } -attribute_hidden -void -__aeabi_unwind_cpp_pr2 (void) +attribute_hidden void __aeabi_unwind_cpp_pr2 (void); +attribute_hidden void __aeabi_unwind_cpp_pr2 (void) { } diff --git a/libc/sysdeps/linux/arm/bits/arm_asm.h b/libc/sysdeps/linux/arm/bits/arm_asm.h index 1d87df6eb..898a78bcc 100644 --- a/libc/sysdeps/linux/arm/bits/arm_asm.h +++ b/libc/sysdeps/linux/arm/bits/arm_asm.h @@ -3,20 +3,22 @@ #define _ARM_ASM_H #ifdef __thumb2__ +# ifdef __ASSEMBLER__ .thumb .syntax unified +# endif /* __ASSEMBLER__ */ #define IT(t, cond) i##t cond #else /* XXX: This can be removed if/when we require an assembler that supports unified assembly syntax. */ #define IT(t, cond) /* Code to return from a thumb function stub. */ -#ifdef __ARM_ARCH_4T__ -#define POP_RET pop {r2, pc} -#else -#define POP_RET pop {r2, r3}; bx r3 -#endif -#endif +# if defined __ARM_ARCH_4T__ && defined __THUMB_INTERWORK__ +# define POP_RET pop {r2, r3}; bx r3 +# else +# define POP_RET pop {r2, pc} +# endif +#endif /* __thumb2__ */ #if defined(__ARM_ARCH_6M__) /* Force arm mode to flush out errors on M profile cores. */ @@ -25,4 +27,3 @@ #endif #endif /* _ARM_ASM_H */ - diff --git a/libc/sysdeps/linux/arm/bits/arm_bx.h b/libc/sysdeps/linux/arm/bits/arm_bx.h new file mode 100644 index 000000000..2c290896d --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/arm_bx.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2013 Yann E. MORIN <yann.morin.1998@free.fr> + * + * This file 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. + * + * This file 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 + * <http://www.gnu.org/licenses/>. + */ + +#ifndef _ARM_BX_H +#define _ARM_BX_H + +/* We need features.h first */ +#if !defined _FEATURES_H +#error Please include features.h first +#endif /* features.h not yet included */ + +#if defined(__USE_BX__) +# if (__ARM_ARCH <= 4 && !defined __ARM_ARCH_4T__) +# error Use of BX was requested, but is not available on the target processor. +# endif /* ARCH level */ +#endif /* __USE_BX__ */ + +#if defined(__USE_BX__) && (__ARM_ARCH > 4 || (__ARM_ARCH == 4 && defined __ARM_ARCH_4T__)) +# define BX(reg) bx reg +# define BXC(cond, reg) bx##cond reg +#else +# define BX(reg) mov pc, reg +# define BXC(cond, reg) mov##cond pc, reg +#endif + +#endif /* _ARM_BX_H */ diff --git a/libc/sysdeps/linux/arm/bits/armsigctx.h b/libc/sysdeps/linux/arm/bits/armsigctx.h index 4530cdbda..aced7b64a 100644 --- a/libc/sysdeps/linux/arm/bits/armsigctx.h +++ b/libc/sysdeps/linux/arm/bits/armsigctx.h @@ -13,9 +13,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* The format of struct sigcontext changed between 2.0 and 2.1 kernels. Fortunately 2.0 puts a magic number in the first word and this is not diff --git a/libc/sysdeps/linux/arm/bits/atomic.h b/libc/sysdeps/linux/arm/bits/atomic.h new file mode 100644 index 000000000..343288cb6 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/atomic.h @@ -0,0 +1,135 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 + <http://www.gnu.org/licenses/>. */ + +#if defined __thumb__ && !defined __thumb2__ +#include_next <common/bits/atomic.h> +#else +#include <stdint.h> +#include <sysdep.h> + + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +void __arm_link_error (void); + +/* Use the atomic builtins provided by GCC in case the backend provides + a pattern to do this efficiently. */ + +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 +#define atomic_full_barrier() __sync_synchronize () +#elif defined __thumb2__ +#define atomic_full_barrier() \ + __asm__ __volatile__ \ + ("movw\tip, #0x0fa0\n\t" \ + "movt\tip, #0xffff\n\t" \ + "blx\tip" \ + : : : "ip", "lr", "cc", "memory"); +#else +#define atomic_full_barrier() \ + __asm__ __volatile__ \ + ("mov\tip, #0xffff0fff\n\t" \ + "mov\tlr, pc\n\t" \ + "add\tpc, ip, #(0xffff0fa0 - 0xffff0fff)" \ + : : : "ip", "lr", "cc", "memory"); +#endif + +/* Atomic compare and exchange. This sequence relies on the kernel to + provide a compare and exchange operation which is atomic on the + current architecture, either via cleverness on pre-ARMv6 or via + ldrex / strex on ARMv6. */ + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + ({ __arm_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + ({ __arm_link_error (); oldval; }) + +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + __sync_val_compare_and_swap ((mem), (oldval), (newval)) + +/* It doesn't matter what register is used for a_oldval2, but we must + specify one to work around GCC PR rtl-optimization/21223. Otherwise + it may cause a_oldval or a_tmp to be moved to a different register. */ + +#elif defined __thumb2__ +/* Thumb-2 has ldrex/strex. However it does not have barrier instructions, + so we still need to use the kernel helper. */ +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ register __typeof (oldval) a_oldval __asm__ ("r0"); \ + register __typeof (oldval) a_newval __asm__ ("r1") = (newval); \ + register __typeof (mem) a_ptr __asm__ ("r2") = (mem); \ + register __typeof (oldval) a_tmp __asm__ ("r3"); \ + register __typeof (oldval) a_oldval2 __asm__ ("r4") = (oldval); \ + __asm__ __volatile__ \ + ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \ + "cmp\t%[tmp], %[old2]\n\t" \ + "bne\t1f\n\t" \ + "mov\t%[old], %[old2]\n\t" \ + "movw\t%[tmp], #0x0fc0\n\t" \ + "movt\t%[tmp], #0xffff\n\t" \ + "blx\t%[tmp]\n\t" \ + "bcc\t0b\n\t" \ + "mov\t%[tmp], %[old2]\n\t" \ + "1:" \ + : [old] "=&r" (a_oldval), [tmp] "=&r" (a_tmp) \ + : [new] "r" (a_newval), [ptr] "r" (a_ptr), \ + [old2] "r" (a_oldval2) \ + : "ip", "lr", "cc", "memory"); \ + a_tmp; }) +#else +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ register __typeof (oldval) a_oldval __asm__ ("r0"); \ + register __typeof (oldval) a_newval __asm__ ("r1") = (newval); \ + register __typeof (mem) a_ptr __asm__ ("r2") = (mem); \ + register __typeof (oldval) a_tmp __asm__ ("r3"); \ + register __typeof (oldval) a_oldval2 __asm__ ("r4") = (oldval); \ + __asm__ __volatile__ \ + ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \ + "cmp\t%[tmp], %[old2]\n\t" \ + "bne\t1f\n\t" \ + "mov\t%[old], %[old2]\n\t" \ + "mov\t%[tmp], #0xffff0fff\n\t" \ + "mov\tlr, pc\n\t" \ + "add\tpc, %[tmp], #(0xffff0fc0 - 0xffff0fff)\n\t" \ + "bcc\t0b\n\t" \ + "mov\t%[tmp], %[old2]\n\t" \ + "1:" \ + : [old] "=&r" (a_oldval), [tmp] "=&r" (a_tmp) \ + : [new] "r" (a_newval), [ptr] "r" (a_ptr), \ + [old2] "r" (a_oldval2) \ + : "ip", "lr", "cc", "memory"); \ + a_tmp; }) +#endif + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __arm_link_error (); oldval; }) + +#endif diff --git a/libc/sysdeps/linux/arm/bits/fcntl.h b/libc/sysdeps/linux/arm/bits/fcntl.h index 01d2d3d14..c6ba9588c 100644 --- a/libc/sysdeps/linux/arm/bits/fcntl.h +++ b/libc/sysdeps/linux/arm/bits/fcntl.h @@ -14,9 +14,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _FCNTL_H # error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead." @@ -50,9 +49,8 @@ # define O_NOFOLLOW 0100000 /* Do not follow links. */ # define O_DIRECT 0200000 /* Direct disk access. */ # define O_NOATIME 01000000 /* Do not set atime. */ -# if 0 # define O_CLOEXEC 02000000 /* Set close_on_exec. */ -# endif +# define O_PATH 010000000 /* Resolve pathname but do not open file. */ #endif /* For now Linux has synchronisity options for data and read operations. @@ -102,6 +100,8 @@ # define F_NOTIFY 1026 /* Request notfications on a directory. */ # define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with close-on-exit set on new fd. */ +# define F_SETPIPE_SZ 1031 /* Set pipe page size array. */ +# define F_GETPIPE_SZ 1032 /* Get pipe page size array. */ #endif /* For F_[GET|SET]FD. */ @@ -189,7 +189,7 @@ struct flock64 #endif -#ifdef __USE_GNU +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ /* Flags for SYNC_FILE_RANGE. */ # define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages in the range before performing the @@ -212,7 +212,7 @@ struct flock64 __BEGIN_DECLS -#ifdef __USE_GNU +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ /* Provide kernel hint to read ahead. */ extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) diff --git a/libc/sysdeps/linux/arm/bits/fenv.h b/libc/sysdeps/linux/arm/bits/fenv.h index 3764d7749..106bf36c2 100644 --- a/libc/sysdeps/linux/arm/bits/fenv.h +++ b/libc/sysdeps/linux/arm/bits/fenv.h @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _FENV_H # error "Never use <bits/fenv.h> directly; include <fenv.h> instead." diff --git a/libc/sysdeps/linux/arm/bits/huge_val.h b/libc/sysdeps/linux/arm/bits/huge_val.h index a215f3c0b..a8b85b3ba 100644 --- a/libc/sysdeps/linux/arm/bits/huge_val.h +++ b/libc/sysdeps/linux/arm/bits/huge_val.h @@ -16,9 +16,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _MATH_H # error "Never use <bits/huge_val.h> directly; include <math.h> instead." @@ -32,7 +31,7 @@ # define HUGE_VAL (__extension__ 0x1.0p2047) #elif defined __GNUC__ -#ifndef __CONFIG_ARM_EABI__ +#ifndef __ARM_EABI__ # define HUGE_VAL \ (__extension__ \ ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ @@ -50,7 +49,7 @@ typedef union { unsigned char __c[8]; double __d; } __huge_val_t; -#ifndef __CONFIG_ARM_EABI__ +#ifndef __ARM_EABI__ # if __BYTE_ORDER == __BIG_ENDIAN # define __HUGE_VAL_bytes { 0, 0, 0, 0, 0x7f, 0xf0, 0, 0 } # endif diff --git a/libc/sysdeps/linux/arm/bits/kernel_stat.h b/libc/sysdeps/linux/arm/bits/kernel_stat.h index ebac6f5ff..7bd89f9ab 100644 --- a/libc/sysdeps/linux/arm/bits/kernel_stat.h +++ b/libc/sysdeps/linux/arm/bits/kernel_stat.h @@ -1,16 +1,10 @@ #ifndef _BITS_STAT_STRUCT_H #define _BITS_STAT_STRUCT_H -#ifndef _LIBC -#error bits/kernel_stat.h is for internal uClibc use only! -#endif - /* This file provides whatever this particular arch's kernel thinks * struct kernel_stat should look like... It turns out each arch has a * different opinion on the subject... */ -#define STAT_HAVE_NSEC 1 - struct kernel_stat { #if defined(__ARMEB__) unsigned short st_dev; @@ -18,7 +12,7 @@ struct kernel_stat { #else unsigned long st_dev; #endif - unsigned long st_ino; + unsigned long st_ino; unsigned short st_mode; unsigned short st_nlink; unsigned short st_uid; @@ -32,12 +26,9 @@ struct kernel_stat { unsigned long st_size; unsigned long st_blksize; unsigned long st_blocks; - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - unsigned long st_mtime_nsec; - unsigned long st_ctime; - unsigned long st_ctime_nsec; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; unsigned long __unused4; unsigned long __unused5; }; @@ -60,12 +51,9 @@ struct kernel_stat64 { unsigned long st_blksize; unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - unsigned long st_mtime_nsec; - unsigned long st_ctime; - unsigned long st_ctime_nsec; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; unsigned long long st_ino; #ifndef __ARM_EABI__ } __attribute__((packed)); diff --git a/libc/sysdeps/linux/arm/bits/kernel_types.h b/libc/sysdeps/linux/arm/bits/kernel_types.h index 766a30621..6b36f3263 100644 --- a/libc/sysdeps/linux/arm/bits/kernel_types.h +++ b/libc/sysdeps/linux/arm/bits/kernel_types.h @@ -32,6 +32,8 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; typedef long long __kernel_loff_t; typedef __kernel_dev_t __kernel_old_dev_t; +typedef long __kernel_long_t; +typedef unsigned long __kernel_ulong_t; typedef struct { #ifdef __USE_ALL diff --git a/libc/sysdeps/linux/arm/bits/mathdef.h b/libc/sysdeps/linux/arm/bits/mathdef.h index e013e74b7..478ceed15 100644 --- a/libc/sysdeps/linux/arm/bits/mathdef.h +++ b/libc/sysdeps/linux/arm/bits/mathdef.h @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #if !defined _MATH_H && !defined _COMPLEX_H # error "Never use <bits/mathdef.h> directly; include <math.h> instead" diff --git a/libc/sysdeps/linux/arm/bits/mman.h b/libc/sysdeps/linux/arm/bits/mman.h deleted file mode 100644 index 828ec944c..000000000 --- a/libc/sysdeps/linux/arm/bits/mman.h +++ /dev/null @@ -1,103 +0,0 @@ -/* Definitions for POSIX memory map interface. Linux/ARM version. - Copyright (C) 1997, 2000, 2003, 2005, 2006 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. */ - -#ifndef _SYS_MMAN_H -# error "Never use <bits/mman.h> directly; include <sys/mman.h> instead." -#endif - -/* The following definitions basically come from the kernel headers. - But the kernel header is not namespace clean. */ - - -/* Protections are chosen from these bits, OR'd together. The - implementation does not necessarily support PROT_EXEC or PROT_WRITE - without PROT_READ. The only guarantees are that no writing will be - allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ - -#define PROT_READ 0x1 /* Page can be read. */ -#define PROT_WRITE 0x2 /* Page can be written. */ -#define PROT_EXEC 0x4 /* Page can be executed. */ -#define PROT_NONE 0x0 /* Page can not be accessed. */ -#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of - growsdown vma (mprotect only). */ -#define PROT_GROWSUP 0x02000000 /* Extend change to start of - growsup vma (mprotect only). */ - -/* Sharing types (must choose one and only one of these). */ -#define MAP_SHARED 0x01 /* Share changes. */ -#define MAP_PRIVATE 0x02 /* Changes are private. */ -#ifdef __USE_MISC -# define MAP_TYPE 0x0f /* Mask for type of mapping. */ -#endif - -/* Other flags. */ -#define MAP_FIXED 0x10 /* Interpret addr exactly. */ -#ifdef __USE_MISC -# define MAP_FILE 0 -# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ -# define MAP_ANON MAP_ANONYMOUS -#endif - -/* These are Linux-specific. */ -#ifdef __USE_MISC -# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ -# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ -# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ -# define MAP_LOCKED 0x02000 /* Lock the mapping. */ -# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ -# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ -# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ -#endif - -/* Flags to `msync'. */ -#define MS_ASYNC 1 /* Sync memory asynchronously. */ -#define MS_SYNC 4 /* Synchronous memory sync. */ -#define MS_INVALIDATE 2 /* Invalidate the caches. */ - -/* Flags for `mlockall'. */ -#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ -#define MCL_FUTURE 2 /* Lock all additions to address - space. */ - -/* Flags for `mremap'. */ -#ifdef __USE_GNU -# define MREMAP_MAYMOVE 1 -# define MREMAP_FIXED 2 -#endif - -/* Advice to `madvise'. */ -#ifdef __USE_BSD -# define MADV_NORMAL 0 /* No further special treatment. */ -# define MADV_RANDOM 1 /* Expect random page references. */ -# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -# define MADV_WILLNEED 3 /* Will need these pages. */ -# define MADV_DONTNEED 4 /* Don't need these pages. */ -# define MADV_REMOVE 9 /* Remove these pages and resources. */ -# define MADV_DONTFORK 10 /* Do not inherit across fork. */ -# define MADV_DOFORK 11 /* Do inherit across fork. */ -#endif - -/* The POSIX people had to invent similar names for the same things. */ -#ifdef __USE_XOPEN2K -# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ -# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ -# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ -# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ -#endif diff --git a/libc/sysdeps/linux/arm/bits/setjmp.h b/libc/sysdeps/linux/arm/bits/setjmp.h index ac52f1281..aa71ba706 100644 --- a/libc/sysdeps/linux/arm/bits/setjmp.h +++ b/libc/sysdeps/linux/arm/bits/setjmp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997,1998,2005,2006 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 @@ -12,19 +12,18 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* Define the machine-dependent type `jmp_buf'. ARM version. */ + #ifndef _BITS_SETJMP_H -#define _BITS_SETJMP_H 1 +#define _BITS_SETJMP_H 1 #if !defined _SETJMP_H && !defined _PTHREAD_H # error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead." #endif -#ifndef _ASM /* Jump buffer contains v1-v6, sl, fp, sp and pc. Other registers are not saved. */ #ifdef __ARM_EABI__ @@ -38,15 +37,10 @@ typedef int __jmp_buf[64] __attribute__((aligned (8))); #elif defined __MAVERICK__ || defined __IWMMXT__ typedef int __jmp_buf[34]; #else +# ifdef __UCLIBC_HAS_FPU__ typedef int __jmp_buf[22]; +# else +typedef int __jmp_buf[10]; +# endif #endif #endif - -#define __JMP_BUF_SP 8 - -/* Test if longjmp to JMPBUF would unwind the frame - containing a local variable at ADDRESS. */ -#define _JMPBUF_UNWINDS(jmpbuf, address) \ - ((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP])) - -#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/arm/bits/shm.h b/libc/sysdeps/linux/arm/bits/shm.h index c89c00a17..2708c58ff 100644 --- a/libc/sysdeps/linux/arm/bits/shm.h +++ b/libc/sysdeps/linux/arm/bits/shm.h @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _SYS_SHM_H # error "Never include <bits/shm.h> directly; use <sys/shm.h> instead." diff --git a/libc/sysdeps/linux/arm/bits/sigcontextinfo.h b/libc/sysdeps/linux/arm/bits/sigcontextinfo.h index 67167f90f..268f0a3f3 100644 --- a/libc/sysdeps/linux/arm/bits/sigcontextinfo.h +++ b/libc/sysdeps/linux/arm/bits/sigcontextinfo.h @@ -13,9 +13,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <bits/armsigctx.h> #include <linux/version.h> diff --git a/libc/sysdeps/linux/arm/bits/stackinfo.h b/libc/sysdeps/linux/arm/bits/stackinfo.h index 2410ba9bd..f4f0bb1cf 100644 --- a/libc/sysdeps/linux/arm/bits/stackinfo.h +++ b/libc/sysdeps/linux/arm/bits/stackinfo.h @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* This file contains a bit of information about the stack allocation of the processor. */ diff --git a/libc/sysdeps/linux/arm/bits/syscalls.h b/libc/sysdeps/linux/arm/bits/syscalls.h index 2d2e0f0a4..e447a7b2d 100644 --- a/libc/sysdeps/linux/arm/bits/syscalls.h +++ b/libc/sysdeps/linux/arm/bits/syscalls.h @@ -9,8 +9,6 @@ glibc-2.3.2/sysdeps/unix/sysv/linux/arm/sysdep.h */ -#define SYS_ify(syscall_name) (__NR_##syscall_name) - #ifdef __ASSEMBLER__ /* Call a given syscall, with arguments loaded. For EABI, we must @@ -32,172 +30,103 @@ #include <errno.h> -#undef _syscall0 -#define _syscall0(type,name) \ -type name(void) \ -{ \ -return (type) (INLINE_SYSCALL(name, 0)); \ -} - -#undef _syscall1 -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ -return (type) (INLINE_SYSCALL(name, 1, arg1)); \ -} - -#undef _syscall2 -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ -return (type) (INLINE_SYSCALL(name, 2, arg1, arg2)); \ -} - -#undef _syscall3 -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ -return (type) (INLINE_SYSCALL(name, 3, arg1, arg2, arg3)); \ -} - -#undef _syscall4 -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ -return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \ -} - -#undef _syscall5 -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ -return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \ -} - -#undef _syscall6 -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5,type6,arg6) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \ -{ \ -return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \ -} - -#undef _syscall7 -#define _syscall7(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5,type6,arg6,type7,arg7) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6,type7 arg7) \ -{ \ -return (type) (INLINE_SYSCALL(name, 7, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); \ -} - - -#undef INLINE_SYSCALL -#define INLINE_SYSCALL(name, nr, args...) \ - ({ unsigned int _inline_sys_result = INTERNAL_SYSCALL (name, , nr, args); \ - if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, ), 0)) \ +#define INLINE_SYSCALL_NCS(name, nr, args...) \ +(__extension__ \ + ({ \ + unsigned int _inline_sys_result = INTERNAL_SYSCALL_NCS (name, , nr, args);\ + if (unlikely (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, ))) \ { \ - __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, )); \ - _inline_sys_result = (unsigned int) -1; \ + __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, )); \ + _inline_sys_result = (unsigned int) -1; \ } \ - (int) _inline_sys_result; }) - -#undef INTERNAL_SYSCALL_DECL -#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + (int) _inline_sys_result; \ + }) \ +) -#undef INTERNAL_SYSCALL -#if !defined(__thumb__) -#if defined(__ARM_EABI__) -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - ({unsigned int __sys_result; \ - { \ - register int _a1 __asm__ ("r0"), _nr __asm__ ("r7"); \ - LOAD_ARGS_##nr (args) \ - _nr = SYS_ify(name); \ - __asm__ __volatile__ ("swi 0x0 @ syscall " #name \ - : "=r" (_a1) \ - : "r" (_nr) ASM_ARGS_##nr \ - : "memory"); \ - __sys_result = _a1; \ - } \ - (int) __sys_result; }) -#else /* defined(__ARM_EABI__) */ - -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - ({ unsigned int __sys_result; \ - { \ - register int _a1 __asm__ ("a1"); \ - LOAD_ARGS_##nr (args) \ - __asm__ __volatile__ ("swi %1 @ syscall " #name \ - : "=r" (_a1) \ - : "i" (SYS_ify(name)) ASM_ARGS_##nr \ - : "memory"); \ - __sys_result = _a1; \ - } \ - (int) __sys_result; }) -#endif -#else /* !defined(__thumb__) */ +#if defined(__thumb__) /* We can't use push/pop inside the asm because that breaks unwinding (ie. thread cancellation). */ -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - ({ unsigned int __sys_result; \ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ +(__extension__ \ + ({ unsigned int __internal_sys_result; \ { \ int _sys_buf[2]; \ - register int _a1 __asm__ ("a1"); \ - register int *_v3 __asm__ ("v3") = _sys_buf; \ - *_v3 = (int) (SYS_ify(name)); \ + register int __a1 __asm__ ("a1"); \ + register int *__v3 __asm__ ("v3") = _sys_buf; \ + *__v3 = (int) (name); \ LOAD_ARGS_##nr (args) \ __asm__ __volatile__ ("str r7, [v3, #4]\n" \ "\tldr r7, [v3]\n" \ "\tswi 0 @ syscall " #name "\n" \ "\tldr r7, [v3, #4]" \ - : "=r" (_a1) \ - : "r" (_v3) ASM_ARGS_##nr \ + : "=r" (__a1) \ + : "r" (__v3) ASM_ARGS_##nr \ : "memory"); \ - __sys_result = _a1; \ + __internal_sys_result = __a1; \ } \ - (int) __sys_result; }) -#endif /*!defined(__thumb__)*/ + (int) __internal_sys_result; }) \ +) +#else /* ARM */ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ +(__extension__ \ + ({unsigned int __internal_sys_result; \ + { \ + register int __a1 __asm__ ("r0"), _nr __asm__ ("r7"); \ + LOAD_ARGS_##nr (args) \ + _nr = (name); \ + __asm__ __volatile__ ("swi 0x0 @ syscall " #name \ + : "=r" (__a1) \ + : "r" (_nr) ASM_ARGS_##nr \ + : "memory"); \ + __internal_sys_result = __a1; \ + } \ + (int) __internal_sys_result; }) \ +) +#endif -#undef INTERNAL_SYSCALL_ERROR_P #define INTERNAL_SYSCALL_ERROR_P(val, err) \ ((unsigned int) (val) >= 0xfffff001u) -#undef INTERNAL_SYSCALL_ERRNO -#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) - #define LOAD_ARGS_0() #define ASM_ARGS_0 #define LOAD_ARGS_1(a1) \ - _a1 = (int) (a1); \ - LOAD_ARGS_0 () -#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1) + int __a1tmp = (int) (a1); \ + LOAD_ARGS_0 () \ + __a1 = __a1tmp; +#define ASM_ARGS_1 ASM_ARGS_0, "r" (__a1) #define LOAD_ARGS_2(a1, a2) \ - register int _a2 __asm__ ("a2") = (int) (a2); \ - LOAD_ARGS_1 (a1) -#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2) + int __a2tmp = (int) (a2); \ + LOAD_ARGS_1 (a1) \ + register int __a2 __asm__ ("a2") = __a2tmp; +#define ASM_ARGS_2 ASM_ARGS_1, "r" (__a2) #define LOAD_ARGS_3(a1, a2, a3) \ - register int _a3 __asm__ ("a3") = (int) (a3); \ - LOAD_ARGS_2 (a1, a2) -#define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3) + int __a3tmp = (int) (a3); \ + LOAD_ARGS_2 (a1, a2) \ + register int __a3 __asm__ ("a3") = __a3tmp; +#define ASM_ARGS_3 ASM_ARGS_2, "r" (__a3) #define LOAD_ARGS_4(a1, a2, a3, a4) \ - register int _a4 __asm__ ("a4") = (int) (a4); \ - LOAD_ARGS_3 (a1, a2, a3) -#define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4) + int __a4tmp = (int) (a4); \ + LOAD_ARGS_3 (a1, a2, a3) \ + register int __a4 __asm__ ("a4") = __a4tmp; +#define ASM_ARGS_4 ASM_ARGS_3, "r" (__a4) #define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ - register int _v1 __asm__ ("v1") = (int) (a5); \ - LOAD_ARGS_4 (a1, a2, a3, a4) -#define ASM_ARGS_5 ASM_ARGS_4, "r" (_v1) + int __v1tmp = (int) (a5); \ + LOAD_ARGS_4 (a1, a2, a3, a4) \ + register int __v1 __asm__ ("v1") = __v1tmp; +#define ASM_ARGS_5 ASM_ARGS_4, "r" (__v1) #define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ - register int _v2 __asm__ ("v2") = (int) (a6); \ - LOAD_ARGS_5 (a1, a2, a3, a4, a5) -#define ASM_ARGS_6 ASM_ARGS_5, "r" (_v2) + int __v2tmp = (int) (a6); \ + LOAD_ARGS_5 (a1, a2, a3, a4, a5) \ + register int __v2 __asm__ ("v2") = __v2tmp; +#define ASM_ARGS_6 ASM_ARGS_5, "r" (__v2) +#ifndef __thumb__ #define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7) \ - register int _v3 __asm__ ("v3") = (int) (a7); \ - LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6) -#define ASM_ARGS_7 ASM_ARGS_6, "r" (_v3) - + int __v3tmp = (int) (a7); \ + LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6) \ + register int __v3 __asm__ ("v3") = __v3tmp; +#define ASM_ARGS_7 ASM_ARGS_6, "r" (__v3) +#endif #endif /* __ASSEMBLER__ */ #endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h b/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h index 85c9adb8a..671afd3ac 100644 --- a/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h @@ -11,28 +11,72 @@ /* can your target use syscall6() for mmap ? */ #undef __UCLIBC_MMAP_HAS_6_ARGS__ -/* does your target use syscall4() for truncate64 ? (32bit arches only) */ -#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ +/* does your target align 64bit values in register pairs ? (32bit arches only) */ +#ifdef __ARM_EABI__ +#define __UCLIBC_SYSCALL_ALIGN_64BIT__ +#else +#undef __UCLIBC_SYSCALL_ALIGN_64BIT__ +#endif /* does your target have a broken create_module() ? */ #define __UCLIBC_BROKEN_CREATE_MODULE__ +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + /* does your target have an asm .set ? */ #define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ -/* define if target doesn't like .global */ -#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ - /* define if target supports .weak */ #define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ /* define if target supports .weakext */ #undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ -/* needed probably only for ppc64 */ -#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ /* define if target supports IEEE signed zero floats */ #define __UCLIBC_HAVE_SIGNED_ZERO__ +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + + +/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */ +#ifndef __ARM_ARCH +# ifdef __ARM_ARCH_2__ +# define __ARM_ARCH 2 +# elif defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__) +# define __ARM_ARCH 3 +# elif defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__) +# define __ARM_ARCH 4 +# elif defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5E__) \ + || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH 5 +# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ + || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) +# define __ARM_ARCH 6 +# elif defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH 7 +# else +# error unknown arm architecture +# endif +#endif + +#ifdef __GNUC__ +# define __need_uClibc_config_h +# include <bits/uClibc_config.h> +# undef __need_uClibc_config_h +# if defined __CONFIG_ARM_EABI__ && !defined __ARM_EABI__ +# error Your toolchain does not support EABI +# elif !defined __CONFIG_ARM_EABI__ && defined __ARM_EABI__ +# error Your toolchain was built for EABI, but you have chosen OABI +# endif +#endif + #endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/arm/bits/wordsize.h b/libc/sysdeps/linux/arm/bits/wordsize.h index ba643b60a..ca82fd7d4 100644 --- a/libc/sysdeps/linux/arm/bits/wordsize.h +++ b/libc/sysdeps/linux/arm/bits/wordsize.h @@ -12,8 +12,7 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/arm/brk.c b/libc/sysdeps/linux/arm/brk.c index 47179901f..0d04eb4dd 100644 --- a/libc/sysdeps/linux/arm/brk.c +++ b/libc/sysdeps/linux/arm/brk.c @@ -13,15 +13,13 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <errno.h> #include <unistd.h> #include <sys/syscall.h> -libc_hidden_proto(brk) /* This must be initialized data because commons can't have aliases. */ void *__curbrk attribute_hidden = 0; diff --git a/libc/sysdeps/linux/arm/bsd-_setjmp.S b/libc/sysdeps/linux/arm/bsd-_setjmp.S index a05570df7..0320bb82c 100644 --- a/libc/sysdeps/linux/arm/bsd-_setjmp.S +++ b/libc/sysdeps/linux/arm/bsd-_setjmp.S @@ -13,9 +13,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <bits/arm_asm.h> diff --git a/libc/sysdeps/linux/arm/bsd-setjmp.S b/libc/sysdeps/linux/arm/bsd-setjmp.S index d7ca72ad5..f37110e36 100644 --- a/libc/sysdeps/linux/arm/bsd-setjmp.S +++ b/libc/sysdeps/linux/arm/bsd-setjmp.S @@ -13,9 +13,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <bits/arm_asm.h> diff --git a/libc/sysdeps/linux/arm/clone.S b/libc/sysdeps/linux/arm/clone.S index d9483735d..b4c7d8a02 100644 --- a/libc/sysdeps/linux/arm/clone.S +++ b/libc/sysdeps/linux/arm/clone.S @@ -13,29 +13,37 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* clone() is even more special than fork() as it mucks with stacks and invokes a function in the right context after its all over. */ +#include <sysdep.h> #define _ERRNO_H #include <features.h> #include <bits/errno.h> #include <sys/syscall.h> #include <bits/arm_asm.h> +#include <bits/arm_bx.h> + +#if defined __UCLIBC_HAS_THREADS__ && !defined __LINUXTHREADS_OLD__ +#include <sysdep-cancel.h> +#endif + +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 #if defined(__NR_clone) /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ .text -.global clone -.type clone,%function +.global __clone +.type __clone,%function .align 2 #if defined(THUMB1_ONLY) .thumb_func -clone: +__clone: @ sanity check args cmp r0, #0 beq __einval @@ -61,8 +69,13 @@ clone: @ pick the function arg and call address off the stack and execute ldr r0, [sp, #4] +#if defined(__USE_BX__) ldr r1, [sp] bl 2f @ blx r1 +#else + mov lr, pc + ldr pc, [sp] +#endif @ and we are done, passing the return value through r0 bl HIDDEN_JUMPTARGET(_exit) @@ -80,7 +93,9 @@ __error: POP_RET .pool #else -clone: +__clone: +.fnstart +.cantunwind @ sanity check args cmp r0, #0 IT(te, ne) @@ -89,25 +104,55 @@ clone: beq __error @ insert the args onto the new stack - sub r1, r1, #8 - str r3, [r1, #4] - @ save the function pointer as the 0th element - str r0, [r1] + str r3, [r1, #-4]! + str r0, [r1, #-4]! @ do the system call @ get flags mov r0, r2 +#ifdef RESET_PID + mov ip, r2 +#endif @ new sp is already in r1 - DO_CALL (clone) - movs a1, a1 + push {r4, r7} + cfi_adjust_cfa_offset (8) + cfi_rel_offset (r4, 0) + cfi_rel_offset (r7, 4) + ldr r2, [sp, #8] + ldr r3, [sp, #12] + ldr r4, [sp, #16] + ldr r7, =SYS_ify(clone) + swi 0x0 + cfi_endproc + cmp r0, #0 + beq 1f + pop {r4, r7} blt __error IT(t, ne) -#if defined(__USE_BX__) - bxne lr -#else - movne pc, lr -#endif + BXC(ne, lr) + + cfi_startproc +.fnend +PSEUDO_END (__clone) +1: + .fnstart + .cantunwind +#ifdef RESET_PID + tst ip, #CLONE_THREAD + bne 3f + GET_TLS (lr) + mov r1, r0 + tst ip, #CLONE_VM + ldr r7, =SYS_ify(getpid) + ite ne + movne r0, #-1 + swieq 0x0 + NEGOFF_ADJ_BASE (r1, TID_OFFSET) + str r0, NEGOFF_OFF1 (r1, TID_OFFSET) + str r0, NEGOFF_OFF2 (r1, PID_OFFSET, TID_OFFSET) +3: +#endif @ pick the function arg and call address off the stack and execute ldr r0, [sp, #4] mov lr, pc @@ -120,6 +165,7 @@ __error: b __syscall_error #endif -.size clone,.-clone +.size __clone,.-__clone +weak_alias(__clone, clone) #endif diff --git a/libc/sysdeps/linux/arm/crt1.S b/libc/sysdeps/linux/arm/crt1.S index 082348e39..ab3b0d293 100644 --- a/libc/sysdeps/linux/arm/crt1.S +++ b/libc/sysdeps/linux/arm/crt1.S @@ -31,9 +31,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* This is the canonical entry point, usually the first thing in the text segment. @@ -133,7 +132,6 @@ _start: #ifdef __PIC__ ldr r4, .L_GOT -.L_GOT_OFF: adr r5, .L_GOT add r4, r5, r4 @@ -201,8 +199,8 @@ _start: #ifdef __PIC__ ldr sl, .L_GOT -.L_GOT_OFF: - add sl, pc, sl + adr a4, .L_GOT + add sl, sl, a4 ldr ip, .L_GOT+4 /* _fini */ ldr a1, [sl, ip] @@ -238,7 +236,7 @@ _start: #ifdef __PIC__ .L_GOT: - .word _GLOBAL_OFFSET_TABLE_-(.L_GOT_OFF+8) + .word _GLOBAL_OFFSET_TABLE_ - .L_GOT .word _fini(GOT) .word _init(GOT) .word main(GOT) diff --git a/libc/sysdeps/linux/arm/crtn.S b/libc/sysdeps/linux/arm/crtn.S index de01b38dc..a4752c186 100644 --- a/libc/sysdeps/linux/arm/crtn.S +++ b/libc/sysdeps/linux/arm/crtn.S @@ -15,7 +15,6 @@ .arm ldmdb fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} #endif - .size _init, .-_init .section .fini .global _fini @@ -29,7 +28,6 @@ .arm ldmdb fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} #endif - .size _fini, .-_fini @ In fact this is modified to 3.4.4 .ident "GCC: (GNU) 3.3.2 20031005 (Debian prerelease)" diff --git a/libc/sysdeps/linux/arm/find_exidx.c b/libc/sysdeps/linux/arm/find_exidx.c index 9e4f4012f..679d90c05 100644 --- a/libc/sysdeps/linux/arm/find_exidx.c +++ b/libc/sysdeps/linux/arm/find_exidx.c @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <link.h> #include <unwind.h> @@ -65,8 +64,8 @@ find_exidx_callback (struct dl_phdr_info * info, size_t size, void * ptr) /* Find the exception index table containing PC. */ -_Unwind_Ptr -__gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount) +_Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount); +_Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount) { struct unw_eh_callback_data data; diff --git a/libc/sysdeps/linux/arm/fpu_control.h b/libc/sysdeps/linux/arm/fpu_control.h index 1170c9e97..1b9b09df6 100644 --- a/libc/sysdeps/linux/arm/fpu_control.h +++ b/libc/sysdeps/linux/arm/fpu_control.h @@ -13,9 +13,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _FPU_CONTROL_H #define _FPU_CONTROL_H diff --git a/libc/sysdeps/linux/arm/getcontext.S b/libc/sysdeps/linux/arm/getcontext.S new file mode 100644 index 000000000..a987c52f3 --- /dev/null +++ b/libc/sysdeps/linux/arm/getcontext.S @@ -0,0 +1,80 @@ +/* Copyright (C) 2012 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> + +#include "ucontext_i.h" + + .syntax unified + .text + +/* int getcontext (ucontext_t *ucp) */ + +ENTRY(__getcontext) + /* No need to save r0-r3, d0-d7, or d16-d31. */ + add r1, r0, #MCONTEXT_ARM_R4 + stmia r1, {r4-r11} + + /* Save R13 separately as Thumb can't STM it. */ + str r13, [r0, #MCONTEXT_ARM_SP] + str r14, [r0, #MCONTEXT_ARM_LR] + /* Return to LR */ + str r14, [r0, #MCONTEXT_ARM_PC] + /* Return zero */ + mov r2, #0 + str r2, [r0, #MCONTEXT_ARM_R0] + + /* Save ucontext_t * across the next call. */ + mov r4, r0 + + /* __sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */ + mov r0, #SIG_BLOCK + mov r1, #0 + add r2, r4, #UCONTEXT_SIGMASK + bl PLTJMP(sigprocmask) + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +# ifdef __VFP_FP__ + /* Store the VFP registers. */ + /* Following instruction is fstmiax ip!, {d8-d15}. */ + stc p11, cr8, [r0], #64 + /* Store the floating-point status register. */ + /* Following instruction is fmrx r2, fpscr. */ + mrc p10, 7, r1, cr1, cr0, 0 + str r1, [r0], #4 +# endif +#endif +#ifdef __IWMMXT__ + /* Save the call-preserved iWMMXt registers. */ + /* Following instructions are wstrd wr10, [r0], #8 (etc.) */ + stcl p1, cr10, [r0], #8 + stcl p1, cr11, [r0], #8 + stcl p1, cr12, [r0], #8 + stcl p1, cr13, [r0], #8 + stcl p1, cr14, [r0], #8 + stcl p1, cr15, [r0], #8 +#endif + + /* Restore the clobbered R4 and LR. */ + ldr r14, [r4, #MCONTEXT_ARM_LR] + ldr r4, [r4, #MCONTEXT_ARM_R4] + + mov r0, #0 + DO_RET(r14) + +END(__getcontext) +weak_alias(__getcontext, getcontext) diff --git a/libc/sysdeps/linux/arm/ioperm.c b/libc/sysdeps/linux/arm/ioperm.c index 708e8ec49..d7ea52695 100644 --- a/libc/sysdeps/linux/arm/ioperm.c +++ b/libc/sysdeps/linux/arm/ioperm.c @@ -14,9 +14,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* I/O port access on the ARM is something of a fiction. What we do is to map an appropriate area of /dev/mem into user space so that a program @@ -33,33 +32,16 @@ the area affected (this is a kernel limitation). So we now just enable all the ports all of the time. */ +#include <sys/io.h> +#include <sys/mman.h> +#include <sys/sysctl.h> +#include <paths.h> #include <errno.h> -#include <fcntl.h> -#include <stdio.h> #include <ctype.h> -#include <stdlib.h> +#include <stdio.h> #include <string.h> #include <unistd.h> - -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/sysctl.h> -#include <sys/io.h> - -libc_hidden_proto(ioperm) - -libc_hidden_proto(readlink) -libc_hidden_proto(mmap) -libc_hidden_proto(sscanf) -libc_hidden_proto(fscanf) -libc_hidden_proto(fprintf) -libc_hidden_proto(fgets) -libc_hidden_proto(fopen) -libc_hidden_proto(fclose) -/* Experimentally off - libc_hidden_proto(strcmp) */ -libc_hidden_proto(open) -libc_hidden_proto(close) - +#include <fcntl.h> #include <linux/version.h> #define PATH_ARM_SYSTYPE "/etc/arm_systype" @@ -198,7 +180,7 @@ int ioperm (unsigned long int from, unsigned long int num, int turn_on) if (! io.base) { int fd; - fd = open ("/dev/mem", O_RDWR); + fd = open (_PATH_MEM, O_RDWR); if (fd < 0) return -1; diff --git a/libc/sysdeps/linux/arm/iopl.c b/libc/sysdeps/linux/arm/iopl.c index 654a4158f..005f2f403 100644 --- a/libc/sysdeps/linux/arm/iopl.c +++ b/libc/sysdeps/linux/arm/iopl.c @@ -14,14 +14,12 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <sys/io.h> #include <errno.h> -libc_hidden_proto(ioperm) #define MAX_PORT 0x10000 diff --git a/libc/sysdeps/linux/arm/jmpbuf-offsets.h b/libc/sysdeps/linux/arm/jmpbuf-offsets.h new file mode 100644 index 000000000..93b50afc5 --- /dev/null +++ b/libc/sysdeps/linux/arm/jmpbuf-offsets.h @@ -0,0 +1,19 @@ +/* Private macros for accessing __jmp_buf contents. ARM version. + Copyright (C) 2006 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 + <http://www.gnu.org/licenses/>. */ + +#define __JMP_BUF_SP 8 diff --git a/libc/sysdeps/linux/arm/jmpbuf-unwind.h b/libc/sysdeps/linux/arm/jmpbuf-unwind.h new file mode 100644 index 000000000..d7b49e224 --- /dev/null +++ b/libc/sysdeps/linux/arm/jmpbuf-unwind.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include <setjmp.h> +#include <jmpbuf-offsets.h> + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP])) + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include <stdint.h> +#include <unwind.h> + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#undef _JMPBUF_UNWINDS +#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \ + ((void *) (address) < (void *) demangle (jmpbuf[__JMP_BUF_SP])) + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[__JMP_BUF_SP] - (_adj)) +#endif diff --git a/libc/sysdeps/linux/arm/libc-aeabi_read_tp.S b/libc/sysdeps/linux/arm/libc-aeabi_read_tp.S new file mode 100644 index 000000000..3aa135bf2 --- /dev/null +++ b/libc/sysdeps/linux/arm/libc-aeabi_read_tp.S @@ -0,0 +1 @@ +#include <ldso/ldso/arm/aeabi_read_tp.S> diff --git a/libc/sysdeps/linux/arm/libc-thumb_atomics.S b/libc/sysdeps/linux/arm/libc-thumb_atomics.S new file mode 100644 index 000000000..e7bc8950d --- /dev/null +++ b/libc/sysdeps/linux/arm/libc-thumb_atomics.S @@ -0,0 +1 @@ +#include <ldso/ldso/arm/thumb_atomics.S> diff --git a/libc/sysdeps/linux/arm/makecontext.c b/libc/sysdeps/linux/arm/makecontext.c new file mode 100644 index 000000000..d6ae6f0d7 --- /dev/null +++ b/libc/sysdeps/linux/arm/makecontext.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2012 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 + <http://www.gnu.org/licenses/>. */ + +#include <stdarg.h> +#include <ucontext.h> + +/* Number of arguments that go in registers. */ +#define NREG_ARGS 4 + +/* Take a context previously prepared via getcontext() and set to + call func() with the given int only args. */ +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) +{ + extern void __startcontext (void); + unsigned long *funcstack; + va_list vl; + unsigned long *regptr; + unsigned int reg; + int misaligned; + + /* Start at the top of stack. */ + funcstack = (unsigned long *) (ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + + /* Ensure the stack stays eight byte aligned. */ + misaligned = ((unsigned long) funcstack & 4) != 0; + + if ((argc > NREG_ARGS) && (argc & 1) != 0) + misaligned = !misaligned; + + if (misaligned) + funcstack -= 1; + + va_start (vl, argc); + + /* Reserve space for the on-stack arguments. */ + if (argc > NREG_ARGS) + funcstack -= (argc - NREG_ARGS); + + ucp->uc_mcontext.arm_sp = (unsigned long) funcstack; + ucp->uc_mcontext.arm_pc = (unsigned long) func; + + /* Exit to startcontext() with the next context in R4 */ + ucp->uc_mcontext.arm_r4 = (unsigned long) ucp->uc_link; + ucp->uc_mcontext.arm_lr = (unsigned long) __startcontext; + + /* The first four arguments go into registers. */ + regptr = &(ucp->uc_mcontext.arm_r0); + + for (reg = 0; (reg < argc) && (reg < NREG_ARGS); reg++) + *regptr++ = va_arg (vl, unsigned long); + + /* And the remainder on the stack. */ + for (; reg < argc; reg++) + *funcstack++ = va_arg (vl, unsigned long); + + va_end (vl); +} +weak_alias (__makecontext, makecontext) diff --git a/libc/sysdeps/linux/arm/mmap.c b/libc/sysdeps/linux/arm/mmap.c deleted file mode 100644 index 47a29f4ae..000000000 --- a/libc/sysdeps/linux/arm/mmap.c +++ /dev/null @@ -1,74 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * _mmap() for uClibc - * - * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> - * - * GNU Library General Public License (LGPL) version 2 or later. - */ -#include <errno.h> -#include <unistd.h> -#include <sys/mman.h> -#include <sys/syscall.h> - -#if defined (__NR_mmap) || defined (__NR_mmap2) - -libc_hidden_proto (mmap) -#if defined (__UCLIBC_MMAP_HAS_6_ARGS__) && defined (__NR_mmap) -#define __NR__mmap __NR_mmap -static __inline__ _syscall6 (__ptr_t, _mmap, __ptr_t, addr, size_t, len, - int, prot, int, flags, int, fd, __off_t, offset); -__ptr_t mmap(__ptr_t addr, size_t len, int prot, - int flags, int fd, __off_t offset) -{ - return (__ptr_t) _mmap (addr, len, prot, flags, - fd, offset); -} - -#elif defined (__NR_mmap2) -#define __NR__mmap __NR_mmap2 - -#ifndef MMAP2_PAGE_SHIFT -# define MMAP2_PAGE_SHIFT 12 -#endif - -static __inline__ _syscall6 (__ptr_t, _mmap, __ptr_t, addr, size_t, len, - int, prot, int, flags, int, fd, __off_t, offset); -__ptr_t mmap(__ptr_t addr, size_t len, int prot, - int flags, int fd, __off_t offset) -{ - /* check if offset is page aligned */ - if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) - { - __set_errno(EINVAL); - return MAP_FAILED; - } -#ifdef __USE_FILE_OFFSET64 - return (__ptr_t) _mmap (addr, len, prot, flags, - fd, ((__u_quad_t) offset >> MMAP2_PAGE_SHIFT)); -#else - return (__ptr_t) _mmap (addr, len, prot, flags, - fd, ((__u_long) offset >> MMAP2_PAGE_SHIFT)); -#endif -} -#elif defined (__NR_mmap) -# define __NR__mmap __NR_mmap -static __inline__ _syscall1(__ptr_t, _mmap, unsigned long *, buffer); -__ptr_t mmap(__ptr_t addr, size_t len, int prot, - int flags, int fd, __off_t offset) -{ - unsigned long buffer[6]; - - buffer[0] = (unsigned long) addr; - buffer[1] = (unsigned long) len; - buffer[2] = (unsigned long) prot; - buffer[3] = (unsigned long) flags; - buffer[4] = (unsigned long) fd; - buffer[5] = (unsigned long) offset; - return (__ptr_t) _mmap(buffer); -} -#endif -libc_hidden_def (mmap) -#else -# error "Your architecture doesn't seem to provide mmap() !?" -#endif diff --git a/libc/sysdeps/linux/arm/mmap64.S b/libc/sysdeps/linux/arm/mmap64.S index 707154124..c9f2bd2f7 100644 --- a/libc/sysdeps/linux/arm/mmap64.S +++ b/libc/sysdeps/linux/arm/mmap64.S @@ -12,17 +12,17 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ -#include <features.h> +#include <_lfs_64.h> #define _ERRNO_H #include <bits/errno.h> #include <sys/syscall.h> #include <bits/arm_asm.h> +#include <bits/arm_bx.h> -#if defined __UCLIBC_HAS_LFS__ && defined __NR_mmap2 +#ifdef __NR_mmap2 /* The mmap2 system call takes six arguments, all in registers. */ .text @@ -92,11 +92,7 @@ mmap64: cmn r0, $4096 ldmfd sp!, {r4, r5} IT(t, cc) -#if defined(__USE_BX__) - bxcc lr -#else - movcc pc, lr -#endif + BXC(cc, lr) b __syscall_error .Linval: mov r0, $-EINVAL diff --git a/libc/sysdeps/linux/arm/posix_fadvise.c b/libc/sysdeps/linux/arm/posix_fadvise.c deleted file mode 100644 index bb4ac7b0c..000000000 --- a/libc/sysdeps/linux/arm/posix_fadvise.c +++ /dev/null @@ -1,36 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * posix_fadvise() for ARM uClibc - * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html - * - * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> - * - * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - */ -#include <sys/syscall.h> -#include <fcntl.h> -#if defined __NR_arm_fadvise64_64 -/* This is for the ARM version of fadvise64_64 which swaps the params - * * about to avoid having ABI compat issues - * */ -#define __NR___syscall_arm_fadvise64_64 __NR_arm_fadvise64_64 -int __libc_posix_fadvise(int fd, off_t offset, off_t len, int advise) -{ - INTERNAL_SYSCALL_DECL (err); - int ret = INTERNAL_SYSCALL (arm_fadvise64_64, err, 6, fd, advise, - __LONG_LONG_PAIR ((long)(offset >> 32), (long)offset), - __LONG_LONG_PAIR ((long)(len >> 32), (long)len)); - - if (INTERNAL_SYSCALL_ERROR_P (ret, err)) - return INTERNAL_SYSCALL_ERRNO (ret, err); - return 0; - -} -weak_alias(__libc_posix_fadvise, posix_fadvise); -#else -int posix_fadvise(int fd attribute_unused, off_t offset attribute_unused, off_t len attribute_unused, int advice attribute_unused) -{ - return ENOSYS; -} -#endif - diff --git a/libc/sysdeps/linux/arm/posix_fadvise64.c b/libc/sysdeps/linux/arm/posix_fadvise64.c deleted file mode 100644 index 479b0c5a2..000000000 --- a/libc/sysdeps/linux/arm/posix_fadvise64.c +++ /dev/null @@ -1,46 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * posix_fadvise64() for ARM uClibc - * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html - * - * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> - * - * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - */ - -#include <features.h> -#include <unistd.h> -#include <errno.h> -#include <endian.h> -#include <stdint.h> -#include <sys/types.h> -#include <sys/syscall.h> -#include <fcntl.h> - -#ifdef __UCLIBC_HAS_LFS__ - -#if defined __NR_arm_fadvise64_64 -/* This is for the ARM version of fadvise64_64 which swaps the params - * about to avoid having ABI compat issues - */ -#define __NR___syscall_arm_fadvise64_64 __NR_arm_fadvise64_64 -int __libc_posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advise) -{ - INTERNAL_SYSCALL_DECL (err); - int ret = INTERNAL_SYSCALL (arm_fadvise64_64, err, 6, fd, advise, - __LONG_LONG_PAIR ((long)(offset >> 32), (long)offset), - __LONG_LONG_PAIR ((long)(len >> 32), (long)len)); - if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) - return 0; - if (INTERNAL_SYSCALL_ERRNO (ret, err) != ENOSYS) - return INTERNAL_SYSCALL_ERRNO (ret, err); - return 0; -} -weak_alias(__libc_posix_fadvise64, posix_fadvise64); -#else -int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advise) -{ - return ENOSYS; -} -#endif -#endif diff --git a/libc/sysdeps/linux/arm/setcontext.S b/libc/sysdeps/linux/arm/setcontext.S new file mode 100644 index 000000000..a5c33a022 --- /dev/null +++ b/libc/sysdeps/linux/arm/setcontext.S @@ -0,0 +1,76 @@ +/* Copyright (C) 2012 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> + +#include "ucontext_i.h" + + .syntax unified + .text + +/* int setcontext (const ucontext_t *ucp) */ + +ENTRY(__setcontext) + mov r4, r0 + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +# ifdef __VFP_FP__ + /* Following instruction is vldmia r0!, {d8-d15}. */ + ldc p11, cr8, [r0], #64 + /* Restore the floating-point status register. */ + ldr r1, [r0], #4 + /* Following instruction is fmxr fpscr, r1. */ + mcr p10, 7, r1, cr1, cr0, 0 +# endif +#endif + +#ifdef __IWMMXT__ + /* Restore the call-preserved iWMMXt registers. */ + /* Following instructions are wldrd wr10, [r0], #8 (etc.) */ + ldcl p1, cr10, [r0], #8 + ldcl p1, cr11, [r0], #8 + ldcl p1, cr12, [r0], #8 + ldcl p1, cr13, [r0], #8 + ldcl p1, cr14, [r0], #8 + ldcl p1, cr15, [r0], #8 +#endif + + /* Now bring back the signal status. */ + mov r0, #SIG_SETMASK + add r1, r4, #UCONTEXT_SIGMASK + mov r2, #0 + bl PLTJMP(sigprocmask) + + /* Loading r0-r3 makes makecontext easier. */ + add r14, r4, #MCONTEXT_ARM_R0 + ldmia r14, {r0-r11} + ldr r13, [r14, #(MCONTEXT_ARM_SP - MCONTEXT_ARM_R0)] + add r14, r14, #(MCONTEXT_ARM_LR - MCONTEXT_ARM_R0) + ldmia r14, {r14, pc} + +END(setcontext) +weak_alias(__setcontext, setcontext) + + /* Called when a makecontext() context returns. Start the + context in R4 or fall through to exit(). */ +ENTRY(__startcontext) + movs r0, r4 + bne PLTJMP(__setcontext) + + @ New context was 0 - exit + b PLTJMP(_exit) +END(__startcontext) diff --git a/libc/sysdeps/linux/arm/setjmp.S b/libc/sysdeps/linux/arm/setjmp.S index 2df7d551a..f7a74cc5a 100644 --- a/libc/sysdeps/linux/arm/setjmp.S +++ b/libc/sysdeps/linux/arm/setjmp.S @@ -13,9 +13,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <features.h> #include <bits/arm_asm.h> @@ -47,7 +46,7 @@ __sigsetjmp: mov ip, r0 #if defined(__thumb2__) stmia ip!, {v1-v6, sl, fp} - movs r2, sp + mov r2, sp stmia ip!, {r2, lr} #else /* Save registers */ diff --git a/libc/sysdeps/linux/arm/sigaction.c b/libc/sysdeps/linux/arm/sigaction.c index 552ac17bf..22d4248f3 100644 --- a/libc/sysdeps/linux/arm/sigaction.c +++ b/libc/sysdeps/linux/arm/sigaction.c @@ -12,9 +12,8 @@ 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. + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. Totally hacked up for uClibc by Erik Andersen <andersen@codepoet.org> */ @@ -29,98 +28,76 @@ extern void __default_sa_restorer(void); extern void __default_rt_sa_restorer(void); -extern __typeof(sigaction) __libc_sigaction; - /* When RT signals are in use we need to use a different return stub. */ #ifdef __NR_rt_sigreturn #define choose_restorer(flags) \ - (flags & SA_SIGINFO) ? __default_rt_sa_restorer \ - : __default_sa_restorer + (flags & SA_SIGINFO) ? __default_rt_sa_restorer \ + : __default_sa_restorer #else #define choose_restorer(flags) \ - __default_sa_restorer + __default_sa_restorer #endif -#ifdef __NR_rt_sigaction -/* Experimentally off - libc_hidden_proto(memcpy) */ +#ifdef __NR_rt_sigaction /* If ACT is not NULL, change the action for SIG to *ACT. If OACT is not NULL, put the old action for SIG in *OACT. */ -int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { - int result; - struct kernel_sigaction kact, koact; - - if (act) { - kact.k_sa_handler = act->sa_handler; - memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t)); - kact.sa_flags = act->sa_flags; -# ifdef HAVE_SA_RESTORER - if (kact.sa_flags & SA_RESTORER) { - kact.sa_restorer = act->sa_restorer; - } else { - kact.sa_restorer = choose_restorer (kact.sa_flags); - kact.sa_flags |= SA_RESTORER; + struct sigaction kact; + if (act && !(act->sa_flags & SA_RESTORER)) { + memcpy(&kact, act, sizeof(kact)); + kact.sa_restorer = choose_restorer(kact.sa_flags); + kact.sa_flags |= SA_RESTORER; + act = &kact; } -# endif - } - - /* XXX The size argument hopefully will have to be changed to the - real size of the user-level sigset_t. */ - result = __syscall_rt_sigaction(sig, act ? __ptrvalue (&kact) : NULL, - oact ? __ptrvalue (&koact) : NULL, _NSIG / 8); - if (oact && result >= 0) { - oact->sa_handler = koact.k_sa_handler; - memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t)); - oact->sa_flags = koact.sa_flags; -# ifdef HAVE_SA_RESTORER - oact->sa_restorer = koact.sa_restorer; -# endif - } - return result; + /* NB: kernel (as of 2.6.25) will return EINVAL + * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t) */ + return __syscall_rt_sigaction(sig, act, oact, sizeof(act->sa_mask)); } - #else /* If ACT is not NULL, change the action for SIG to *ACT. If OACT is not NULL, put the old action for SIG in *OACT. */ -int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { - int result; - struct old_kernel_sigaction kact, koact; - - if (act) { - kact.k_sa_handler = act->sa_handler; - kact.sa_mask = act->sa_mask.__val[0]; - kact.sa_flags = act->sa_flags; -# ifdef HAVE_SA_RESTORER - if (kact.sa_flags & SA_RESTORER) { - kact.sa_restorer = act->sa_restorer; - } else { - kact.sa_restorer = choose_restorer (kact.sa_flags); - kact.sa_flags |= SA_RESTORER; + int result; + struct old_kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags; + if (kact.sa_flags & SA_RESTORER) { + kact.sa_restorer = act->sa_restorer; + } else { + kact.sa_restorer = choose_restorer(kact.sa_flags); + kact.sa_flags |= SA_RESTORER; + } } -# endif - } - result = __syscall_sigaction(sig, act ? __ptrvalue (&kact) : NULL, - oact ? __ptrvalue (&koact) : NULL); - if (oact && result >= 0) { - oact->sa_handler = koact.k_sa_handler; - oact->sa_mask.__val[0] = koact.sa_mask; - oact->sa_flags = koact.sa_flags; -# ifdef HAVE_SA_RESTORER - oact->sa_restorer = koact.sa_restorer; -# endif - } - return result; + result = __syscall_sigaction(sig, + act ? &kact : NULL, + oact ? &koact : NULL); + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return result; } #endif + #ifndef LIBC_SIGACTION -libc_hidden_proto(sigaction) +# ifndef __UCLIBC_HAS_THREADS__ +strong_alias(__libc_sigaction,sigaction) +libc_hidden_def(sigaction) +# else weak_alias(__libc_sigaction,sigaction) libc_hidden_weak(sigaction) +# endif #endif diff --git a/libc/sysdeps/linux/arm/sigrestorer.S b/libc/sysdeps/linux/arm/sigrestorer.S index 79728fd40..f657fe333 100644 --- a/libc/sysdeps/linux/arm/sigrestorer.S +++ b/libc/sysdeps/linux/arm/sigrestorer.S @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <bits/arm_asm.h> #include <sys/syscall.h> diff --git a/libc/sysdeps/linux/arm/swapcontext.S b/libc/sysdeps/linux/arm/swapcontext.S new file mode 100644 index 000000000..ba6e31c4d --- /dev/null +++ b/libc/sysdeps/linux/arm/swapcontext.S @@ -0,0 +1,63 @@ +/* Copyright (C) 2012 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> + +#include "ucontext_i.h" + + .syntax unified + .text + +/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ + +ENTRY(swapcontext) + + /* Have getcontext() do most of the work then fix up + LR afterwards. Save R3 to keep the stack aligned. */ + push {r0,r1,r3,r14} + cfi_adjust_cfa_offset (16) + cfi_rel_offset (r0,0) + cfi_rel_offset (r1,4) + cfi_rel_offset (r3,8) + cfi_rel_offset (r14,12) + + bl __getcontext + mov r4, r0 + + pop {r0,r1,r3,r14} + cfi_adjust_cfa_offset (-16) + cfi_restore (r0) + cfi_restore (r1) + cfi_restore (r3) + cfi_restore (r14) + + /* Exit if getcontext() failed. */ + cmp r4, #0 + itt ne + movne r0, r4 + RETINSTR(ne, r14) + + /* Fix up LR and the PC. */ + str r13,[r0, #MCONTEXT_ARM_SP] + str r14,[r0, #MCONTEXT_ARM_LR] + str r14,[r0, #MCONTEXT_ARM_PC] + + /* And swap using swapcontext(). */ + mov r0, r1 + b __setcontext + +END(swapcontext) diff --git a/libc/sysdeps/linux/arm/sys/elf.h b/libc/sysdeps/linux/arm/sys/elf.h index faa731068..4c06715da 100644 --- a/libc/sysdeps/linux/arm/sys/elf.h +++ b/libc/sysdeps/linux/arm/sys/elf.h @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _SYS_ELF_H #define _SYS_ELF_H 1 diff --git a/libc/sysdeps/linux/arm/sys/io.h b/libc/sysdeps/linux/arm/sys/io.h index 68639902c..1a47bb514 100644 --- a/libc/sysdeps/linux/arm/sys/io.h +++ b/libc/sysdeps/linux/arm/sys/io.h @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _SYS_IO_H @@ -23,16 +22,19 @@ __BEGIN_DECLS +#if defined __UCLIBC_LINUX_SPECIFIC__ /* If TURN_ON is TRUE, request for permission to do direct i/o on the port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O permission off for that range. This call requires root privileges. */ extern int ioperm (unsigned long int __from, unsigned long int __num, int __turn_on) __THROW; +libc_hidden_proto(ioperm) /* Set the I/O privilege level to LEVEL. If LEVEL is nonzero, permission to access any I/O port is granted. This call requires root privileges. */ extern int iopl (int __level) __THROW; +#endif /* __UCLIBC_LINUX_SPECIFIC__ */ /* The functions that actually perform reads and writes. */ extern unsigned char inb (unsigned long int port) __THROW; diff --git a/libc/sysdeps/linux/arm/sys/procfs.h b/libc/sysdeps/linux/arm/sys/procfs.h index 3b3736324..14f233a63 100644 --- a/libc/sysdeps/linux/arm/sys/procfs.h +++ b/libc/sysdeps/linux/arm/sys/procfs.h @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _SYS_PROCFS_H #define _SYS_PROCFS_H 1 diff --git a/libc/sysdeps/linux/arm/sys/ucontext.h b/libc/sysdeps/linux/arm/sys/ucontext.h index 9ecff7b59..c10d774a5 100644 --- a/libc/sysdeps/linux/arm/sys/ucontext.h +++ b/libc/sysdeps/linux/arm/sys/ucontext.h @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* System V/ARM ABI compliant context switching support. */ diff --git a/libc/sysdeps/linux/arm/sys/user.h b/libc/sysdeps/linux/arm/sys/user.h index 3fae43f83..4420fc9c8 100644 --- a/libc/sysdeps/linux/arm/sys/user.h +++ b/libc/sysdeps/linux/arm/sys/user.h @@ -12,9 +12,8 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _SYS_USER_H #define _SYS_USER_H 1 diff --git a/libc/sysdeps/linux/arm/syscall-eabi.S b/libc/sysdeps/linux/arm/syscall-eabi.S index b9318821b..534c6e988 100644 --- a/libc/sysdeps/linux/arm/syscall-eabi.S +++ b/libc/sysdeps/linux/arm/syscall-eabi.S @@ -12,12 +12,12 @@ 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. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ -#include <sys/syscall.h> +#include <features.h> #include <bits/arm_asm.h> +#include <bits/arm_bx.h> /* In the EABI syscall interface, we don't need a special syscall to implement syscall(). It won't work reliably with 64-bit arguments @@ -62,11 +62,7 @@ syscall: ldmfd sp!, {r4, r5, r6, r7} cmn r0, #4096 IT(t, cc) -#if defined(__USE_BX__) - bxcc lr -#else - movcc pc, lr -#endif + BXC(cc, lr) b __syscall_error #endif diff --git a/libc/sysdeps/linux/arm/sysdep.h b/libc/sysdeps/linux/arm/sysdep.h new file mode 100644 index 000000000..14529892d --- /dev/null +++ b/libc/sysdeps/linux/arm/sysdep.h @@ -0,0 +1,396 @@ +/* Assembler macros for ARM. + Copyright (C) 1997, 1998, 2003 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _LINUX_ARM_SYSDEP_H +#define _LINUX_ARM_SYSDEP_H 1 + +#include <common/sysdep.h> +#include <bits/arm_bx.h> +#include <sys/syscall.h> +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#define SWI_BASE (0x900000) +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +#define ALIGNARG(log2) log2 +/* For ELF we need the `.type' directive to make shared libs work right. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +/* In ELF C symbols are asm symbols. */ +#undef NO_UNDERSCORES +#define NO_UNDERSCORES + +#define PLTJMP(_x) _x##(PLT) + +/* APCS-32 doesn't preserve the condition codes across function call. */ +#ifdef __APCS_32__ +#define LOADREGS(cond, base, reglist...)\ + ldm##cond base,reglist +#define RETINSTR(cond, reg) \ + BXC(cond, reg) +#define DO_RET(_reg) \ + BX(_reg) +#else /* APCS-26 */ +#define LOADREGS(cond, base, reglist...) \ + ldm##cond base,reglist^ +#define RETINSTR(cond, reg) \ + mov##cond##s pc, reg +#define DO_RET(_reg) \ + movs pc, _reg +#endif + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + .globl C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \ + .align ALIGNARG(4); \ + name##: \ + CALL_MCOUNT + +#undef END +#define END(name) \ + ASM_SIZE_DIRECTIVE(name) + +/* If compiled for profiling, call `mcount' at the start of each function. */ +#ifdef PROF +#define CALL_MCOUNT \ + str lr,[sp, #-4]! ; \ + bl PLTJMP(mcount) ; \ + ldr lr, [sp], #4 ; +#else +#define CALL_MCOUNT /* Do nothing. */ +#endif + +#ifdef NO_UNDERSCORES +/* Since C identifiers are not normally prefixed with an underscore + on this system, the asm identifier `syscall_error' intrudes on the + C name space. Make sure we use an innocuous name. */ +#define syscall_error __syscall_error +#define mcount _mcount +#endif +/* Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the `lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in R0 + is a real error number. Linus said he will make sure the no syscall + returns a value in -1 .. -4095 as a valid result so we can safely + test with -4095. */ + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args); \ + cmn r0, $4096; + +#define PSEUDO_RET \ + RETINSTR(cc, lr); \ + b PLTJMP(SYSCALL_ERROR) +#undef ret +#define ret PSEUDO_RET + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + SYSCALL_ERROR_HANDLER \ + END (name) + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args); + +#define PSEUDO_RET_NOERRNO \ + DO_RET (lr); + +#undef ret_NOERRNO +#define ret_NOERRNO PSEUDO_RET_NOERRNO + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +/* The function has to return the error code. */ +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + rsb r0, r0, #0 + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +#undef ret_ERRVAL +#define ret_ERRVAL PSEUDO_RET_NOERRNO + +#if defined NOT_IN_libc +# define SYSCALL_ERROR __local_syscall_error +# ifdef RTLD_PRIVATE_ERRNO +# define SYSCALL_ERROR_HANDLER \ +__local_syscall_error: \ + ldr r1, 1f; \ + rsb r0, r0, #0; \ +0: str r0, [pc, r1]; \ + mvn r0, #0; \ + DO_RET(lr); \ +1: .word C_SYMBOL_NAME(rtld_errno) - 0b - 8; +# else +# define SYSCALL_ERROR_HANDLER \ +__local_syscall_error: \ + str lr, [sp, #-4]!; \ + str r0, [sp, #-4]!; \ + bl PLTJMP(C_SYMBOL_NAME(__errno_location)); \ + ldr r1, [sp], #4; \ + rsb r1, r1, #0; \ + str r1, [r0]; \ + mvn r0, #0; \ + ldr pc, [sp], #4; +# endif +#else +# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +# define SYSCALL_ERROR __syscall_error +#endif + +/* Linux takes system call args in registers: + syscall number in the SWI instruction + arg 1 r0 + arg 2 r1 + arg 3 r2 + arg 4 r3 + arg 5 r4 (this is different from the APCS convention) + arg 6 r5 + arg 7 r6 + + The compiler is going to form a call by coming here, through PSEUDO, with + arguments + syscall number in the DO_CALL macro + arg 1 r0 + arg 2 r1 + arg 3 r2 + arg 4 r3 + arg 5 [sp] + arg 6 [sp+4] + arg 7 [sp+8] + + We need to shuffle values between R4..R6 and the stack so that the + caller's v1..v3 and stack frame are not corrupted, and the kernel + sees the right arguments. + +*/ +#if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__) +# define ARCH_HAS_HARD_TP +#endif + +# ifdef __thumb2__ +# define NEGOFF_ADJ_BASE(R, OFF) add R, R, $OFF +# define NEGOFF_ADJ_BASE2(D, S, OFF) add D, S, $OFF +# define NEGOFF_OFF1(R, OFF) [R] +# define NEGOFF_OFF2(R, OFFA, OFFB) [R, $((OFFA) - (OFFB))] +# else +# define NEGOFF_ADJ_BASE(R, OFF) +# define NEGOFF_ADJ_BASE2(D, S, OFF) mov D, S +# define NEGOFF_OFF1(R, OFF) [R, $OFF] +# define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA] +# endif + +# ifdef ARCH_HAS_HARD_TP +/* If the cpu has cp15 available, use it. */ +# define GET_TLS(TMP) mrc p15, 0, r0, c13, c0, 3 +# else +/* At this generic level we have no tricks to pull. Call the ABI routine. */ +# define GET_TLS(TMP) \ + push { r1, r2, r3, lr }; \ + cfi_remember_state; \ + cfi_adjust_cfa_offset (16); \ + cfi_rel_offset (r1, 0); \ + cfi_rel_offset (r2, 4); \ + cfi_rel_offset (r3, 8); \ + cfi_rel_offset (lr, 12); \ + bl __aeabi_read_tp; \ + pop { r1, r2, r3, lr }; \ + cfi_restore_state +# endif /* ARCH_HAS_HARD_TP */ + + + + +#undef DO_CALL +#if defined(__ARM_EABI__) +#define DO_CALL(syscall_name, args) \ + DOARGS_##args \ + mov ip, r7; \ + ldr r7, =SYS_ify (syscall_name); \ + swi 0x0; \ + mov r7, ip; \ + UNDOARGS_##args +#else +#define DO_CALL(syscall_name, args) \ + DOARGS_##args \ + swi SYS_ify (syscall_name); \ + UNDOARGS_##args +#endif + +#define DOARGS_0 /* nothing */ +#define DOARGS_1 /* nothing */ +#define DOARGS_2 /* nothing */ +#define DOARGS_3 /* nothing */ +#define DOARGS_4 /* nothing */ +#define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $4]; +#define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmia ip, {r4, r5}; +#define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmia ip, {r4, r5, r6}; + +#define UNDOARGS_0 /* nothing */ +#define UNDOARGS_1 /* nothing */ +#define UNDOARGS_2 /* nothing */ +#define UNDOARGS_3 /* nothing */ +#define UNDOARGS_4 /* nothing */ +#define UNDOARGS_5 ldr r4, [sp], $4; +#define UNDOARGS_6 ldmfd sp!, {r4, r5}; +#define UNDOARGS_7 ldmfd sp!, {r4, r5, r6}; + +#else /* not __ASSEMBLER__ */ +/* Define a macro which expands into the inline wrapper code for a system + call. */ +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ unsigned int _inline_sys_result = INTERNAL_SYSCALL (name, , nr, args); \ + if (unlikely (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, ))) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, )); \ + _inline_sys_result = (unsigned int) -1; \ + } \ + (int) _inline_sys_result; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#undef INTERNAL_SYSCALL_RAW +#if defined(__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_ARG_7 is sacrificed. + * We can't use push/pop inside the asm because that breaks + * unwinding (ie. thread cancellation). + */ +#define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \ + ({ unsigned int _internal_sys_result; \ + { \ + int _sys_buf[2]; \ + register int __a1 __asm__ ("a1"); \ + register int *_v3 __asm__ ("v3") = _sys_buf; \ + LOAD_ARGS_##nr (args) \ + *_v3 = (int) (name); \ + __asm__ __volatile__ ("str r7, [v3, #4]\n" \ + "\tldr r7, [v3]\n" \ + "\tswi 0 @ syscall " #name "\n" \ + "\tldr r7, [v3, #4]" \ + : "=r" (__a1) \ + : "r" (_v3) ASM_ARGS_##nr \ + : "memory"); \ + _internal_sys_result = __a1; \ + } \ + (int) _internal_sys_result; }) +#elif defined(__ARM_EABI__) +#define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \ + ({unsigned int _internal_sys_result; \ + { \ + register int __a1 __asm__ ("r0"), _nr __asm__ ("r7"); \ + LOAD_ARGS_##nr (args) \ + _nr = name; \ + __asm__ __volatile__ ("swi 0x0 @ syscall " #name \ + : "=r" (__a1) \ + : "r" (_nr) ASM_ARGS_##nr \ + : "memory"); \ + _internal_sys_result = __a1; \ + } \ + (int) _internal_sys_result; }) +#else /* !defined(__ARM_EABI__) */ +#define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \ + ({ unsigned int _internal_sys_result; \ + { \ + register int __a1 __asm__ ("a1"); \ + LOAD_ARGS_##nr (args) \ + __asm__ __volatile__ ("swi %1 @ syscall " #name \ + : "=r" (__a1) \ + : "i" (name) ASM_ARGS_##nr \ + : "memory"); \ + _internal_sys_result = __a1; \ + } \ + (int) _internal_sys_result; }) +#endif + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args) + +#undef INTERNAL_SYSCALL_ARM +#define INTERNAL_SYSCALL_ARM(name, err, nr, args...) \ + INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args) + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) >= 0xfffff001u) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +#if defined(__ARM_EABI__) +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + INTERNAL_SYSCALL_RAW(number, err, nr, args) +#else +/* We can't implement non-constant syscalls directly since the syscall + number is normally encoded in the instruction. So use SYS_syscall. */ +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + INTERNAL_SYSCALL_NCS_##nr (number, err, args) + +#define INTERNAL_SYSCALL_NCS_0(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 1, number, args) +#define INTERNAL_SYSCALL_NCS_1(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 2, number, args) +#define INTERNAL_SYSCALL_NCS_2(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 3, number, args) +#define INTERNAL_SYSCALL_NCS_3(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 4, number, args) +#define INTERNAL_SYSCALL_NCS_4(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 5, number, args) +#define INTERNAL_SYSCALL_NCS_5(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 6, number, args) +#endif + +#endif /* __ASSEMBLER__ */ + +/* Pointer mangling is not yet supported for ARM. */ +#define PTR_MANGLE(var) (void) (var) +#define PTR_DEMANGLE(var) (void) (var) + +#endif /* linux/arm/sysdep.h */ diff --git a/libc/sysdeps/linux/arm/ucontext_i.sym b/libc/sysdeps/linux/arm/ucontext_i.sym new file mode 100644 index 000000000..965032260 --- /dev/null +++ b/libc/sysdeps/linux/arm/ucontext_i.sym @@ -0,0 +1,30 @@ +#include <inttypes.h> +#include <signal.h> +#include <stddef.h> +#include <sys/ucontext.h> + +SIG_BLOCK +SIG_SETMASK + +-- Offsets of the fields in the ucontext_t structure. +#define ucontext(member) offsetof (ucontext_t, member) +#define mcontext(member) ucontext (uc_mcontext.member) + +UCONTEXT_FLAGS ucontext (uc_flags) +UCONTEXT_LINK ucontext (uc_link) +UCONTEXT_STACK ucontext (uc_stack) +UCONTEXT_MCONTEXT ucontext (uc_mcontext) +UCONTEXT_SIGMASK ucontext (uc_sigmask) + +UCONTEXT_REGSPACE ucontext (uc_regspace) + +MCONTEXT_TRAP_NO mcontext (trap_no) +MCONTEXT_ERROR_CODE mcontext (error_code) +MCONTEXT_OLDMASK mcontext (oldmask) +MCONTEXT_ARM_R0 mcontext (arm_r0) +MCONTEXT_ARM_R4 mcontext (arm_r4) +MCONTEXT_ARM_SP mcontext (arm_sp) +MCONTEXT_ARM_LR mcontext (arm_lr) +MCONTEXT_ARM_PC mcontext (arm_pc) +MCONTEXT_ARM_CPSR mcontext (arm_cpsr) +MCONTEXT_FAULT_ADDRESS mcontext (fault_address) diff --git a/libc/sysdeps/linux/arm/unwind.h b/libc/sysdeps/linux/arm/unwind.h new file mode 100644 index 000000000..601aa8f59 --- /dev/null +++ b/libc/sysdeps/linux/arm/unwind.h @@ -0,0 +1,278 @@ +/* Header file for the ARM EABI unwinder + Copyright (C) 2003, 2004, 2005, 2009 Free Software Foundation, Inc. + Contributed by Paul Brook + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + In addition to the permissions in the GNU General Public License, the + Free Software Foundation gives you unlimited permission to link the + compiled version of this file into combinations with other programs, + and to distribute those combinations without any restriction coming + from the use of this file. (The General Public License restrictions + do apply in other respects; for example, they cover modification of + the file, and distribution when not linked into a combine + executable.) + + This file 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, see + <http://www.gnu.org/licenses/>. */ + +/* Language-independent unwinder header public defines. This contains both + ABI defined objects, and GNU support routines. */ + +#ifndef UNWIND_ARM_H +#define UNWIND_ARM_H + +#define __ARM_EABI_UNWINDER__ 1 + +#ifdef __cplusplus +extern "C" { +#endif + typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); + typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); + typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); + typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__))); + typedef _Unwind_Word _uw; + typedef unsigned _uw64 __attribute__((mode(__DI__))); + typedef unsigned _uw16 __attribute__((mode(__HI__))); + typedef unsigned _uw8 __attribute__((mode(__QI__))); + + typedef enum + { + _URC_OK = 0, /* operation completed successfully */ + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8, + _URC_FAILURE = 9 /* unspecified failure of some kind */ + } + _Unwind_Reason_Code; + + typedef enum + { + _US_VIRTUAL_UNWIND_FRAME = 0, + _US_UNWIND_FRAME_STARTING = 1, + _US_UNWIND_FRAME_RESUME = 2, + _US_ACTION_MASK = 3, + _US_FORCE_UNWIND = 8, + _US_END_OF_STACK = 16 + } + _Unwind_State; + + /* Provided only for for compatibility with existing code. */ + typedef int _Unwind_Action; +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 +#define _UA_END_OF_STACK 16 +#define _URC_NO_REASON _URC_OK + + typedef struct _Unwind_Control_Block _Unwind_Control_Block; + typedef struct _Unwind_Context _Unwind_Context; + typedef _uw _Unwind_EHT_Header; + + + /* UCB: */ + + struct _Unwind_Control_Block + { +#ifdef _LIBC + /* For the benefit of code which assumes this is a scalar. All + glibc ever does is clear it. */ + _uw64 exception_class; +#else + char exception_class[8]; +#endif + void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *); + /* Unwinder cache, private fields for the unwinder's use */ + struct + { + _uw reserved1; /* Forced unwind stop fn, 0 if not forced */ + _uw reserved2; /* Personality routine address */ + _uw reserved3; /* Saved callsite address */ + _uw reserved4; /* Forced unwind stop arg */ + _uw reserved5; + } + unwinder_cache; + /* Propagation barrier cache (valid after phase 1): */ + struct + { + _uw sp; + _uw bitpattern[5]; + } + barrier_cache; + /* Cleanup cache (preserved over cleanup): */ + struct + { + _uw bitpattern[4]; + } + cleanup_cache; + /* Pr cache (for pr's benefit): */ + struct + { + _uw fnstart; /* function start address */ + _Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */ + _uw additional; /* additional data */ + _uw reserved1; + } + pr_cache; + long long int :0; /* Force alignment to 8-byte boundary */ + }; + + /* Virtual Register Set*/ + + typedef enum + { + _UVRSC_CORE = 0, /* integer register */ + _UVRSC_VFP = 1, /* vfp */ + _UVRSC_FPA = 2, /* fpa */ + _UVRSC_WMMXD = 3, /* Intel WMMX data register */ + _UVRSC_WMMXC = 4 /* Intel WMMX control register */ + } + _Unwind_VRS_RegClass; + + typedef enum + { + _UVRSD_UINT32 = 0, + _UVRSD_VFPX = 1, + _UVRSD_FPAX = 2, + _UVRSD_UINT64 = 3, + _UVRSD_FLOAT = 4, + _UVRSD_DOUBLE = 5 + } + _Unwind_VRS_DataRepresentation; + + typedef enum + { + _UVRSR_OK = 0, + _UVRSR_NOT_IMPLEMENTED = 1, + _UVRSR_FAILED = 2 + } + _Unwind_VRS_Result; + + /* Frame unwinding state. */ + typedef struct + { + /* The current word (bytes packed msb first). */ + _uw data; + /* Pointer to the next word of data. */ + _uw *next; + /* The number of bytes left in this word. */ + _uw8 bytes_left; + /* The number of words pointed to by ptr. */ + _uw8 words_left; + } + __gnu_unwind_state; + + typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State, + _Unwind_Control_Block *, _Unwind_Context *); + + _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass, + _uw, _Unwind_VRS_DataRepresentation, + void *); + + _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass, + _uw, _Unwind_VRS_DataRepresentation, + void *); + + _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass, + _uw, _Unwind_VRS_DataRepresentation); + + + /* Support functions for the PR. */ +#define _Unwind_Exception _Unwind_Control_Block + typedef char _Unwind_Exception_Class[8]; + + void * _Unwind_GetLanguageSpecificData (_Unwind_Context *); + _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *); + + /* These two should never be used. */ + _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *); + _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *); + + /* Interface functions: */ + _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp); + void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp); + _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp); + + typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + _Unwind_Control_Block *, struct _Unwind_Context *, void *); + _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *, + _Unwind_Stop_Fn, void *); + _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *); + void _Unwind_Complete(_Unwind_Control_Block *ucbp); + void _Unwind_DeleteException (_Unwind_Exception *); + + _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *, + _Unwind_Context *); + _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *, + __gnu_unwind_state *); + + /* Decode an R_ARM_TARGET2 relocation. */ + static inline _Unwind_Word + _Unwind_decode_target2 (_Unwind_Word ptr) + { + _Unwind_Word tmp; + + tmp = *(_Unwind_Word *) ptr; + /* Zero values are always NULL. */ + if (!tmp) + return 0; + +#if defined(linux) || defined(__NetBSD__) + /* Pc-relative indirect. */ + tmp += ptr; + tmp = *(_Unwind_Word *) tmp; +#elif defined(__symbian__) + /* Absolute pointer. Nothing more to do. */ +#else + /* Pc-relative pointer. */ + tmp += ptr; +#endif + return tmp; + } + + static inline _Unwind_Word + _Unwind_GetGR (_Unwind_Context *context, int regno) + { + _uw val; + _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); + return val; + } + + /* Return the address of the instruction, not the actual IP value. */ +#define _Unwind_GetIP(context) \ + (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1) + + static inline void + _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val) + { + _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); + } + + /* The dwarf unwinder doesn't understand arm/thumb state. We assume the + landing pad uses the same instruction set as the call site. */ +#define _Unwind_SetIP(context, val) \ + _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1)) + +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) + (struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* defined UNWIND_ARM_H */ diff --git a/libc/sysdeps/linux/arm/vfork.S b/libc/sysdeps/linux/arm/vfork.S index 42595b026..221a90c40 100644 --- a/libc/sysdeps/linux/arm/vfork.S +++ b/libc/sysdeps/linux/arm/vfork.S @@ -7,11 +7,21 @@ #include <features.h> #include <bits/arm_asm.h> +#include <bits/arm_bx.h> #define _ERRNO_H #include <bits/errno.h> #include <sys/syscall.h> +#ifndef SAVE_PID +#define SAVE_PID +#endif + +#ifndef RESTORE_PID +#define RESTORE_PID +#endif + + #ifdef __NR_fork .text .global __vfork @@ -23,7 +33,9 @@ .thumb_func __vfork: #ifdef __NR_vfork + SAVE_PID DO_CALL (vfork) + RESTORE_PID ldr r1, =0xfffff000 cmp r0, r1 bcs 1f @@ -57,14 +69,12 @@ __error: __vfork: #ifdef __NR_vfork + SAVE_PID DO_CALL (vfork) + RESTORE_PID cmn r0, #4096 IT(t, cc) -#if defined(__USE_BX__) - bxcc lr -#else - movcc pc, lr -#endif + BXC(cc, lr) /* Check if vfork even exists. */ ldr r1, =-ENOSYS @@ -78,11 +88,7 @@ __vfork: /* Syscall worked. Return to child/parent */ IT(t, cc) -#if defined(__USE_BX__) - bxcc lr -#else - movcc pc, lr -#endif + BXC(cc, lr) __error: b __syscall_error @@ -91,5 +97,5 @@ __error: .size __vfork,.-__vfork weak_alias(__vfork,vfork) -libc_hidden_weak(vfork) +libc_hidden_def(vfork) #endif |
