diff options
Diffstat (limited to 'libc/sysdeps/linux/i386')
54 files changed, 1487 insertions, 811 deletions
diff --git a/libc/sysdeps/linux/i386/Makefile.arch b/libc/sysdeps/linux/i386/Makefile.arch index bff33a8f2..1c72d23fd 100644 --- a/libc/sysdeps/linux/i386/Makefile.arch +++ b/libc/sysdeps/linux/i386/Makefile.arch @@ -5,15 +5,14 @@ # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. # -CSRC := brk.c sigaction.c __syscall_error.c +CSRC-y := brk.c __syscall_error.c sigaction.c -SSRC := \ - __longjmp.S vfork.S clone.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \ - sync_file_range.S syscall.S mmap.S mmap64.S +SSRC-y := \ + __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \ + sync_file_range.S syscall.S mmap.S \ + copysign.S -ifeq ($(UCLIBC_HAS_ADVANCED_REALTIME),y) -SSRC += posix_fadvise64.S -CSRC += posix_fadvise.c -endif - -include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch +SSRC-$(UCLIBC_HAS_LFS) += mmap64.S +SSRC-$(if $(findstring yy,$(UCLIBC_HAS_ADVANCED_REALTIME)$(UCLIBC_HAS_LFS)),y) += posix_fadvise64.S +SSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += vfork.S clone.S +SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.S setcontext.S getcontext.S swapcontext.S diff --git a/libc/sysdeps/linux/i386/__longjmp.S b/libc/sysdeps/linux/i386/__longjmp.S index e2809c06c..dd71b7c08 100644 --- a/libc/sysdeps/linux/i386/__longjmp.S +++ b/libc/sysdeps/linux/i386/__longjmp.S @@ -14,13 +14,9 @@ You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + see <http://www.gnu.org/licenses/>. */ -#include <features.h> -#define _ASM -#define _SETJMP_H -#include <bits/setjmp.h> +#include <jmpbuf-offsets.h> .global __longjmp .type __longjmp,%function diff --git a/libc/sysdeps/linux/i386/__syscall_error.c b/libc/sysdeps/linux/i386/__syscall_error.c index 7509d4409..36946bc6d 100644 --- a/libc/sysdeps/linux/i386/__syscall_error.c +++ b/libc/sysdeps/linux/i386/__syscall_error.c @@ -28,9 +28,8 @@ int __syscall_error(void) attribute_hidden; int __syscall_error(void) { - register int edx __asm__ ("%edx"); - __asm__ ("mov %eax, %edx\n\t" - "negl %edx"); - __set_errno (edx); + register int eax __asm__ ("%eax"); + int _errno = -eax; + __set_errno (_errno); return -1; } diff --git a/libc/sysdeps/linux/i386/bits/atomic.h b/libc/sysdeps/linux/i386/bits/atomic.h index a20f424f8..66849acbc 100644 --- a/libc/sysdeps/linux/i386/bits/atomic.h +++ b/libc/sysdeps/linux/i386/bits/atomic.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 <stdint.h> @@ -60,21 +59,21 @@ typedef uintmax_t uatomic_max_t; #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ - __asm__ __volatile__ (LOCK_PREFIX "cmpxchgb %b2, %1" \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgb %b2, %1" \ : "=a" (ret), "=m" (*mem) \ : "q" (newval), "m" (*mem), "0" (oldval)); \ ret; }) #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ - __asm__ __volatile__ (LOCK_PREFIX "cmpxchgw %w2, %1" \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgw %w2, %1" \ : "=a" (ret), "=m" (*mem) \ : "r" (newval), "m" (*mem), "0" (oldval)); \ ret; }) #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ - __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %1" \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %1" \ : "=a" (ret), "=m" (*mem) \ : "r" (newval), "m" (*mem), "0" (oldval)); \ ret; }) @@ -92,7 +91,7 @@ typedef uintmax_t uatomic_max_t; # ifdef __PIC__ # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ - __asm__ __volatile__ ("xchgl %2, %%ebx\n\t" \ + __asm__ __volatile__ ("xchgl %2, %%ebx\n\t" \ LOCK_PREFIX "cmpxchg8b %1\n\t" \ "xchgl %2, %%ebx" \ : "=A" (ret), "=m" (*mem) \ @@ -131,7 +130,7 @@ typedef uintmax_t uatomic_max_t; : "=r" (result), "=m" (*mem) \ : "0" (newvalue), "m" (*mem)); \ else if (sizeof (*mem) == 4) \ - __asm__ __volatile__ ("xchgl %0, %1" \ + __asm__ __volatile__ ("xchgl %0, %1" \ : "=r" (result), "=m" (*mem) \ : "0" (newvalue), "m" (*mem)); \ else \ @@ -146,11 +145,11 @@ typedef uintmax_t uatomic_max_t; ({ __typeof (*mem) __result; \ __typeof (value) __addval = (value); \ if (sizeof (*mem) == 1) \ - __asm__ __volatile__ (LOCK_PREFIX "xaddb %b0, %1" \ + __asm__ __volatile__ (LOCK_PREFIX "xaddb %b0, %1" \ : "=r" (__result), "=m" (*mem) \ : "0" (__addval), "m" (*mem)); \ else if (sizeof (*mem) == 2) \ - __asm__ __volatile__ (LOCK_PREFIX "xaddw %w0, %1" \ + __asm__ __volatile__ (LOCK_PREFIX "xaddw %w0, %1" \ : "=r" (__result), "=m" (*mem) \ : "0" (__addval), "m" (*mem)); \ else if (sizeof (*mem) == 4) \ @@ -204,11 +203,11 @@ typedef uintmax_t uatomic_max_t; #define atomic_add_negative(mem, value) \ ({ unsigned char __result; \ if (sizeof (*mem) == 1) \ - __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; sets %1" \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; sets %1" \ : "=m" (*mem), "=qm" (__result) \ : "iq" (value), "m" (*mem)); \ else if (sizeof (*mem) == 2) \ - __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; sets %1" \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; sets %1" \ : "=m" (*mem), "=qm" (__result) \ : "ir" (value), "m" (*mem)); \ else if (sizeof (*mem) == 4) \ @@ -223,11 +222,11 @@ typedef uintmax_t uatomic_max_t; #define atomic_add_zero(mem, value) \ ({ unsigned char __result; \ if (sizeof (*mem) == 1) \ - __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; setz %1" \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; setz %1" \ : "=m" (*mem), "=qm" (__result) \ : "ir" (value), "m" (*mem)); \ else if (sizeof (*mem) == 2) \ - __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; setz %1" \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; setz %1" \ : "=m" (*mem), "=qm" (__result) \ : "ir" (value), "m" (*mem)); \ else if (sizeof (*mem) == 4) \ @@ -241,15 +240,15 @@ typedef uintmax_t uatomic_max_t; #define atomic_increment(mem) \ (void) ({ if (sizeof (*mem) == 1) \ - __asm__ __volatile__ (LOCK_PREFIX "incb %b0" \ + __asm__ __volatile__ (LOCK_PREFIX "incb %b0" \ : "=m" (*mem) \ : "m" (*mem)); \ else if (sizeof (*mem) == 2) \ - __asm__ __volatile__ (LOCK_PREFIX "incw %w0" \ + __asm__ __volatile__ (LOCK_PREFIX "incw %w0" \ : "=m" (*mem) \ : "m" (*mem)); \ else if (sizeof (*mem) == 4) \ - __asm__ __volatile__ (LOCK_PREFIX "incl %0" \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0" \ : "=m" (*mem) \ : "m" (*mem)); \ else \ @@ -276,7 +275,7 @@ typedef uintmax_t uatomic_max_t; : "=m" (*mem), "=qm" (__result) \ : "m" (*mem)); \ else if (sizeof (*mem) == 4) \ - __asm__ __volatile__ (LOCK_PREFIX "incl %0; sete %1" \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0; sete %1" \ : "=m" (*mem), "=qm" (__result) \ : "m" (*mem)); \ else \ @@ -286,15 +285,15 @@ typedef uintmax_t uatomic_max_t; #define atomic_decrement(mem) \ (void) ({ if (sizeof (*mem) == 1) \ - __asm__ __volatile__ (LOCK_PREFIX "decb %b0" \ + __asm__ __volatile__ (LOCK_PREFIX "decb %b0" \ : "=m" (*mem) \ : "m" (*mem)); \ else if (sizeof (*mem) == 2) \ - __asm__ __volatile__ (LOCK_PREFIX "decw %w0" \ + __asm__ __volatile__ (LOCK_PREFIX "decw %w0" \ : "=m" (*mem) \ : "m" (*mem)); \ else if (sizeof (*mem) == 4) \ - __asm__ __volatile__ (LOCK_PREFIX "decl %0" \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0" \ : "=m" (*mem) \ : "m" (*mem)); \ else \ @@ -305,7 +304,7 @@ typedef uintmax_t uatomic_max_t; do \ __tmpval = __oldval; \ while ((__oldval = __arch_compare_and_exchange_val_64_acq \ - (__memp, __oldval - 1, __oldval)) == __tmpval); \ + (__memp, __oldval - 1, __oldval)) == __tmpval); \ } \ }) @@ -321,7 +320,7 @@ typedef uintmax_t uatomic_max_t; : "=m" (*mem), "=qm" (__result) \ : "m" (*mem)); \ else if (sizeof (*mem) == 4) \ - __asm__ __volatile__ (LOCK_PREFIX "decl %0; sete %1" \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0; sete %1" \ : "=m" (*mem), "=qm" (__result) \ : "m" (*mem)); \ else \ @@ -361,7 +360,7 @@ typedef uintmax_t uatomic_max_t; __asm__ __volatile__ (LOCK_PREFIX "btsl %3, %1; setc %0" \ : "=q" (__result), "=m" (*mem) \ : "m" (*mem), "ir" (bit)); \ - else \ + else \ abort (); \ __result; }) diff --git a/libc/sysdeps/linux/i386/bits/byteswap.h b/libc/sysdeps/linux/i386/bits/byteswap.h index 33af20888..651852e57 100644 --- a/libc/sysdeps/linux/i386/bits/byteswap.h +++ b/libc/sysdeps/linux/i386/bits/byteswap.h @@ -13,121 +13,43 @@ 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 _BYTESWAP_H && !defined _NETINET_IN_H -# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead." -#endif - -#ifndef _BITS_BYTESWAP_H -#define _BITS_BYTESWAP_H 1 +#ifndef _ASM_BITS_BYTESWAP_H +#define _ASM_BITS_BYTESWAP_H 1 -/* Swap bytes in 16 bit value. */ -#define __bswap_constant_16(x) \ - ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) - -#ifdef __GNUC__ -# if __GNUC__ >= 2 -# define __bswap_16(x) \ +#define __bswap_non_constant_16(x) \ (__extension__ \ - ({ register unsigned short int __v, __x = (x); \ - if (__builtin_constant_p (__x)) \ - __v = __bswap_constant_16 (__x); \ - else \ - __asm__ ("rorw $8, %w0" \ - : "=r" (__v) \ - : "0" (__x) \ - : "cc"); \ + ({ register unsigned short int __v; \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (x) \ + : "cc"); \ __v; })) -# else -/* This is better than nothing. */ -# define __bswap_16(x) \ - (__extension__ \ - ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); })) -# endif -#else -static __inline unsigned short int -__bswap_16 (unsigned short int __bsx) -{ - return __bswap_constant_16 (__bsx); -} -#endif - -/* Swap bytes in 32 bit value. */ -#define __bswap_constant_32(x) \ - ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) -#ifdef __GNUC__ -# if __GNUC__ >= 2 /* To swap the bytes in a word the i486 processors and up provide the `bswap' opcode. On i386 we have to use three instructions. */ -# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ +#if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ && !defined __pentium4__ -# define __bswap_32(x) \ +# define __bswap_non_constant_32(x) \ (__extension__ \ - ({ register unsigned int __v, __x = (x); \ - if (__builtin_constant_p (__x)) \ - __v = __bswap_constant_32 (__x); \ - else \ - __asm__ ("rorw $8, %w0;" \ - "rorl $16, %0;" \ - "rorw $8, %w0" \ - : "=r" (__v) \ - : "0" (__x) \ - : "cc"); \ + ({ register unsigned int __v; \ + __asm__ ("rorw $8, %w0;" \ + "rorl $16, %0;" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (x) \ + : "cc"); \ __v; })) -# else -# define __bswap_32(x) \ +#else +# define __bswap_non_constant_32(x) \ (__extension__ \ - ({ register unsigned int __v, __x = (x); \ - if (__builtin_constant_p (__x)) \ - __v = __bswap_constant_32 (__x); \ - else \ - __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \ + ({ register unsigned int __v; \ + __asm__ ("bswap %0" : "=r" (__v) : "0" (x)); \ __v; })) -# endif -# else -# define __bswap_32(x) \ - (__extension__ \ - ({ register unsigned int __x = (x); __bswap_constant_32 (__x); })) -# endif -#else -static __inline unsigned int -__bswap_32 (unsigned int __bsx) -{ - return __bswap_constant_32 (__bsx); -} #endif - -#if defined __GNUC__ && __GNUC__ >= 2 -/* Swap bytes in 64 bit value. */ -#define __bswap_constant_64(x) \ - ((((x) & 0xff00000000000000ull) >> 56) \ - | (((x) & 0x00ff000000000000ull) >> 40) \ - | (((x) & 0x0000ff0000000000ull) >> 24) \ - | (((x) & 0x000000ff00000000ull) >> 8) \ - | (((x) & 0x00000000ff000000ull) << 8) \ - | (((x) & 0x0000000000ff0000ull) << 24) \ - | (((x) & 0x000000000000ff00ull) << 40) \ - | (((x) & 0x00000000000000ffull) << 56)) - -# define __bswap_64(x) \ - (__extension__ \ - ({ union { __extension__ unsigned long long int __ll; \ - unsigned long int __l[2]; } __w, __r; \ - if (__builtin_constant_p (x)) \ - __r.__ll = __bswap_constant_64 (x); \ - else \ - { \ - __w.__ll = (x); \ - __r.__l[0] = __bswap_32 (__w.__l[1]); \ - __r.__l[1] = __bswap_32 (__w.__l[0]); \ - } \ - __r.__ll; })) #endif -#endif /* _BITS_BYTESWAP_H */ +#include <bits/byteswap-common.h> diff --git a/libc/sysdeps/linux/i386/bits/fcntl.h b/libc/sysdeps/linux/i386/bits/fcntl.h index 0b53b459b..4dfeae831 100644 --- a/libc/sysdeps/linux/i386/bits/fcntl.h +++ b/libc/sysdeps/linux/i386/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_DIRECTORY 0200000 /* Must be a directory. */ # define O_NOFOLLOW 0400000 /* Do not follow links. */ # 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/i386/bits/fenv.h b/libc/sysdeps/linux/i386/bits/fenv.h index ef3fcb384..9bd976fc1 100644 --- a/libc/sysdeps/linux/i386/bits/fenv.h +++ b/libc/sysdeps/linux/i386/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." @@ -82,9 +81,9 @@ typedef struct fenv_t; /* If the default argument is used we use this value. */ -#define FE_DFL_ENV ((__const fenv_t *) -1) +#define FE_DFL_ENV ((const fenv_t *) -1) #ifdef __USE_GNU /* Floating-point environment where none of the exception is masked. */ -# define FE_NOMASK_ENV ((__const fenv_t *) -2) +# define FE_NOMASK_ENV ((const fenv_t *) -2) #endif diff --git a/libc/sysdeps/linux/i386/bits/huge_vall.h b/libc/sysdeps/linux/i386/bits/huge_vall.h new file mode 100644 index 000000000..7e9c24d8a --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/huge_vall.h @@ -0,0 +1,42 @@ +/* `HUGE_VALL' constant for ix86 (where it is infinity). + Used by <stdlib.h> and <math.h> functions for overflow. + Copyright (C) 1992, 1995, 1996, 1997, 1999, 2000, 2004 + 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 _MATH_H +# error "Never use <bits/huge_vall.h> directly; include <math.h> instead." +#endif + +#if __GNUC_PREREQ(3,3) +# define HUGE_VALL (__builtin_huge_vall()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VALL (__extension__ 0x1.0p32767L) +#else + +# define __HUGE_VALL_bytes { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x7f, 0, 0 } + +# define __huge_vall_t union { unsigned char __c[12]; long double __ld; } +# ifdef __GNUC__ +# define HUGE_VALL (__extension__ \ + ((__huge_vall_t) { __c: __HUGE_VALL_bytes }).__ld) +# else /* Not GCC. */ +static __huge_vall_t __huge_vall = { __HUGE_VALL_bytes }; +# define HUGE_VALL (__huge_vall.__ld) +# endif /* GCC. */ + +#endif /* GCC 2.95 */ diff --git a/libc/sysdeps/linux/i386/bits/kernel_stat.h b/libc/sysdeps/linux/i386/bits/kernel_stat.h index 20eb6d2ef..231a984b4 100644 --- a/libc/sysdeps/linux/i386/bits/kernel_stat.h +++ b/libc/sysdeps/linux/i386/bits/kernel_stat.h @@ -1,17 +1,12 @@ #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 stat should look like... It turns out each arch has a * different opinion on the subject... */ struct kernel_stat { - unsigned short st_dev; - unsigned short __pad1; + unsigned long st_dev; unsigned long st_ino; unsigned short st_mode; unsigned short st_nlink; @@ -22,19 +17,16 @@ struct kernel_stat { unsigned long st_size; unsigned long st_blksize; unsigned long st_blocks; - unsigned long st_atime; - unsigned long __unused1; - unsigned long st_mtime; - unsigned long __unused2; - unsigned long st_ctime; - unsigned long __unused3; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; unsigned long __unused4; unsigned long __unused5; }; struct kernel_stat64 { - unsigned short st_dev; - unsigned char __pad0[10]; + unsigned long long st_dev; + unsigned char __pad0[4]; #define _HAVE_STAT64___ST_INO unsigned long __st_ino; unsigned int st_mode; @@ -47,12 +39,9 @@ struct kernel_stat64 { unsigned long st_blksize; unsigned long st_blocks; /* Number 512-byte blocks allocated. */ unsigned long __pad4; /* future possible st_blocks high bits */ - unsigned long st_atime; - unsigned long __pad5; - unsigned long st_mtime; - unsigned long __pad6; - unsigned long st_ctime; - unsigned long __pad7; /* will be high 32 bits of ctime someday */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; unsigned long long st_ino; }; diff --git a/libc/sysdeps/linux/i386/bits/kernel_types.h b/libc/sysdeps/linux/i386/bits/kernel_types.h index 6609dd312..59044b8e6 100644 --- a/libc/sysdeps/linux/i386/bits/kernel_types.h +++ b/libc/sysdeps/linux/i386/bits/kernel_types.h @@ -7,9 +7,14 @@ /* a hack for compiling a 32 bit user space with 64 bit * kernel on x86_64 */ -#if !defined(__ARCH_I386_POSIX_TYPES_H) && !defined(_ASM_X86_64_POSIX_TYPES_H) +#if !defined(__ARCH_I386_POSIX_TYPES_H) && \ + !defined(_ASM_X86_64_POSIX_TYPES_H) && \ + !defined(_ASM_X86_POSIX_TYPES_32_H) && \ + !defined(_ASM_X86_POSIX_TYPES_64_H) #define _ASM_X86_64_POSIX_TYPES_H #define __ARCH_I386_POSIX_TYPES_H +#define _ASM_X86_POSIX_TYPES_32_H +#define _ASM_X86_POSIX_TYPES_64_H typedef unsigned short __kernel_dev_t; typedef unsigned long __kernel_ino_t; @@ -35,6 +40,8 @@ typedef unsigned int __kernel_gid32_t; typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; typedef __kernel_dev_t __kernel_old_dev_t; +typedef long __kernel_long_t; +typedef unsigned long __kernel_ulong_t; typedef long long __kernel_loff_t; typedef struct { @@ -45,4 +52,4 @@ typedef struct { #endif } __kernel_fsid_t; -#endif /* __ARCH_I386_POSIX_TYPES_H */ +#endif diff --git a/libc/sysdeps/linux/i386/bits/mathdef.h b/libc/sysdeps/linux/i386/bits/mathdef.h index a3786fc81..ca4d5e5eb 100644 --- a/libc/sysdeps/linux/i386/bits/mathdef.h +++ b/libc/sysdeps/linux/i386/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/i386/bits/mathinline.h b/libc/sysdeps/linux/i386/bits/mathinline.h index ca7277d76..b3a50a538 100644 --- a/libc/sysdeps/linux/i386/bits/mathinline.h +++ b/libc/sysdeps/linux/i386/bits/mathinline.h @@ -15,9 +15,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/mathinline.h> directly; include <math.h> instead." @@ -26,7 +25,7 @@ #ifdef __cplusplus # define __MATH_INLINE __inline #else -# define __MATH_INLINE extern __inline +# define __MATH_INLINE __extern_inline #endif @@ -206,7 +205,7 @@ __NTH (__signbitl (long double __x)) __MATH_INLINE float_type __NTH (func (float_type __x)) \ { \ register float_type __result; \ - __asm__ __volatile__ (op : "=t" (__result) : params); \ + __asm__ __volatile__ (op : "=t" (__result) : params); \ return __result; \ } @@ -529,8 +528,8 @@ __inline_mathcodeNP (tanh, __x, \ __inline_mathcodeNP (floor, __x, \ register long double __value; \ - __volatile unsigned short int __cw; \ - __volatile unsigned short int __cwtmp; \ + __volatile__ unsigned short int __cw; \ + __volatile__ unsigned short int __cwtmp; \ __asm__ __volatile__ ("fnstcw %0" : "=m" (__cw)); \ __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \ __asm__ __volatile__ ("fldcw %0" : : "m" (__cwtmp)); \ @@ -540,8 +539,8 @@ __inline_mathcodeNP (floor, __x, \ __inline_mathcodeNP (ceil, __x, \ register long double __value; \ - __volatile unsigned short int __cw; \ - __volatile unsigned short int __cwtmp; \ + __volatile__ unsigned short int __cw; \ + __volatile__ unsigned short int __cwtmp; \ __asm__ __volatile__ ("fnstcw %0" : "=m" (__cw)); \ __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \ __asm__ __volatile__ ("fldcw %0" : : "m" (__cwtmp)); \ @@ -713,11 +712,22 @@ __inline_mathcodeNP2 (drem, __x, __y, \ __MATH_INLINE int __NTH (__finite (double __x)) { - return (__extension__ - (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1] - | 0x800fffffu) + 1) >> 31)); + union { double __d; int __i[2]; } u; + u.__d = __x; + /* Finite numbers have at least one zero bit in exponent. */ + /* All other numbers will result in 0xffffffff after OR: */ + return (u.__i[1] | 0x800fffff) != 0xffffffff; } +__MATH_INLINE int +__NTH (__finitef (float __x)) +{ + union { float __d; int __i; } u; + u.__d = __x; + return (u.__i | 0x807fffff) != 0xffffffff; +} + + /* Miscellaneous functions */ # ifdef __FAST_MATH__ __inline_mathcode (__coshm1, __x, \ diff --git a/libc/sysdeps/linux/i386/bits/mman.h b/libc/sysdeps/linux/i386/bits/mman.h deleted file mode 100644 index 00cb98239..000000000 --- a/libc/sysdeps/linux/i386/bits/mman.h +++ /dev/null @@ -1,103 +0,0 @@ -/* Definitions for POSIX memory map interface. Linux/i386 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/i386/bits/select.h b/libc/sysdeps/linux/i386/bits/select.h index 972bfb685..541294f62 100644 --- a/libc/sysdeps/linux/i386/bits/select.h +++ b/libc/sysdeps/linux/i386/bits/select.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_SELECT_H # error "Never use <bits/select.h> directly; include <sys/select.h> instead." diff --git a/libc/sysdeps/linux/i386/bits/setjmp.h b/libc/sysdeps/linux/i386/bits/setjmp.h index 107fe58b3..6eb29f1c0 100644 --- a/libc/sysdeps/linux/i386/bits/setjmp.h +++ b/libc/sysdeps/linux/i386/bits/setjmp.h @@ -1,4 +1,5 @@ -/* Copyright (C) 1997, 1998, 2000, 2001, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1997,1998,2000,2001,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 @@ -12,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/>. */ /* Define the machine-dependent type `jmp_buf'. Intel 386 version. */ #ifndef _BITS_SETJMP_H @@ -24,23 +24,6 @@ # error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead." #endif -#if defined __USE_MISC || defined _ASM -# define JB_BX 0 -# define JB_SI 1 -# define JB_DI 2 -# define JB_BP 3 -# define JB_SP 4 -# define JB_PC 5 -# define JB_SIZE 24 -#endif - -#ifndef _ASM typedef int __jmp_buf[6]; -#endif - -/* Test if longjmp to JMPBUF would unwind the frame - containing a local variable at ADDRESS. */ -#define _JMPBUF_UNWINDS(jmpbuf, address) \ - ((void *) (address) < (void *) (jmpbuf)[JB_SP]) #endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/i386/bits/sigcontextinfo.h b/libc/sysdeps/linux/i386/bits/sigcontextinfo.h index b7367bac6..4cafabdcb 100644 --- a/libc/sysdeps/linux/i386/bits/sigcontextinfo.h +++ b/libc/sysdeps/linux/i386/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/>. */ #define SIGCONTEXT struct sigcontext #define SIGCONTEXT_EXTRA_ARGS diff --git a/libc/sysdeps/linux/i386/bits/stackinfo.h b/libc/sysdeps/linux/i386/bits/stackinfo.h index a9a6745aa..e1b61fae0 100644 --- a/libc/sysdeps/linux/i386/bits/stackinfo.h +++ b/libc/sysdeps/linux/i386/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/i386/bits/syscalls.h b/libc/sysdeps/linux/i386/bits/syscalls.h index 014539c2a..566b5acf5 100644 --- a/libc/sysdeps/linux/i386/bits/syscalls.h +++ b/libc/sysdeps/linux/i386/bits/syscalls.h @@ -1,211 +1,193 @@ #ifndef _BITS_SYSCALLS_H #define _BITS_SYSCALLS_H + #ifndef _SYSCALL_H # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead." #endif /* - Some of the sneaky macros in the code were taken from - glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h -*/ + * Some of the sneaky macros in the code were taken from + * glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h + */ #ifndef __ASSEMBLER__ #include <errno.h> -#define SYS_ify(syscall_name) (__NR_##syscall_name) - -#define INTERNAL_SYSCALL_DECL(err) do { } while (0) - -#define INTERNAL_SYSCALL_ERROR_P(val, err) \ - ((unsigned int) (val) >= 0xfffff001u) - -#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) - -/* We need some help from the assembler to generate optimal code. We - define some macros here which later will be used. */ - -#if defined __SUPPORT_LD_DEBUG__ && defined __DOMULTI__ -#error LD debugging and DOMULTI are incompatible +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ +(__extension__ \ + ({ \ + register unsigned int resultvar; \ + __asm__ __volatile__ ( \ + LOADARGS_##nr \ + "movl %1, %%eax\n\t" \ + "int $0x80\n\t" \ + RESTOREARGS_##nr \ + : "=a" (resultvar) \ + : "g" (name) ASMFMT_##nr(args) : "memory", "cc" \ + ); \ + (int) resultvar; \ + }) \ +) + +#if 1 /* defined __PIC__ || defined __pic__ */ + +/* This code avoids pushing/popping ebx as much as possible. + * I think the main reason was that older GCCs had problems + * with proper saving/restoring of ebx if "b" constraint was used, + * which was breaking -fPIC code really badly. + * At least gcc 4.2.x seems to not need these tricks anymore, + * but this code is still useful because it often avoids + * using stack for saving ebx. + * Keeping it unconditionally enabled for now. + */ + +/* We need some help from the assembler to generate optimal code. + * We define some macros here which later will be used. */ +/* gcc>=4.6 with LTO need the same guards as IMA (a.k.a --combine) did. + * See gcc.gnu.org/PR47577 */ +/* FIXME: drop these b* macros! */ + +__asm__ ( +#if defined __DOMULTI__ || __GNUC_PREREQ (4, 6) + /* Protect against asm macro redefinition (happens in __DOMULTI__ mode). + * Unfortunately, it ends up visible in .o files. */ + ".ifndef _BITS_SYSCALLS_ASM\n\t" + ".set _BITS_SYSCALLS_ASM,1\n\t" #endif - -#ifdef __DOMULTI__ -__asm__ (".L__X'%ebx = 1\n\t" - ".L__X'%ecx = 2\n\t" - ".L__X'%edx = 2\n\t" - ".L__X'%eax = 3\n\t" - ".L__X'%esi = 3\n\t" - ".L__X'%edi = 3\n\t" - ".L__X'%ebp = 3\n\t" - ".L__X'%esp = 3\n\t" - ".ifndef _BITS_SYSCALLS_ASM\n\t" - ".set _BITS_SYSCALLS_ASM,1\n\t" - ".macro bpushl name reg\n\t" - ".if 1 - \\name\n\t" - ".if 2 - \\name\n\t" - "pushl %ebx\n\t" - ".else\n\t" - "xchgl \\reg, %ebx\n\t" - ".endif\n\t" - ".endif\n\t" - ".endm\n\t" - ".macro bpopl name reg\n\t" - ".if 1 - \\name\n\t" - ".if 2 - \\name\n\t" - "popl %ebx\n\t" - ".else\n\t" - "xchgl \\reg, %ebx\n\t" - ".endif\n\t" - ".endif\n\t" - ".endm\n\t" - ".macro bmovl name reg\n\t" - ".if 1 - \\name\n\t" - ".if 2 - \\name\n\t" - "movl \\reg, %ebx\n\t" - ".endif\n\t" - ".endif\n\t" - ".endm\n\t" - ".endif\n\t"); -#else -__asm__ (".L__X'%ebx = 1\n\t" - ".L__X'%ecx = 2\n\t" - ".L__X'%edx = 2\n\t" - ".L__X'%eax = 3\n\t" - ".L__X'%esi = 3\n\t" - ".L__X'%edi = 3\n\t" - ".L__X'%ebp = 3\n\t" - ".L__X'%esp = 3\n\t" - ".macro bpushl name reg\n\t" - ".if 1 - \\name\n\t" - ".if 2 - \\name\n\t" - "pushl %ebx\n\t" - ".else\n\t" - "xchgl \\reg, %ebx\n\t" - ".endif\n\t" - ".endif\n\t" - ".endm\n\t" - ".macro bpopl name reg\n\t" - ".if 1 - \\name\n\t" - ".if 2 - \\name\n\t" - "popl %ebx\n\t" - ".else\n\t" - "xchgl \\reg, %ebx\n\t" - ".endif\n\t" - ".endif\n\t" - ".endm\n\t" - ".macro bmovl name reg\n\t" - ".if 1 - \\name\n\t" - ".if 2 - \\name\n\t" - "movl \\reg, %ebx\n\t" - ".endif\n\t" - ".endif\n\t" - ".endm\n\t"); + ".L__X'%ebx = 1\n\t" + ".L__X'%ecx = 2\n\t" + ".L__X'%edx = 2\n\t" + ".L__X'%eax = 3\n\t" + ".L__X'%esi = 3\n\t" + ".L__X'%edi = 3\n\t" + ".L__X'%ebp = 3\n\t" + ".L__X'%esp = 3\n\t" + + /* Loading param #1 (ebx) is done by loading it into + * another register, and then performing bpushl+bmovl, + * since we must preserve ebx */ + + ".macro bpushl name reg\n\t" + ".if 1 - \\name\n\t" /* if reg!=ebx... */ + ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ + "pushl %ebx\n\t" /* save ebx on stack */ + ".else\n\t" + "xchgl \\reg, %ebx\n\t" /* else save ebx in reg, and load reg to ebx */ + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + + ".macro bmovl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ + "movl \\reg, %ebx\n\t" /* load reg to ebx */ + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + + ".macro bpopl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ + "popl %ebx\n\t" /* restore ebx from stack */ + ".else\n\t" + "xchgl \\reg, %ebx\n\t" /* else restore ebx from reg */ + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + +#if defined __DOMULTI__ || __GNUC_PREREQ (4, 6) + ".endif\n\t" /* _BITS_SYSCALLS_ASM */ #endif - -#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)); \ -} - #define INLINE_SYSCALL(name, nr, args...) \ - ({ \ - unsigned int _resultvar = INTERNAL_SYSCALL (name, , nr, args); \ - if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_resultvar, ), 0)) \ - { \ - __set_errno (INTERNAL_SYSCALL_ERRNO (_resultvar, )); \ - _resultvar = 0xffffffff; \ - } \ - (int) _resultvar; }) - -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - ({ \ - register unsigned int resultvar; \ - __asm__ __volatile__ ( \ - LOADARGS_##nr \ - "movl %1, %%eax\n\t" \ - "int $0x80\n\t" \ - RESTOREARGS_##nr \ - : "=a" (resultvar) \ - : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc"); \ - (int) resultvar; }) +); #define LOADARGS_0 -#define LOADARGS_1 \ - "bpushl .L__X'%k2, %k2\n\t" \ - "bmovl .L__X'%k2, %k2\n\t" -#define LOADARGS_2 LOADARGS_1 -#define LOADARGS_3 LOADARGS_1 -#define LOADARGS_4 LOADARGS_1 -#define LOADARGS_5 LOADARGS_1 -#define LOADARGS_6 LOADARGS_1 "push %%ebp ; movl %7, %%ebp\n\t" +#define LOADARGS_1 "bpushl .L__X'%k2, %k2\n\t" "bmovl .L__X'%k2, %k2\n\t" +#define LOADARGS_2 LOADARGS_1 +#define LOADARGS_3 LOADARGS_1 +#define LOADARGS_4 LOADARGS_1 +#define LOADARGS_5 LOADARGS_1 +#define LOADARGS_6 LOADARGS_1 "push %%ebp\n\t" "movl %7, %%ebp\n\t" #define RESTOREARGS_0 -#define RESTOREARGS_1 \ - "bpopl .L__X'%k2, %k2\n\t" -#define RESTOREARGS_2 RESTOREARGS_1 -#define RESTOREARGS_3 RESTOREARGS_1 -#define RESTOREARGS_4 RESTOREARGS_1 -#define RESTOREARGS_5 RESTOREARGS_1 -#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1 +#define RESTOREARGS_1 "bpopl .L__X'%k2, %k2\n\t" +#define RESTOREARGS_2 RESTOREARGS_1 +#define RESTOREARGS_3 RESTOREARGS_1 +#define RESTOREARGS_4 RESTOREARGS_1 +#define RESTOREARGS_5 RESTOREARGS_1 +#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1 #define ASMFMT_0() +/* "acdSD" constraint would work too, but "SD" would use esi/edi and cause + * them to be pushed/popped by compiler, "a" would use eax and cause ebx + * to be saved/restored on stack, not in register. Narrowing choice down + * to "ecx or edx" results in smaller and faster code: */ #define ASMFMT_1(arg1) \ - , "acdSD" (arg1) + , "cd" (arg1) +/* Can use "adSD" constraint here: */ #define ASMFMT_2(arg1, arg2) \ - , "adSD" (arg1), "c" (arg2) + , "d" (arg1), "c" (arg2) +/* Can use "aSD" constraint here: */ #define ASMFMT_3(arg1, arg2, arg3) \ - , "aSD" (arg1), "c" (arg2), "d" (arg3) + , "a" (arg1), "c" (arg2), "d" (arg3) +/* Can use "aD" constraint here: */ #define ASMFMT_4(arg1, arg2, arg3, arg4) \ - , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) #define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ - , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6) + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "g" (arg6) + +#else /* !PIC */ + +/* Simpler code which just uses "b" constraint to load ebx. + * Seems to work with gc 4.2.x, and generates slightly smaller, + * but slightly slower code. Example (time syscall): + * + * - 8b 4c 24 04 mov 0x4(%esp),%ecx + * - 87 cb xchg %ecx,%ebx + * + 53 push %ebx + * + 8b 5c 24 08 mov 0x8(%esp),%ebx + * b8 0d 00 00 00 mov $0xd,%eax + * cd 80 int $0x80 + * - 87 cb xchg %ecx,%ebx + * + 5b pop %ebx + * c3 ret + * + * 2 bytes smaller, but uses stack via "push/pop ebx" + */ + +#define LOADARGS_0 +#define LOADARGS_1 +#define LOADARGS_2 +#define LOADARGS_3 +#define LOADARGS_4 +#define LOADARGS_5 +#define LOADARGS_6 "push %%ebp\n\t" "movl %7, %%ebp\n\t" + +#define RESTOREARGS_0 +#define RESTOREARGS_1 +#define RESTOREARGS_2 +#define RESTOREARGS_3 +#define RESTOREARGS_4 +#define RESTOREARGS_5 +#define RESTOREARGS_6 "pop %%ebp\n\t" + +#define ASMFMT_0() +#define ASMFMT_1(arg1) \ + , "b" (arg1) +#define ASMFMT_2(arg1, arg2) \ + , "b" (arg1), "c" (arg2) +#define ASMFMT_3(arg1, arg2, arg3) \ + , "b" (arg1), "c" (arg2), "d" (arg3) +#define ASMFMT_4(arg1, arg2, arg3, arg4) \ + , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) +#define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ + , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) +#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ + , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6) + +#endif /* !PIC */ #endif /* __ASSEMBLER__ */ #endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h b/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h index f4730d987..5b6c2fc78 100644 --- a/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h @@ -11,8 +11,8 @@ /* 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) */ +#undef __UCLIBC_SYSCALL_ALIGN_64BIT__ /* does your target have a broken create_module() ? */ #define __UCLIBC_BROKEN_CREATE_MODULE__ @@ -24,21 +24,21 @@ /* 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 */ +#define __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__ + #if defined _LIBC #define internal_function __attribute__ ((regparm (3), stdcall)) #endif diff --git a/libc/sysdeps/linux/i386/bits/wchar.h b/libc/sysdeps/linux/i386/bits/wchar.h index 442a4621e..b94fc7a3f 100644 --- a/libc/sysdeps/linux/i386/bits/wchar.h +++ b/libc/sysdeps/linux/i386/bits/wchar.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 _BITS_WCHAR_H #define _BITS_WCHAR_H 1 diff --git a/libc/sysdeps/linux/i386/bits/wordsize.h b/libc/sysdeps/linux/i386/bits/wordsize.h index 7c3cd9c7d..d8f66ddc5 100644 --- a/libc/sysdeps/linux/i386/bits/wordsize.h +++ b/libc/sysdeps/linux/i386/bits/wordsize.h @@ -12,13 +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/>. */ #define __WORDSIZE 32 -#ifdef UCLIBC_INTERNAL +#ifdef _LIBC #ifndef smallint_type #define smallint_type char #endif diff --git a/libc/sysdeps/linux/i386/brk.c b/libc/sysdeps/linux/i386/brk.c index eda8ad9ce..a513886e3 100644 --- a/libc/sysdeps/linux/i386/brk.c +++ b/libc/sysdeps/linux/i386/brk.c @@ -1,6 +1,7 @@ /* brk system call for Linux/i386. Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. - This file is part of the GNU C Library. + Copyright (c) 2015 mirabilos <tg@mirbsd.org> + This file is part of uclibc-ng, derived from 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 @@ -13,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/>. */ #include <errno.h> #include <unistd.h> @@ -24,26 +24,31 @@ /* This must be initialized data because commons can't have aliases. */ void *__curbrk attribute_hidden = 0; -libc_hidden_proto(brk) -int brk (void *addr) +int brk(void *addr) { - void *__unbounded newbrk, *__unbounded scratch; - - __asm__ ("movl %%ebx, %1\n" /* Save %ebx in scratch register. */ - "movl %3, %%ebx\n" /* Put ADDR in %ebx to be syscall arg. */ - "int $0x80 # %2\n" /* Perform the system call. */ - "movl %1, %%ebx\n" /* Restore %ebx from scratch register. */ - : "=a" (newbrk), "=r" (scratch) - : "0" (__NR_brk), "g" (__ptrvalue (addr))); - - __curbrk = newbrk; - - if (newbrk < addr) - { - __set_errno (ENOMEM); - return -1; - } - - return 0; + void *newbrk; + + /* + * EBC is used in PIC code, we need to save/restore it manually. + * Unfortunately, GCC won't do that for us even if we use con- + * straints, and we cannot push it either as ESP clobbers are + * silently ignored, but EDX is preserved, so it's scratch space. + */ + __asm__("xchgl %%edx,%%ebx" + "\n int $0x80" + "\n xchgl %%edx,%%ebx" + : "=a" (newbrk) + : "0" (__NR_brk), "d" (addr) + : "cc" + ); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno(ENOMEM); + return -1; + } + + return 0; } libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/i386/bsd-_setjmp.S b/libc/sysdeps/linux/i386/bsd-_setjmp.S index f3cd6cbf6..fac94e351 100644 --- a/libc/sysdeps/linux/i386/bsd-_setjmp.S +++ b/libc/sysdeps/linux/i386/bsd-_setjmp.S @@ -13,17 +13,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/>. */ /* This just does a tail-call to `__sigsetjmp (ARG, 0)'. We cannot do it in C because it must be a tail-call, so frame-unwinding in setjmp doesn't clobber the state restored by longjmp. */ -#define _ASM -#define _SETJMP_H -#include <bits/setjmp.h> +#include <jmpbuf-offsets.h> .global _setjmp .type _setjmp,%function diff --git a/libc/sysdeps/linux/i386/bsd-setjmp.S b/libc/sysdeps/linux/i386/bsd-setjmp.S index df46997d9..c634cf16a 100644 --- a/libc/sysdeps/linux/i386/bsd-setjmp.S +++ b/libc/sysdeps/linux/i386/bsd-setjmp.S @@ -13,13 +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. */ - -#define _ASM -#define _SETJMP_H -#include <bits/setjmp.h> + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ .global setjmp .type setjmp,%function diff --git a/libc/sysdeps/linux/i386/clone.S b/libc/sysdeps/linux/i386/clone.S index 14fc25ca1..632cf59df 100644 --- a/libc/sysdeps/linux/i386/clone.S +++ b/libc/sysdeps/linux/i386/clone.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/>. */ /* clone() is even more special than fork() as it mucks with stacks and invokes a function in the right context after its all over. @@ -79,7 +78,10 @@ clone: movl %eax,8(%ecx) /* Don't leak any information. */ movl $0,4(%ecx) +#ifndef RESET_PID movl $0,(%ecx) +#endif + /* Do the system call */ pushl %ebx @@ -90,6 +92,10 @@ clone: movl FLAGS+12(%esp),%ebx movl CTID+12(%esp),%edi movl $__NR_clone,%eax +#ifdef RESET_PID + /* Remember the flag value. */ + movl %ebx, (%ecx) +#endif int $0x80 popl %edi popl %esi @@ -121,3 +127,4 @@ __error: jmp __syscall_error .size clone,.-clone +weak_alias(clone, __clone) diff --git a/libc/sysdeps/linux/i386/copysign.S b/libc/sysdeps/linux/i386/copysign.S new file mode 100644 index 000000000..6499ce05d --- /dev/null +++ b/libc/sysdeps/linux/i386/copysign.S @@ -0,0 +1,55 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Public domain. + */ + +#define _ERRNO_H 1 +#include <features.h> +#include <bits/errno.h> + +.text +.global copysign +.type copysign,%function +copysign: + movl 16(%esp),%edx + movl 8(%esp),%eax + andl $0x80000000,%edx + andl $0x7fffffff,%eax + orl %edx,%eax + movl %eax,8(%esp) + fldl 4(%esp) + ret +.size copysign,.-copysign + +libc_hidden_def(copysign) + +.global copysignf +.type copysignf,%function +copysignf: + movl 8(%esp),%edx + movl 4(%esp),%eax + andl $0x80000000,%edx + andl $0x7fffffff,%eax + orl %edx,%eax + movl %eax,4(%esp) + flds 4(%esp) + ret +.size copysignf,.-copysignf + +libc_hidden_def(copysignf) + +.global copysignl +.type copysignl,%function +copysignl: + movl 24(%esp),%edx + movl 12(%esp),%eax + andl $0x8000,%edx + andl $0x7fff,%eax + orl %edx,%eax + movl %eax,12(%esp) + fldt 4(%esp) + ret +.size copysignl,.-copysignl + +libc_hidden_def(copysignl) + diff --git a/libc/sysdeps/linux/i386/crt1.S b/libc/sysdeps/linux/i386/crt1.S index a133cb9e0..35a6552e8 100644 --- a/libc/sysdeps/linux/i386/crt1.S +++ b/libc/sysdeps/linux/i386/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. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry diff --git a/libc/sysdeps/linux/i386/crtn.S b/libc/sysdeps/linux/i386/crtn.S index 191250487..34d5b38e2 100644 --- a/libc/sysdeps/linux/i386/crtn.S +++ b/libc/sysdeps/linux/i386/crtn.S @@ -6,7 +6,6 @@ popl %ebx popl %ebp ret -.size _init,.-_init @@ -16,7 +15,6 @@ popl %ebx popl %ebp ret -.size _fini,.-_fini diff --git a/libc/sysdeps/linux/i386/fpu_control.h b/libc/sysdeps/linux/i386/fpu_control.h index c6cb005d7..c2a672d29 100644 --- a/libc/sysdeps/linux/i386/fpu_control.h +++ b/libc/sysdeps/linux/i386/fpu_control.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 _FPU_CONTROL_H #define _FPU_CONTROL_H 1 diff --git a/libc/sysdeps/linux/i386/getcontext.S b/libc/sysdeps/linux/i386/getcontext.S new file mode 100644 index 000000000..3221b597c --- /dev/null +++ b/libc/sysdeps/linux/i386/getcontext.S @@ -0,0 +1,84 @@ +/* Save current context. + Copyright (C) 2001-2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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" + + +ENTRY(__getcontext) + /* Load address of the context data structure. */ + movl 4(%esp), %eax + + /* Return value of getcontext. EAX is the only register whose + value is not preserved. */ + movl $0, oEAX(%eax) + + /* Save the 32-bit register values and the return address. */ + movl %ecx, oECX(%eax) + movl %edx, oEDX(%eax) + movl %edi, oEDI(%eax) + movl %esi, oESI(%eax) + movl %ebp, oEBP(%eax) + movl (%esp), %ecx + movl %ecx, oEIP(%eax) + leal 4(%esp), %ecx /* Exclude the return address. */ + movl %ecx, oESP(%eax) + movl %ebx, oEBX(%eax) + + /* Save the FS segment register. We don't touch the GS register + since it is used for threads. */ + xorl %edx, %edx + movw %fs, %dx + movl %edx, oFS(%eax) + + /* We have separate floating-point register content memory on the + stack. We use the __fpregs_mem block in the context. Set the + links up correctly. */ + leal oFPREGSMEM(%eax), %ecx + movl %ecx, oFPREGS(%eax) + /* Save the floating-point context. */ + fnstenv (%ecx) + /* And load it right back since the processor changes the mask. + Intel thought this opcode to be used in interrupt handlers which + would block all exceptions. */ + fldenv (%ecx) + + /* Save the current signal mask. */ + pushl %ebx + cfi_adjust_cfa_offset (4) + cfi_rel_offset (ebx, 0) + leal oSIGMASK(%eax), %edx + xorl %ecx, %ecx + movl $SIG_BLOCK, %ebx + movl $__NR_sigprocmask, %eax + ENTER_KERNEL + popl %ebx + cfi_adjust_cfa_offset (-4) + cfi_restore (ebx) + cmpl $-4095, %eax /* Check %eax for error. */ + jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ + + /* All done, return 0 for success. */ + xorl %eax, %eax +L(pseudo_end): + ret +PSEUDO_END(__getcontext) + +weak_alias (__getcontext, getcontext) diff --git a/libc/sysdeps/linux/i386/jmpbuf-offsets.h b/libc/sysdeps/linux/i386/jmpbuf-offsets.h new file mode 100644 index 000000000..47aa49948 --- /dev/null +++ b/libc/sysdeps/linux/i386/jmpbuf-offsets.h @@ -0,0 +1,25 @@ +/* Private macros for accessing __jmp_buf contents. i386 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 JB_BX 0 +#define JB_SI 1 +#define JB_DI 2 +#define JB_BP 3 +#define JB_SP 4 +#define JB_PC 5 +#define JB_SIZE 24 diff --git a/libc/sysdeps/linux/i386/jmpbuf-unwind.h b/libc/sysdeps/linux/i386/jmpbuf-unwind.h new file mode 100644 index 000000000..4516d9398 --- /dev/null +++ b/libc/sysdeps/linux/i386/jmpbuf-unwind.h @@ -0,0 +1,23 @@ +/* + * 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)[JB_SP]) + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include <stdint.h> +#include <unwind.h> + +#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)[JB_SP] - (_adj)) +#endif diff --git a/libc/sysdeps/linux/i386/makecontext.S b/libc/sysdeps/linux/i386/makecontext.S new file mode 100644 index 000000000..d12799d80 --- /dev/null +++ b/libc/sysdeps/linux/i386/makecontext.S @@ -0,0 +1,123 @@ +/* Create new context. + Copyright (C) 2001,2002,2005,2007,2008,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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" + + +ENTRY(__makecontext) + movl 4(%esp), %eax + + /* Load the address of the function we are supposed to run. */ + movl 8(%esp), %ecx + + /* Compute the address of the stack. The information comes from + to us_stack element. */ + movl oSS_SP(%eax), %edx + movl %ecx, oEIP(%eax) + addl oSS_SIZE(%eax), %edx + + /* Remember the number of parameters for the exit handler since + it has to remove them. We store the number in the EBX register + which the function we will call must preserve. */ + movl 12(%esp), %ecx + movl %ecx, oEBX(%eax) + + /* Make room on the new stack for the parameters. + Room for the arguments, return address (== L(exitcode)) and + oLINK pointer is needed. One of the pointer sizes is subtracted + after aligning the stack. */ + negl %ecx + leal -4(%edx,%ecx,4), %edx + negl %ecx + + /* Align the stack. */ + andl $0xfffffff0, %edx + subl $4, %edx + + /* Store the future stack pointer. */ + movl %edx, oESP(%eax) + + /* Put the next context on the new stack (from the uc_link + element). */ + movl oLINK(%eax), %eax + movl %eax, 4(%edx,%ecx,4) + + /* Copy all the parameters. */ + jecxz 2f +1: movl 12(%esp,%ecx,4), %eax + movl %eax, (%edx,%ecx,4) + decl %ecx + jnz 1b +2: + + /* If the function we call returns we must continue with the + context which is given in the uc_link element. To do this + set the return address for the function the user provides + to a little bit of helper code which does the magic (see + below). */ +#ifdef __PIC__ + call 1f + cfi_adjust_cfa_offset (4) +1: popl %ecx + cfi_adjust_cfa_offset (-4) + addl $L(exitcode)-1b, %ecx + movl %ecx, (%edx) +#else + movl $L(exitcode), (%edx) +#endif + /* 'makecontext' returns no value. */ +L(pseudo_end): + ret + + /* This is the helper code which gets called if a function which + is registered with 'makecontext' returns. In this case we + have to install the context listed in the uc_link element of + the context 'makecontext' manipulated at the time of the + 'makecontext' call. If the pointer is NULL the process must + terminate. */ + cfi_endproc +L(exitcode): + /* This removes the parameters passed to the function given to + 'makecontext' from the stack. EBX contains the number of + parameters (see above). */ + leal (%esp,%ebx,4), %esp + +#ifdef __PIC__ + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx +#endif + cmpl $0, (%esp) /* Check the next context. */ + je 2f /* If it is zero exit. */ + + call JUMPTARGET(__setcontext) + /* If this returns (which can happen if the syscall fails) we'll + exit the program with the return error value (-1). */ + + movl %eax, (%esp) +2: call HIDDEN_JUMPTARGET(exit) + /* The 'exit' call should never return. In case it does cause + the process to terminate. */ + hlt + cfi_startproc +END(__makecontext) + +weak_alias (__makecontext, makecontext) diff --git a/libc/sysdeps/linux/i386/mmap.S b/libc/sysdeps/linux/i386/mmap.S index fe7a7986c..8f9b03243 100644 --- a/libc/sysdeps/linux/i386/mmap.S +++ b/libc/sysdeps/linux/i386/mmap.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/>. */ #define _ERRNO_H 1 #include <features.h> diff --git a/libc/sysdeps/linux/i386/mmap64.S b/libc/sysdeps/linux/i386/mmap64.S index a6b4aa042..2c80ceb01 100644 --- a/libc/sysdeps/linux/i386/mmap64.S +++ b/libc/sysdeps/linux/i386/mmap64.S @@ -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 <_lfs_64.h> #define _ERRNO_H 1 -#include <features.h> #include <bits/errno.h> #include <sys/syscall.h> -#if defined __UCLIBC_HAS_LFS__ && defined __NR_mmap2 - +#ifdef __NR_mmap2 #define LINKAGE 4 #define PTR_SIZE 4 diff --git a/libc/sysdeps/linux/i386/posix_fadvise.c b/libc/sysdeps/linux/i386/posix_fadvise.c deleted file mode 100644 index 5406213b8..000000000 --- a/libc/sysdeps/linux/i386/posix_fadvise.c +++ /dev/null @@ -1,34 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * posix_fadvise() for uClibc - * - * Copyright (C) 2008 Bernhard Reutner-Fischer <uclibc@uclibc.org> - * - * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - */ - -#include <sys/syscall.h> -#if defined __USE_GNU -#include <fcntl.h> - - -#if defined __NR_fadvise64_64 || defined __NR_fadvise64 -libc_hidden_proto(posix_fadvise64) -libc_hidden_proto(posix_fadvise) -int posix_fadvise(int fd, off_t offset, off_t len, int advice) -{ - if (posix_fadvise64(fd, offset, len, advice) != 0) - return errno; - return 0; -} -libc_hidden_def(posix_fadvise) -#elif defined __UCLIBC_HAS_STUBS__ -libc_hidden_proto(posix_fadvise) -int posix_fadvise(int fd attribute_unused, off_t offset attribute_unused, - off_t len attribute_unused, int advice attribute_unused) -{ - return ENOSYS; -} -libc_hidden_def(posix_fadvise) -#endif -#endif diff --git a/libc/sysdeps/linux/i386/posix_fadvise64.S b/libc/sysdeps/linux/i386/posix_fadvise64.S index da3f36394..3047b0d05 100644 --- a/libc/sysdeps/linux/i386/posix_fadvise64.S +++ b/libc/sysdeps/linux/i386/posix_fadvise64.S @@ -13,20 +13,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 _ERRNO_H 1 -#include <features.h> -#include <bits/errno.h> +#include <_lfs_64.h> #include <sys/syscall.h> +#ifdef __NR_fadvise64_64 + .text .global posix_fadvise64 .type posix_fadvise64,%function posix_fadvise64: -#if defined __NR_fadvise64_64 && defined __UCLIBC_HAS_LFS__ /* Save regs */ pushl %ebp pushl %ebx @@ -35,12 +33,12 @@ posix_fadvise64: movl $__NR_fadvise64_64, %eax /* Syscall number in %eax. */ - movl 24(%esp), %ebx - movl 28(%esp), %ecx - movl 32(%esp), %edx - movl 36(%esp), %esi - movl 40(%esp), %edi - movl 44(%esp), %ebp + movl 20(%esp), %ebx + movl 24(%esp), %ecx + movl 28(%esp), %edx + movl 32(%esp), %esi + movl 36(%esp), %edi + movl 40(%esp), %ebp /* Do the system call trap. */ int $0x80 @@ -51,48 +49,10 @@ posix_fadvise64: popl %ebx popl %ebp - /* If 0 > %eax > -4096 there was an error. */ - cmpl $-4096, %eax - ja __syscall_error -#elif defined __NR_fadvise64 - /* Save regs */ - pushl %ebx - pushl %esi - pushl %edi - - /* does len overflow long? */ - cmpl $0, 40(%esp) - movl $-EOVERFLOW, %eax - ja overflow + /* Returns 0 on success, else an error code. */ + negl %eax - movl $__NR_fadvise64, %eax /* Syscall number in %eax. */ - - movl 24(%esp), %ebx - movl 28(%esp), %ecx - movl 32(%esp), %edx - movl 36(%esp), %esi - movl 44(%esp), %edi - - /* Do the system call trap. */ - int $0x80 -overflow: - /* Restore regs */ - popl %edi - popl %esi - popl %ebx - - /* If 0 > %eax > -4096 there was an error. */ - cmpl $-4096, %eax - ja __syscall_error - -#elif defined __UCLIBC_HAS_STUBS__ - movl $-ENOSYS, %eax - jmp __syscall_error -#endif /* Successful; return the syscall's value. */ ret - .size posix_fadvise64,.-posix_fadvise64 - -libc_hidden_def(posix_fadvise64) - +#endif diff --git a/libc/sysdeps/linux/i386/setcontext.S b/libc/sysdeps/linux/i386/setcontext.S new file mode 100644 index 000000000..ae953cc6b --- /dev/null +++ b/libc/sysdeps/linux/i386/setcontext.S @@ -0,0 +1,96 @@ +/* Install given context. + Copyright (C) 2001-2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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" + + +ENTRY(__setcontext) + /* Load address of the context data structure. */ + movl 4(%esp), %eax + + /* Get the current signal mask. Note that we preserve EBX in case + the system call fails and we return from the function with an + error. */ + pushl %ebx + cfi_adjust_cfa_offset (4) + xorl %edx, %edx + leal oSIGMASK(%eax), %ecx + movl $SIG_SETMASK, %ebx + cfi_rel_offset (ebx, 0) + movl $__NR_sigprocmask, %eax + ENTER_KERNEL + popl %ebx + cfi_adjust_cfa_offset (-4) + cfi_restore (ebx) + cmpl $-4095, %eax /* Check %eax for error. */ + jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ + + /* EAX was modified, reload it. */ + movl 4(%esp), %eax + + /* Restore the floating-point context. Not the registers, only the + rest. */ + movl oFPREGS(%eax), %ecx + fldenv (%ecx) + + /* Restore the FS segment register. We don't touch the GS register + since it is used for threads. */ + movl oFS(%eax), %ecx + movw %cx, %fs + + /* Fetch the address to return to. */ + movl oEIP(%eax), %ecx + + /* Load the new stack pointer. */ + cfi_def_cfa (eax, 0) + cfi_offset (edi, oEDI) + cfi_offset (esi, oESI) + cfi_offset (ebp, oEBP) + cfi_offset (ebx, oEBX) + cfi_offset (edx, oEDX) + cfi_offset (ecx, oECX) + movl oESP(%eax), %esp + + /* Push the return address on the new stack so we can return there. */ + pushl %ecx + + /* Load the values of all the 32-bit registers (except ESP). + Since we are loading from EAX, it must be last. */ + movl oEDI(%eax), %edi + movl oESI(%eax), %esi + movl oEBP(%eax), %ebp + movl oEBX(%eax), %ebx + movl oEDX(%eax), %edx + movl oECX(%eax), %ecx + movl oEAX(%eax), %eax + + /* End FDE here, we fall into another context. */ + cfi_endproc + cfi_startproc + + /* The following 'ret' will pop the address of the code and jump + to it. */ + +L(pseudo_end): + ret +PSEUDO_END(__setcontext) + +weak_alias (__setcontext, setcontext) diff --git a/libc/sysdeps/linux/i386/setjmp.S b/libc/sysdeps/linux/i386/setjmp.S index 20a6a0bcf..505b85cf5 100644 --- a/libc/sysdeps/linux/i386/setjmp.S +++ b/libc/sysdeps/linux/i386/setjmp.S @@ -13,14 +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. */ - -#define _ASM -#define _SETJMP_H -#include <bits/setjmp.h> - + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ .global __sigsetjmp .type __sigsetjmp,%function diff --git a/libc/sysdeps/linux/i386/sigaction.c b/libc/sysdeps/linux/i386/sigaction.c index e8729647f..77da69d5e 100644 --- a/libc/sysdeps/linux/i386/sigaction.c +++ b/libc/sysdeps/linux/i386/sigaction.c @@ -13,8 +13,7 @@ You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + see <http://www.gnu.org/licenses/>. Totally hacked up for uClibc by Erik Andersen <andersen@codepoet.org> */ @@ -27,111 +26,81 @@ #define SA_RESTORER 0x04000000 -extern __typeof(sigaction) __libc_sigaction; - #if defined __NR_rt_sigaction -/* Experimentally off - libc_hidden_proto(memcpy) */ -extern void restore_rt (void) __asm__ ("__restore_rt") attribute_hidden; -extern void restore (void) __asm__ ("__restore") attribute_hidden; +extern void restore_rt(void) __asm__ ("__restore_rt") attribute_hidden; +extern void restore(void) __asm__ ("__restore") attribute_hidden; /* 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; - -#ifdef SIGCANCEL - if (sig == SIGCANCEL) { - __set_errno (EINVAL); - return -1; - } -#endif - - if (act) { - kact.k_sa_handler = act->sa_handler; - memcpy (&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask)); - kact.sa_flags = act->sa_flags; - - kact.sa_flags = act->sa_flags | SA_RESTORER; - kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) - ? &restore_rt : &restore); - } - - /* 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 (oact->sa_mask)); - oact->sa_flags = koact.sa_flags; - oact->sa_restorer = koact.sa_restorer; - } - return result; + struct sigaction kact; + + if (act) { + memcpy(&kact, act, sizeof(kact)); + kact.sa_flags |= SA_RESTORER; + kact.sa_restorer = (act->sa_flags & SA_SIGINFO) ? &restore_rt : &restore; + act = &kact; + } + /* 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 -extern void restore (void) __asm__ ("__restore") attribute_hidden; + +extern void restore(void) __asm__ ("__restore") attribute_hidden; /* 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; - -#ifdef SIGCANCEL - if (sig == SIGCANCEL) { - __set_errno (EINVAL); - return -1; - } -#endif - - if (act) { - kact.k_sa_handler = act->sa_handler; - kact.sa_mask = act->sa_mask.__val[0]; - kact.sa_flags = act->sa_flags | SA_RESTORER; - kact.sa_restorer = &restore; - } - - __asm__ __volatile__ ("pushl %%ebx\n" - "movl %2, %%ebx\n" - "int $0x80\n" - "popl %%ebx" - : "=a" (result) - : "0" (__NR_sigaction), "mr" (sig), - "c" (act ? __ptrvalue (&kact) : 0), - "d" (oact ? __ptrvalue (&koact) : 0)); - - if (result < 0) { - __set_errno(-result); - return -1; - } - - if (oact) { - 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; + 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 | SA_RESTORER; + kact.sa_restorer = &restore; + } + __asm__ __volatile__ ( + " pushl %%ebx\n" + " movl %3, %%ebx\n" + " int $0x80\n" + " popl %%ebx\n" + : "=a" (result), "=m" (koact) + : "0" (__NR_sigaction), "r" (sig), "m" (kact), + "c" (act ? &kact : NULL), + "d" (oact ? &koact : NULL)); + if (result < 0) { + __set_errno(-result); + return -1; + } + if (oact) { + 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 - - /* NOTE: Please think twice before making any changes to the bits of code below. GDB needs some intimate knowledge about it to recognize them as signal trampolines, and make backtraces through @@ -140,33 +109,30 @@ libc_hidden_weak(sigaction) If you ever feel the need to make any changes, please notify the appropriate GDB maintainer. */ -#define RESTORE(name, syscall) RESTORE2 (name, syscall) -#define RESTORE2(name, syscall) \ -__asm__ \ - ( \ - ".text\n" \ - "__" #name ":\n" \ - " movl $" #syscall ", %eax\n" \ - " int $0x80" \ - ); +#define RESTORE(name, syscall) RESTORE2(name, syscall) #ifdef __NR_rt_sigaction /* The return code for realtime-signals. */ -RESTORE (restore_rt, __NR_rt_sigreturn) +# define RESTORE2(name, syscall) \ +__asm__ ( \ + ".text\n" \ + "__" #name ":\n" \ + " movl $" #syscall ", %eax\n" \ + " int $0x80\n" \ +); +RESTORE(restore_rt, __NR_rt_sigreturn) #endif #ifdef __NR_sigreturn /* For the boring old signals. */ # undef RESTORE2 # define RESTORE2(name, syscall) \ -__asm__ \ - ( \ - ".text\n" \ - "__" #name ":\n" \ - " popl %eax\n" \ - " movl $" #syscall ", %eax\n" \ - " int $0x80" \ - ); - -RESTORE (restore, __NR_sigreturn) +__asm__ ( \ + ".text\n" \ + "__" #name ":\n" \ + " popl %eax\n" \ + " movl $" #syscall ", %eax\n" \ + " int $0x80\n" \ +); +RESTORE(restore, __NR_sigreturn) #endif diff --git a/libc/sysdeps/linux/i386/swapcontext.S b/libc/sysdeps/linux/i386/swapcontext.S new file mode 100644 index 000000000..ee5d0e4d5 --- /dev/null +++ b/libc/sysdeps/linux/i386/swapcontext.S @@ -0,0 +1,110 @@ +/* Save current context and install the given one. + Copyright (C) 2001-2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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" + + +ENTRY(__swapcontext) + /* Load address of the context data structure we save in. */ + movl 4(%esp), %eax + + /* Return value of swapcontext. EAX is the only register whose + value is not preserved. */ + movl $0, oEAX(%eax) + + /* Save the 32-bit register values and the return address. */ + movl %ecx, oECX(%eax) + movl %edx, oEDX(%eax) + movl %edi, oEDI(%eax) + movl %esi, oESI(%eax) + movl %ebp, oEBP(%eax) + movl (%esp), %ecx + movl %ecx, oEIP(%eax) + leal 4(%esp), %ecx + movl %ecx, oESP(%eax) + movl %ebx, oEBX(%eax) + + /* Save the FS segment register. */ + xorl %edx, %edx + movw %fs, %dx + movl %edx, oFS(%eax) + + /* We have separate floating-point register content memory on the + stack. We use the __fpregs_mem block in the context. Set the + links up correctly. */ + leal oFPREGSMEM(%eax), %ecx + movl %ecx, oFPREGS(%eax) + /* Save the floating-point context. */ + fnstenv (%ecx) + + /* Load address of the context data structure we have to load. */ + movl 8(%esp), %ecx + + /* Save the current signal mask and install the new one. */ + pushl %ebx + leal oSIGMASK(%eax), %edx + leal oSIGMASK(%ecx), %ecx + movl $SIG_SETMASK, %ebx + movl $__NR_sigprocmask, %eax + ENTER_KERNEL + popl %ebx + cmpl $-4095, %eax /* Check %eax for error. */ + jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ + + /* EAX was modified, reload it. */ + movl 8(%esp), %eax + + /* Restore the floating-point context. Not the registers, only the + rest. */ + movl oFPREGS(%eax), %ecx + fldenv (%ecx) + + /* Restore the FS segment register. We don't touch the GS register + since it is used for threads. */ + movl oFS(%eax), %edx + movw %dx, %fs + + /* Fetch the address to return to. */ + movl oEIP(%eax), %ecx + + /* Load the new stack pointer. */ + movl oESP(%eax), %esp + + /* Push the return address on the new stack so we can return there. */ + pushl %ecx + + /* Load the values of all the 32-bit registers (except ESP). + Since we are loading from EAX, it must be last. */ + movl oEDI(%eax), %edi + movl oESI(%eax), %esi + movl oEBP(%eax), %ebp + movl oEBX(%eax), %ebx + movl oEDX(%eax), %edx + movl oECX(%eax), %ecx + movl oEAX(%eax), %eax + + /* The following 'ret' will pop the address of the code and jump + to it. */ +L(pseudo_end): + ret +PSEUDO_END(__swapcontext) + +weak_alias (__swapcontext, swapcontext) diff --git a/libc/sysdeps/linux/i386/sync_file_range.S b/libc/sysdeps/linux/i386/sync_file_range.S index 6cdaf452a..d2cbd5170 100644 --- a/libc/sysdeps/linux/i386/sync_file_range.S +++ b/libc/sysdeps/linux/i386/sync_file_range.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/>. */ #define _ERRNO_H 1 #include <features.h> diff --git a/libc/sysdeps/linux/i386/sys/debugreg.h b/libc/sysdeps/linux/i386/sys/debugreg.h index c99c94359..ac1926b5b 100644 --- a/libc/sysdeps/linux/i386/sys/debugreg.h +++ b/libc/sysdeps/linux/i386/sys/debugreg.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_DEBUGREG_H #define _SYS_DEBUGREG_H 1 diff --git a/libc/sysdeps/linux/i386/sys/elf.h b/libc/sysdeps/linux/i386/sys/elf.h index d959cdca1..9d64e9768 100644 --- a/libc/sysdeps/linux/i386/sys/elf.h +++ b/libc/sysdeps/linux/i386/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/i386/sys/io.h b/libc/sysdeps/linux/i386/sys/io.h index 87b99a94a..fa750995c 100644 --- a/libc/sysdeps/linux/i386/sys/io.h +++ b/libc/sysdeps/linux/i386/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 #define _SYS_IO_H 1 diff --git a/libc/sysdeps/linux/i386/sys/perm.h b/libc/sysdeps/linux/i386/sys/perm.h index e389e6679..c26868114 100644 --- a/libc/sysdeps/linux/i386/sys/perm.h +++ b/libc/sysdeps/linux/i386/sys/perm.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_PERM_H diff --git a/libc/sysdeps/linux/i386/sys/procfs.h b/libc/sysdeps/linux/i386/sys/procfs.h index f0be43309..673baa1ec 100644 --- a/libc/sysdeps/linux/i386/sys/procfs.h +++ b/libc/sysdeps/linux/i386/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/i386/sys/reg.h b/libc/sysdeps/linux/i386/sys/reg.h index 39003c45b..b993f999a 100644 --- a/libc/sysdeps/linux/i386/sys/reg.h +++ b/libc/sysdeps/linux/i386/sys/reg.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_REG_H #define _SYS_REG_H 1 diff --git a/libc/sysdeps/linux/i386/sys/ucontext.h b/libc/sysdeps/linux/i386/sys/ucontext.h index d6474c722..6306623ab 100644 --- a/libc/sysdeps/linux/i386/sys/ucontext.h +++ b/libc/sysdeps/linux/i386/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/>. */ #ifndef _SYS_UCONTEXT_H #define _SYS_UCONTEXT_H 1 diff --git a/libc/sysdeps/linux/i386/sys/user.h b/libc/sysdeps/linux/i386/sys/user.h index c5cfff256..80dd8a23c 100644 --- a/libc/sysdeps/linux/i386/sys/user.h +++ b/libc/sysdeps/linux/i386/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/i386/sys/vm86.h b/libc/sysdeps/linux/i386/sys/vm86.h index 8faeed7f1..1f7871bfb 100644 --- a/libc/sysdeps/linux/i386/sys/vm86.h +++ b/libc/sysdeps/linux/i386/sys/vm86.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_VM86_H diff --git a/libc/sysdeps/linux/i386/sysdep.h b/libc/sysdeps/linux/i386/sysdep.h new file mode 100644 index 000000000..c92a10663 --- /dev/null +++ b/libc/sysdeps/linux/i386/sysdep.h @@ -0,0 +1,429 @@ +/* Copyright (C) 1992,1993,1995-2000,2002-2006,2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995. + + 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_I386_SYSDEP_H +#define _LINUX_I386_SYSDEP_H 1 + +#include <sys/syscall.h> +#include <common/sysdep.h> + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ +#define ALIGNARG(log2) 1<<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 an entry point visible from C. + + There is currently a bug in gdb which prevents us from specifying + incomplete stabs information. Fake some entries here which specify + the current source file. */ +#define ENTRY(name) \ + .globl C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(4); \ + C_LABEL(name) \ + cfi_startproc; \ + CALL_MCOUNT + +#undef END +#define END(name) \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) \ + +/* If compiled for profiling, call `mcount' at the start of each function. */ +#ifdef PROF +/* The mcount code relies on a normal frame pointer being on the stack + to locate our caller, so push one just for its benefit. */ +#define CALL_MCOUNT \ + pushl %ebp; cfi_adjust_cfa_offset (4); movl %esp, %ebp; \ + cfi_def_cfa_register (ebp); call JUMPTARGET(mcount); \ + popl %ebp; cfi_def_cfa (esp, 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 + +#undef JUMPTARGET +#ifdef __PIC__ +#define JUMPTARGET(name) name##@PLT +#define SYSCALL_PIC_SETUP \ + pushl %ebx; \ + cfi_adjust_cfa_offset (4); \ + call 0f; \ +0: popl %ebx; \ + cfi_adjust_cfa_offset (-4); \ + addl $_GLOBAL_OFFSET_TABLE+[.-0b], %ebx; + + +# define SETUP_PIC_REG(reg) \ + .ifndef __x86.get_pc_thunk.reg; \ + .section .gnu.linkonce.t.__x86.get_pc_thunk.reg,"ax",@progbits; \ + .globl __x86.get_pc_thunk.reg; \ + .hidden __x86.get_pc_thunk.reg; \ + .type __x86.get_pc_thunk.reg,@function; \ +__x86.get_pc_thunk.reg: \ + movl (%esp), %e##reg; \ + ret; \ + .size __x86.get_pc_thunk.reg, . - __x86.get_pc_thunk.reg; \ + .previous; \ + .endif; \ + call __x86.get_pc_thunk.reg + +# define LOAD_PIC_REG(reg) \ + SETUP_PIC_REG(reg); addl $_GLOBAL_OFFSET_TABLE_, %e##reg + +#else +#define JUMPTARGET(name) name +#define SYSCALL_PIC_SETUP /* Nothing. */ +#endif + +/* Local label name for asm code. */ +#ifndef L +#ifdef HAVE_ELF +#define L(name) .L##name +#else +#define L(name) name +#endif +#endif + +/* Avoid conflics with thunk section */ +#undef __i686 +#endif /* __ASSEMBLER__ */ + +/* 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 SYS_ify(syscall_name) __NR_##syscall_name + +#if defined USE_DL_SYSINFO \ + && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define I386_USE_SYSENTER 1 +#else +# undef I386_USE_SYSENTER +#endif + +#ifdef __ASSEMBLER__ + +/* 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 %eax + 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 savely + test with -4095. */ + +/* We don't want the label for the error handle to be global when we define + it here. */ +#ifdef __PIC__ +# define SYSCALL_ERROR_LABEL 0f +#else +# define SYSCALL_ERROR_LABEL syscall_error +#endif + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +#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) + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +#define ret_NOERRNO ret + +/* 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); \ + negl %eax + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +#ifndef __PIC__ +# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +#else + +# ifdef RTLD_PRIVATE_ERRNO +# define SYSCALL_ERROR_HANDLER \ +0:SETUP_PIC_REG(cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + movl %edx, rtld_errno@GOTOFF(%ecx); \ + orl $-1, %eax; \ + jmp L(pseudo_end); + +# elif defined _LIBC_REENTRANT + +# if defined USE___THREAD +# ifndef NOT_IN_libc +# define SYSCALL_ERROR_ERRNO __libc_errno +# else +# define SYSCALL_ERROR_ERRNO errno +# endif +# define SYSCALL_ERROR_HANDLER \ +0:SETUP_PIC_REG (cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + SYSCALL_ERROR_HANDLER_TLS_STORE (%edx, %ecx); \ + orl $-1, %eax; \ + jmp L(pseudo_end); +# ifndef NO_TLS_DIRECT_SEG_REFS +# define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff) \ + movl src, %gs:(destoff) +# else +# define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff) \ + addl %gs:0, destoff; \ + movl src, (destoff) +# endif +# else +# define SYSCALL_ERROR_HANDLER \ +0:pushl %ebx; \ + cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); \ + SETUP_PIC_REG (bx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + pushl %edx; \ + cfi_adjust_cfa_offset (4); \ + call __errno_location@PLT; \ + popl %ecx; \ + cfi_adjust_cfa_offset (-4); \ + popl %ebx; \ + cfi_adjust_cfa_offset (-4); \ + cfi_restore (ebx); \ + movl %ecx, (%eax); \ + orl $-1, %eax; \ + jmp L(pseudo_end); +/* A quick note: it is assumed that the call to `__errno_location' does + not modify the stack! */ +# endif +# else +/* Store (- %eax) into errno through the GOT. */ +# define SYSCALL_ERROR_HANDLER \ +0:SETUP_PIC_REG(cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + movl errno@GOT(%ecx), %ecx; \ + movl %edx, (%ecx); \ + orl $-1, %eax; \ + jmp L(pseudo_end); +# endif /* _LIBC_REENTRANT */ +#endif /* __PIC__ */ + + +/* The original calling convention for system calls on Linux/i386 is + to use int $0x80. */ +#ifdef I386_USE_SYSENTER +# ifdef SHARED +# define ENTER_KERNEL call *%gs:SYSINFO_OFFSET +# else +# define ENTER_KERNEL call *_dl_sysinfo +# endif +#else +# define ENTER_KERNEL int $0x80 +#endif + +/* Linux takes system call arguments in registers: + + syscall number %eax call-clobbered + arg 1 %ebx call-saved + arg 2 %ecx call-clobbered + arg 3 %edx call-clobbered + arg 4 %esi call-saved + arg 5 %edi call-saved + arg 6 %ebp call-saved + + The stack layout upon entering the function is: + + 24(%esp) Arg# 6 + 20(%esp) Arg# 5 + 16(%esp) Arg# 4 + 12(%esp) Arg# 3 + 8(%esp) Arg# 2 + 4(%esp) Arg# 1 + (%esp) Return address + + (Of course a function with say 3 arguments does not have entries for + arguments 4, 5, and 6.) + + The following code tries hard to be optimal. A general assumption + (which is true according to the data books I have) is that + + 2 * xchg is more expensive than pushl + movl + popl + + Beside this a neat trick is used. The calling conventions for Linux + tell that among the registers used for parameters %ecx and %edx need + not be saved. Beside this we may clobber this registers even when + they are not used for parameter passing. + + As a result one can see below that we save the content of the %ebx + register in the %edx register when we have less than 3 arguments + (2 * movl is less expensive than pushl + popl). + + Second unlike for the other registers we don't save the content of + %ecx and %edx when we have more than 1 and 2 registers resp. + + The code below might look a bit long but we have to take care for + the pipelined processors (i586). Here the `pushl' and `popl' + instructions are marked as NP (not pairable) but the exception is + two consecutive of these instruction. This gives no penalty on + other processors though. */ + +#undef DO_CALL +#define DO_CALL(syscall_name, args) \ + PUSHARGS_##args \ + DOARGS_##args \ + movl $SYS_ify (syscall_name), %eax; \ + ENTER_KERNEL \ + POPARGS_##args + +#define PUSHARGS_0 /* No arguments to push. */ +#define DOARGS_0 /* No arguments to frob. */ +#define POPARGS_0 /* No arguments to pop. */ +#define _PUSHARGS_0 /* No arguments to push. */ +#define _DOARGS_0(n) /* No arguments to frob. */ +#define _POPARGS_0 /* No arguments to pop. */ + +#define PUSHARGS_1 movl %ebx, %edx; L(SAVEBX1): PUSHARGS_0 +#define DOARGS_1 _DOARGS_1 (4) +#define POPARGS_1 POPARGS_0; movl %edx, %ebx; L(RESTBX1): +#define _PUSHARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); L(PUSHBX1): _PUSHARGS_0 +#define _DOARGS_1(n) movl n(%esp), %ebx; _DOARGS_0(n-4) +#define _POPARGS_1 _POPARGS_0; popl %ebx; cfi_adjust_cfa_offset (-4); \ + cfi_restore (ebx); L(POPBX1): + +#define PUSHARGS_2 PUSHARGS_1 +#define DOARGS_2 _DOARGS_2 (8) +#define POPARGS_2 POPARGS_1 +#define _PUSHARGS_2 _PUSHARGS_1 +#define _DOARGS_2(n) movl n(%esp), %ecx; _DOARGS_1 (n-4) +#define _POPARGS_2 _POPARGS_1 + +#define PUSHARGS_3 _PUSHARGS_2 +#define DOARGS_3 _DOARGS_3 (16) +#define POPARGS_3 _POPARGS_3 +#define _PUSHARGS_3 _PUSHARGS_2 +#define _DOARGS_3(n) movl n(%esp), %edx; _DOARGS_2 (n-4) +#define _POPARGS_3 _POPARGS_2 + +#define PUSHARGS_4 _PUSHARGS_4 +#define DOARGS_4 _DOARGS_4 (24) +#define POPARGS_4 _POPARGS_4 +#define _PUSHARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (esi, 0); L(PUSHSI1): _PUSHARGS_3 +#define _DOARGS_4(n) movl n(%esp), %esi; _DOARGS_3 (n-4) +#define _POPARGS_4 _POPARGS_3; popl %esi; cfi_adjust_cfa_offset (-4); \ + cfi_restore (esi); L(POPSI1): + +#define PUSHARGS_5 _PUSHARGS_5 +#define DOARGS_5 _DOARGS_5 (32) +#define POPARGS_5 _POPARGS_5 +#define _PUSHARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (edi, 0); L(PUSHDI1): _PUSHARGS_4 +#define _DOARGS_5(n) movl n(%esp), %edi; _DOARGS_4 (n-4) +#define _POPARGS_5 _POPARGS_4; popl %edi; cfi_adjust_cfa_offset (-4); \ + cfi_restore (edi); L(POPDI1): + +#define PUSHARGS_6 _PUSHARGS_6 +#define DOARGS_6 _DOARGS_6 (40) +#define POPARGS_6 _POPARGS_6 +#define _PUSHARGS_6 pushl %ebp; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebp, 0); L(PUSHBP1): _PUSHARGS_5 +#define _DOARGS_6(n) movl n(%esp), %ebp; _DOARGS_5 (n-4) +#define _POPARGS_6 _POPARGS_5; popl %ebp; cfi_adjust_cfa_offset (-4); \ + cfi_restore (ebp); L(POPBP1): + +#endif /* __ASSEMBLER__ */ + + +/* Pointer mangling support. */ +#if defined NOT_IN_libc && defined IS_IN_rtld +/* We cannot use the thread descriptor because in ld.so we use setjmp + earlier than the descriptor is initialized. Using a global variable + is too complicated here since we have no PC-relative addressing mode. */ +#else +# ifdef __ASSEMBLER__ +# define PTR_MANGLE(reg) xorl %gs:POINTER_GUARD, reg; \ + roll $9, reg +# define PTR_DEMANGLE(reg) rorl $9, reg; \ + xorl %gs:POINTER_GUARD, reg +# else +# include <stddef.h> +# define PTR_MANGLE(var) __asm__ ("xorl %%gs:%c2, %0\n" \ + "roll $9, %0" \ + : "=r" (var) \ + : "0" (var), \ + "i" (offsetof (tcbhead_t, \ + pointer_guard))) +# define PTR_DEMANGLE(var) __asm__ ("rorl $9, %0\n" \ + "xorl %%gs:%c2, %0" \ + : "=r" (var) \ + : "0" (var), \ + "i" (offsetof (tcbhead_t, \ + pointer_guard))) +# endif +#endif + +#endif /* linux/i386/sysdep.h */ diff --git a/libc/sysdeps/linux/i386/ucontext_i.sym b/libc/sysdeps/linux/i386/ucontext_i.sym new file mode 100644 index 000000000..b11a5509c --- /dev/null +++ b/libc/sysdeps/linux/i386/ucontext_i.sym @@ -0,0 +1,30 @@ +#include <stddef.h> +#include <signal.h> +#include <sys/ucontext.h> + +-- + +SIG_BLOCK +SIG_SETMASK + +#define ucontext(member) offsetof (ucontext_t, member) +#define mcontext(member) ucontext (uc_mcontext.member) +#define mreg(reg) mcontext (gregs[REG_##reg]) + +oLINK ucontext (uc_link) +oSS_SP ucontext (uc_stack.ss_sp) +oSS_SIZE ucontext (uc_stack.ss_size) +oGS mreg (GS) +oFS mreg (FS) +oEDI mreg (EDI) +oESI mreg (ESI) +oEBP mreg (EBP) +oESP mreg (ESP) +oEBX mreg (EBX) +oEDX mreg (EDX) +oECX mreg (ECX) +oEAX mreg (EAX) +oEIP mreg (EIP) +oFPREGS mcontext (fpregs) +oSIGMASK ucontext (uc_sigmask) +oFPREGSMEM ucontext (__fpregs_mem) diff --git a/libc/sysdeps/linux/i386/vfork.S b/libc/sysdeps/linux/i386/vfork.S index 8005ff1d2..d85726f19 100644 --- a/libc/sysdeps/linux/i386/vfork.S +++ b/libc/sysdeps/linux/i386/vfork.S @@ -18,9 +18,19 @@ __vfork: popl %ecx + +#ifdef SAVE_PID + SAVE_PID +#endif + movl $__NR_vfork,%eax int $0x80 pushl %ecx + +#ifdef RESTORE_PID + RESTORE_PID +#endif + cmpl $-4095,%eax jae __syscall_error ret @@ -28,4 +38,4 @@ __vfork: .size __vfork,.-__vfork weak_alias(__vfork,vfork) -libc_hidden_weak(vfork) +libc_hidden_def(vfork) |
