summaryrefslogtreecommitdiff
path: root/libc/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps')
-rw-r--r--libc/sysdeps/generic/ldsodefs.h6
-rw-r--r--libc/sysdeps/generic/paths.h8
-rw-r--r--libc/sysdeps/gnu/configure36
-rw-r--r--libc/sysdeps/gnu/configure.in36
-rw-r--r--libc/sysdeps/i386/fpu/e_exp10l.S41
-rw-r--r--libc/sysdeps/i386/fpu/e_expl.S80
-rw-r--r--libc/sysdeps/i386/fpu/libm-test-ulps64
-rw-r--r--libc/sysdeps/i386/fpu/s_expm1l.S91
-rw-r--r--libc/sysdeps/ieee754/dbl-64/e_exp10.c48
-rw-r--r--libc/sysdeps/ieee754/dbl-64/s_logb.c37
-rw-r--r--libc/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c13
-rw-r--r--libc/sysdeps/ieee754/flt-32/s_logbf.c32
-rw-r--r--libc/sysdeps/ieee754/ldbl-128/e_exp10l.c47
-rw-r--r--libc/sysdeps/ieee754/ldbl-128/s_logbl.c31
-rw-r--r--libc/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c46
-rw-r--r--libc/sysdeps/ieee754/ldbl-128ibm/s_logbl.c35
-rw-r--r--libc/sysdeps/ieee754/ldbl-96/s_logbl.c35
-rw-r--r--libc/sysdeps/mach/bits/libc-lock.h5
-rw-r--r--libc/sysdeps/mach/hurd/Makefile3
-rw-r--r--libc/sysdeps/mach/hurd/accept.c65
-rw-r--r--libc/sysdeps/mach/hurd/accept4.c99
-rw-r--r--libc/sysdeps/mach/hurd/bits/fcntl.h11
-rw-r--r--libc/sysdeps/mach/hurd/bits/ioctls.h3
-rw-r--r--libc/sysdeps/mach/hurd/bits/libc-lock.h5
-rw-r--r--libc/sysdeps/mach/hurd/bits/posix_opt.h30
-rw-r--r--libc/sysdeps/mach/hurd/bits/socket.h362
-rw-r--r--libc/sysdeps/mach/hurd/bits/stat.h59
-rw-r--r--libc/sysdeps/mach/hurd/brk.c20
-rw-r--r--libc/sysdeps/mach/hurd/chroot.c5
-rwxr-xr-xlibc/sysdeps/mach/hurd/configure5
-rw-r--r--libc/sysdeps/mach/hurd/configure.in4
-rw-r--r--libc/sysdeps/mach/hurd/dirfd.c5
-rw-r--r--libc/sysdeps/mach/hurd/dl-sysdep.c11
-rw-r--r--libc/sysdeps/mach/hurd/dl-sysdep.h5
-rw-r--r--libc/sysdeps/mach/hurd/dup2.c114
-rw-r--r--libc/sysdeps/mach/hurd/dup3.c139
-rw-r--r--libc/sysdeps/mach/hurd/i386/Makefile4
-rw-r--r--libc/sysdeps/mach/hurd/i386/____longjmp_chk.S107
-rw-r--r--libc/sysdeps/mach/hurd/i386/init-first.c47
-rw-r--r--libc/sysdeps/mach/hurd/i386/signal-defines.sym10
-rw-r--r--libc/sysdeps/mach/hurd/ioctl.c21
-rw-r--r--libc/sysdeps/mach/hurd/kernel-features.h13
-rw-r--r--libc/sysdeps/mach/hurd/mkdir.c8
-rw-r--r--libc/sysdeps/mach/hurd/mkdirat.c9
-rw-r--r--libc/sysdeps/mach/hurd/mlock.c4
-rw-r--r--libc/sysdeps/mach/hurd/openat.c6
-rw-r--r--libc/sysdeps/mach/hurd/opendir.c42
-rw-r--r--libc/sysdeps/mach/hurd/readlinkat.c63
-rw-r--r--libc/sysdeps/mach/hurd/recvfrom.c6
-rw-r--r--libc/sysdeps/mach/hurd/setitimer.c5
-rw-r--r--libc/sysdeps/mach/hurd/setresgid.c76
-rw-r--r--libc/sysdeps/mach/hurd/setresuid.c75
-rw-r--r--libc/sysdeps/mach/hurd/xmknodat.c10
-rw-r--r--libc/sysdeps/mach/hurd/xstatconv.c11
-rw-r--r--libc/sysdeps/mach/nanosleep.c33
-rw-r--r--libc/sysdeps/posix/getaddrinfo.c2
-rw-r--r--libc/sysdeps/posix/getcwd.c3
-rw-r--r--libc/sysdeps/powerpc/memmove.c5
-rw-r--r--libc/sysdeps/sparc/fpu/bits/fenv.h4
-rw-r--r--libc/sysdeps/sparc/fpu/fpu_control.h8
-rw-r--r--libc/sysdeps/sparc/fpu/libm-test-ulps50
-rw-r--r--libc/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_floor-vis3.S3
-rw-r--r--libc/sysdeps/sparc/sysdep.h25
-rw-r--r--libc/sysdeps/unix/syscalls.list2
-rw-r--r--libc/sysdeps/unix/sysv/linux/configure32
-rw-r--r--libc/sysdeps/unix/sysv/linux/configure.in32
-rw-r--r--libc/sysdeps/unix/sysv/linux/syscalls.list3
-rw-r--r--libc/sysdeps/unix/sysv/syscalls.list9
-rw-r--r--libc/sysdeps/x86_64/Makefile13
-rw-r--r--libc/sysdeps/x86_64/dl-machine.h132
-rw-r--r--libc/sysdeps/x86_64/dl-trampoline.S4
-rw-r--r--libc/sysdeps/x86_64/fpu/bits/mathinline.h48
-rw-r--r--libc/sysdeps/x86_64/fpu/e_exp10l.S2
-rw-r--r--libc/sysdeps/x86_64/fpu/e_expl.S80
-rw-r--r--libc/sysdeps/x86_64/fpu/libm-test-ulps91
-rw-r--r--libc/sysdeps/x86_64/fpu/s_expm1l.S87
-rw-r--r--libc/sysdeps/x86_64/tst-quad1.c25
-rw-r--r--libc/sysdeps/x86_64/tst-quad1pie.c1
-rw-r--r--libc/sysdeps/x86_64/tst-quad2.c1
-rw-r--r--libc/sysdeps/x86_64/tst-quad2pie.c1
-rw-r--r--libc/sysdeps/x86_64/tst-quadmod1.S44
-rw-r--r--libc/sysdeps/x86_64/tst-quadmod1pie.S2
-rw-r--r--libc/sysdeps/x86_64/tst-quadmod2.S43
-rw-r--r--libc/sysdeps/x86_64/tst-quadmod2pie.S1
84 files changed, 2085 insertions, 854 deletions
diff --git a/libc/sysdeps/generic/ldsodefs.h b/libc/sysdeps/generic/ldsodefs.h
index f6458627d..16bcfd10c 100644
--- a/libc/sysdeps/generic/ldsodefs.h
+++ b/libc/sysdeps/generic/ldsodefs.h
@@ -725,7 +725,11 @@ rtld_hidden_proto (_dl_make_stack_executable)
might use the variable which results in copy relocations on some
platforms. But this does not matter, ld.so can always use the local
copy. */
-extern void *__libc_stack_end attribute_relro;
+extern void *__libc_stack_end
+#ifndef LIBC_STACK_END_NOT_RELRO
+ attribute_relro
+#endif
+ ;
rtld_hidden_proto (__libc_stack_end)
/* Parameters passed to the dynamic linker. */
diff --git a/libc/sysdeps/generic/paths.h b/libc/sysdeps/generic/paths.h
index 439992fe7..f85e88cb9 100644
--- a/libc/sysdeps/generic/paths.h
+++ b/libc/sysdeps/generic/paths.h
@@ -46,15 +46,15 @@
#define _PATH_DRUM "/dev/drum"
#define _PATH_GSHADOW "/etc/gshadow"
#define _PATH_KMEM "/dev/kmem"
-#define _PATH_MAILDIR "/var/mail"
#define _PATH_LASTLOG "/var/log/lastlog"
-#define _PATH_MAN "/usr/man"
+#define _PATH_MAILDIR "/var/mail"
+#define _PATH_MAN "/usr/share/man"
#define _PATH_MEM "/dev/mem"
#define _PATH_MNTTAB "/etc/fstab"
#define _PATH_MOUNTED "/var/run/mtab"
#define _PATH_NOLOGIN "/etc/nologin"
-#define _PATH_PRESERVE "/var/preserve"
-#define _PATH_RWHODIR "/var/rwho"
+#define _PATH_PRESERVE "/var/lib"
+#define _PATH_RWHODIR "/var/spool/rwho"
#define _PATH_SENDMAIL "/usr/sbin/sendmail"
#define _PATH_SHADOW "/etc/shadow"
#define _PATH_SHELLS "/etc/shells"
diff --git a/libc/sysdeps/gnu/configure b/libc/sysdeps/gnu/configure
new file mode 100644
index 000000000..634e1d0cc
--- /dev/null
+++ b/libc/sysdeps/gnu/configure
@@ -0,0 +1,36 @@
+# This file is generated from configure.in by Autoconf. DO NOT EDIT!
+
+# Local configure fragment for sysdeps/gnu.
+
+# The Filesystem Hierarchy Standard prescribes where to place "essential"
+# files. I.e., when the installation prefix is "/usr" we have to place
+# shared library objects and the configuration files on the root partition
+# in /lib and /etc.
+case "$prefix" in
+/usr | /usr/)
+ # 64-bit libraries on bi-arch platforms go in /lib64 instead of /lib.
+ # Allow earlier configure scripts to handle libc_cv_slibdir, libdir,
+ # and libc_cv_localedir.
+ test -n "$libc_cv_slibdir" || \
+ case $machine in
+ sparc/sparc64 | x86_64* | powerpc/powerpc64 | s390/s390-64)
+ libc_cv_slibdir=/lib64
+ if test "$libdir" = '${exec_prefix}/lib'; then
+ libdir='${exec_prefix}/lib64';
+ # Locale data can be shared between 32bit and 64bit libraries
+ libc_cv_localedir='${exec_prefix}/lib/locale'
+ fi
+ ;;
+ *)
+ libc_cv_slibdir=/lib
+ ;;
+ esac
+ # Allow the user to override the path with --sysconfdir
+ if test "$sysconfdir" = '${prefix}/etc'; then
+ libc_cv_sysconfdir=/etc
+ else
+ libc_cv_sysconfdir=$sysconfdir
+ fi
+ libc_cv_rootsbindir=/sbin
+ ;;
+esac
diff --git a/libc/sysdeps/gnu/configure.in b/libc/sysdeps/gnu/configure.in
new file mode 100644
index 000000000..3422007ff
--- /dev/null
+++ b/libc/sysdeps/gnu/configure.in
@@ -0,0 +1,36 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+
+# Local configure fragment for sysdeps/gnu.
+
+# The Filesystem Hierarchy Standard prescribes where to place "essential"
+# files. I.e., when the installation prefix is "/usr" we have to place
+# shared library objects and the configuration files on the root partition
+# in /lib and /etc.
+case "$prefix" in
+/usr | /usr/)
+ # 64-bit libraries on bi-arch platforms go in /lib64 instead of /lib.
+ # Allow earlier configure scripts to handle libc_cv_slibdir, libdir,
+ # and libc_cv_localedir.
+ test -n "$libc_cv_slibdir" || \
+ case $machine in
+ sparc/sparc64 | x86_64* | powerpc/powerpc64 | s390/s390-64)
+ libc_cv_slibdir=/lib64
+ if test "$libdir" = '${exec_prefix}/lib'; then
+ libdir='${exec_prefix}/lib64';
+ # Locale data can be shared between 32bit and 64bit libraries
+ libc_cv_localedir='${exec_prefix}/lib/locale'
+ fi
+ ;;
+ *)
+ libc_cv_slibdir=/lib
+ ;;
+ esac
+ # Allow the user to override the path with --sysconfdir
+ if test "$sysconfdir" = '${prefix}/etc'; then
+ libc_cv_sysconfdir=/etc
+ else
+ libc_cv_sysconfdir=$sysconfdir
+ fi
+ libc_cv_rootsbindir=/sbin
+ ;;
+esac
diff --git a/libc/sysdeps/i386/fpu/e_exp10l.S b/libc/sysdeps/i386/fpu/e_exp10l.S
index 04ec8001d..d843e2b5e 100644
--- a/libc/sysdeps/i386/fpu/e_exp10l.S
+++ b/libc/sysdeps/i386/fpu/e_exp10l.S
@@ -1,39 +1,2 @@
-/*
- * Written by Ulrich Drepper <drepper@cygnus.com>.
- */
-
-#include <machine/asm.h>
-
-/* 10^x = 2^(x * log2l(10)) */
-ENTRY(__ieee754_exp10l)
- fldt 4(%esp)
-/* I added the following ugly construct because expl(+-Inf) resulted
- in NaN. The ugliness results from the bright minds at Intel.
- For the i686 the code can be written better.
- -- drepper@cygnus.com. */
- fxam /* Is NaN or +-Inf? */
- fstsw %ax
- movb $0x45, %dh
- andb %ah, %dh
- cmpb $0x05, %dh
- je 1f /* Is +-Inf, jump. */
- fldl2t
- fmulp /* x * log2(10) */
- fld %st
- frndint /* int(x * log2(10)) */
- fsubr %st,%st(1) /* fract(x * log2(10)) */
- fxch
- f2xm1 /* 2^(fract(x * log2(10))) - 1 */
- fld1
- faddp /* 2^(fract(x * log2(10))) */
- fscale /* e^x */
- fstp %st(1)
- ret
-
-1: testl $0x200, %eax /* Test sign. */
- jz 2f /* If positive, jump. */
- fstp %st
- fldz /* Set result to 0. */
-2: ret
-END (__ieee754_exp10l)
-strong_alias (__ieee754_exp10l, __exp10l_finite)
+#define USE_AS_EXP10L
+#include <e_expl.S>
diff --git a/libc/sysdeps/i386/fpu/e_expl.S b/libc/sysdeps/i386/fpu/e_expl.S
index 45c4d0753..bab0a081b 100644
--- a/libc/sysdeps/i386/fpu/e_expl.S
+++ b/libc/sysdeps/i386/fpu/e_expl.S
@@ -24,9 +24,33 @@
#include <machine/asm.h>
+#ifdef USE_AS_EXP10L
+# define IEEE754_EXPL __ieee754_exp10l
+# define EXPL_FINITE __exp10l_finite
+# define FLDLOG fldl2t
+#elif defined USE_AS_EXPM1L
+# define IEEE754_EXPL __expm1l
+# undef EXPL_FINITE
+# define FLDLOG fldl2e
+#else
+# define IEEE754_EXPL __ieee754_expl
+# define EXPL_FINITE __expl_finite
+# define FLDLOG fldl2e
+#endif
+
.section .rodata.cst16,"aM",@progbits,16
.p2align 4
+#ifdef USE_AS_EXP10L
+ ASM_TYPE_DIRECTIVE(c0,@object)
+c0: .byte 0, 0, 0, 0, 0, 0, 0x9a, 0xd4, 0x00, 0x40
+ .byte 0, 0, 0, 0, 0, 0
+ ASM_SIZE_DIRECTIVE(c0)
+ ASM_TYPE_DIRECTIVE(c1,@object)
+c1: .byte 0x58, 0x92, 0xfc, 0x15, 0x37, 0x9a, 0x97, 0xf0, 0xef, 0x3f
+ .byte 0, 0, 0, 0, 0, 0
+ ASM_SIZE_DIRECTIVE(c1)
+#else
ASM_TYPE_DIRECTIVE(c0,@object)
c0: .byte 0, 0, 0, 0, 0, 0, 0xaa, 0xb8, 0xff, 0x3f
.byte 0, 0, 0, 0, 0, 0
@@ -35,6 +59,7 @@ c0: .byte 0, 0, 0, 0, 0, 0, 0xaa, 0xb8, 0xff, 0x3f
c1: .byte 0x20, 0xfa, 0xee, 0xc2, 0x5f, 0x70, 0xa5, 0xec, 0xed, 0x3f
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(c1)
+#endif
ASM_TYPE_DIRECTIVE(csat,@object)
csat: .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0e, 0x40
.byte 0, 0, 0, 0, 0, 0
@@ -47,7 +72,13 @@ csat: .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0e, 0x40
#endif
.text
-ENTRY(__ieee754_expl)
+ENTRY(IEEE754_EXPL)
+#ifdef USE_AS_EXPM1L
+ movzwl 4+8(%esp), %eax
+ xorb $0x80, %ah // invert sign bit (now 1 is "positive")
+ cmpl $0xc006, %eax // is num positive and exp >= 6 (number is >= 128.0)?
+ jae HIDDEN_JUMPTARGET (__expl) // (if num is denormal, it is at least >= 64.0)
+#endif
fldt 4(%esp)
/* I added the following ugly construct because expl(+-Inf) resulted
in NaN. The ugliness results from the bright minds at Intel.
@@ -57,7 +88,9 @@ ENTRY(__ieee754_expl)
#ifdef PIC
LOAD_PIC_REG (cx)
#endif
+#ifndef USE_AS_EXPM1L
movzwl 4+8(%esp), %eax
+#endif
andl $0x7fff, %eax
cmpl $0x400d, %eax
jle 3f
@@ -75,8 +108,17 @@ ENTRY(__ieee754_expl)
andb $2, %ah
jz 3f
fchs
-3: fldl2e /* 1 log2(e) */
- fmul %st(1), %st /* 1 x log2(e) */
+3:
+#ifdef USE_AS_EXPM1L
+ /* Test for +-0 as argument. */
+ fstsw %ax
+ movb $0x45, %dh
+ andb %ah, %dh
+ cmpb $0x40, %dh
+ je 2f
+#endif
+ FLDLOG /* 1 log2(base) */
+ fmul %st(1), %st /* 1 x log2(base) */
frndint /* 1 i */
fld %st(1) /* 2 x */
frndint /* 2 xi */
@@ -92,18 +134,40 @@ ENTRY(__ieee754_expl)
fldt MO(c1) /* 4 */
fmul %st(4), %st /* 4 c1 * x */
faddp %st, %st(1) /* 3 f = f + c1 * x */
- f2xm1 /* 3 2^(fract(x * log2(e))) - 1 */
+ f2xm1 /* 3 2^(fract(x * log2(base))) - 1 */
+#ifdef USE_AS_EXPM1L
+ fstp %st(1) /* 2 */
+ fscale /* 2 scale factor is st(1); base^x - 2^i */
+ fxch /* 2 i */
+ fld1 /* 3 1.0 */
+ fscale /* 3 2^i */
+ fld1 /* 4 1.0 */
+ fsubrp %st, %st(1) /* 3 2^i - 1.0 */
+ fstp %st(1) /* 2 */
+ faddp %st, %st(1) /* 1 base^x - 1.0 */
+#else
fld1 /* 4 1.0 */
- faddp /* 3 2^(fract(x * log2(e))) */
+ faddp /* 3 2^(fract(x * log2(base))) */
fstp %st(1) /* 2 */
- fscale /* 2 scale factor is st(1); e^x */
+ fscale /* 2 scale factor is st(1); base^x */
fstp %st(1) /* 1 */
+#endif
fstp %st(1) /* 0 */
jmp 2f
1: testl $0x200, %eax /* Test sign. */
jz 2f /* If positive, jump. */
fstp %st
+#ifdef USE_AS_EXPM1L
+ fld1
+ fchs
+#else
fldz /* Set result to 0. */
+#endif
2: ret
-END(__ieee754_expl)
-strong_alias (__ieee754_expl, __expl_finite)
+END(IEEE754_EXPL)
+#ifdef USE_AS_EXPM1L
+libm_hidden_def (__expm1l)
+weak_alias (__expm1l, expm1l)
+#else
+strong_alias (IEEE754_EXPL, EXPL_FINITE)
+#endif
diff --git a/libc/sysdeps/i386/fpu/libm-test-ulps b/libc/sysdeps/i386/fpu/libm-test-ulps
index 63235537e..cdc26a0c6 100644
--- a/libc/sysdeps/i386/fpu/libm-test-ulps
+++ b/libc/sysdeps/i386/fpu/libm-test-ulps
@@ -1008,10 +1008,6 @@ Test "cos_upward (9) == -0.9111302618846769883682947111811653112463":
ildouble: 1
ldouble: 1
-# cosh
-Test "cosh (0.75) == 1.29468328467684468784170818539018176":
-ildouble: 1
-
# cosh_downward
Test "cosh_downward (22) == 1792456423.065795780980053377632656584997":
double: 1
@@ -1899,29 +1895,20 @@ double: 1
float: 1
idouble: 1
ifloat: 1
-ildouble: 4
-ldouble: 4
+ildouble: 2
+ldouble: 2
Test "sinh_downward (23) == 4872401723.124451299966006944252978187305":
double: 1
float: 1
idouble: 1
ifloat: 1
+ildouble: 2
+ldouble: 2
Test "sinh_downward (24) == 13244561064.92173614705070540368454568168":
float: 1
ifloat: 1
-ildouble: 5
-ldouble: 5
-
-# sinh_tonearest
-Test "sinh_tonearest (22) == 1792456423.065795780701106568345764104225":
-ildouble: 3
-ldouble: 3
-Test "sinh_tonearest (23) == 4872401723.124451299966006944252978187305":
-ildouble: 1
-ldouble: 1
-Test "sinh_tonearest (24) == 13244561064.92173614705070540368454568168":
-ildouble: 6
-ldouble: 6
+ildouble: 2
+ldouble: 2
# sinh_towardzero
Test "sinh_towardzero (22) == 1792456423.065795780701106568345764104225":
@@ -1929,31 +1916,31 @@ double: 1
float: 1
idouble: 1
ifloat: 1
-ildouble: 4
-ldouble: 4
+ildouble: 2
+ldouble: 2
Test "sinh_towardzero (23) == 4872401723.124451299966006944252978187305":
double: 1
float: 1
idouble: 1
ifloat: 1
+ildouble: 2
+ldouble: 2
Test "sinh_towardzero (24) == 13244561064.92173614705070540368454568168":
float: 1
ifloat: 1
-ildouble: 5
-ldouble: 5
+ildouble: 2
+ldouble: 2
# sinh_upward
Test "sinh_upward (22) == 1792456423.065795780701106568345764104225":
-ildouble: 16
-ldouble: 16
+ildouble: 1
+ldouble: 1
Test "sinh_upward (23) == 4872401723.124451299966006944252978187305":
-ildouble: 27
-ldouble: 27
+ildouble: 1
+ldouble: 1
Test "sinh_upward (24) == 13244561064.92173614705070540368454568168":
double: 1
idouble: 1
-ildouble: 7
-ldouble: 7
# tan
Test "tan (0x1p16383) == 0.422722393732022337800504160054440141575":
@@ -2587,9 +2574,6 @@ ifloat: 1
ildouble: 1
ldouble: 1
-Function: "cosh":
-ildouble: 1
-
Function: "cosh_downward":
double: 1
float: 1
@@ -2862,26 +2846,22 @@ double: 1
float: 1
idouble: 1
ifloat: 1
-ildouble: 5
-ldouble: 5
-
-Function: "sinh_tonearest":
-ildouble: 6
-ldouble: 6
+ildouble: 2
+ldouble: 2
Function: "sinh_towardzero":
double: 1
float: 1
idouble: 1
ifloat: 1
-ildouble: 5
-ldouble: 5
+ildouble: 2
+ldouble: 2
Function: "sinh_upward":
double: 1
idouble: 1
-ildouble: 27
-ldouble: 27
+ildouble: 1
+ldouble: 1
Function: "tan":
double: 1
diff --git a/libc/sysdeps/i386/fpu/s_expm1l.S b/libc/sysdeps/i386/fpu/s_expm1l.S
index e91f18b69..7fbd99b0d 100644
--- a/libc/sysdeps/i386/fpu/s_expm1l.S
+++ b/libc/sysdeps/i386/fpu/s_expm1l.S
@@ -1,89 +1,2 @@
-/* ix87 specific implementation of exp(x)-1.
- Copyright (C) 1996-1997, 2002, 2005, 2008, 2012 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
- Based on code by John C. Bowman <bowman@ipp-garching.mpg.de>.
- Corrections by H.J. Lu (hjl@gnu.ai.mit.edu), 1997.
-
- 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/>. */
-
- /* Using: e^x - 1 = 2^(x * log2(e)) - 1 */
-
-#include <sysdep.h>
-#include <machine/asm.h>
-
- .section .rodata
-
- .align ALIGNARG(4)
- ASM_TYPE_DIRECTIVE(minus1,@object)
-minus1: .double -1.0
- ASM_SIZE_DIRECTIVE(minus1)
- ASM_TYPE_DIRECTIVE(one,@object)
-one: .double 1.0
- ASM_SIZE_DIRECTIVE(one)
- ASM_TYPE_DIRECTIVE(l2e,@object)
-l2e: .tfloat 1.442695040888963407359924681002
- ASM_SIZE_DIRECTIVE(l2e)
-
-#ifdef PIC
-#define MO(op) op##@GOTOFF(%edx)
-#else
-#define MO(op) op
-#endif
-
- .text
-ENTRY(__expm1l)
- movzwl 4+8(%esp), %eax // load sign bit and 15-bit exponent
- xorb $0x80, %ah // invert sign bit (now 1 is "positive")
- cmpl $0xc006, %eax // is num positive and exp >= 6 (number is >= 128.0)?
- jae HIDDEN_JUMPTARGET (__expl) // (if num is denormal, it is at least >= 64.0)
-
- fldt 4(%esp) // x
- fxam // Is NaN or +-Inf?
- fstsw %ax
- movb $0x45, %ch
- andb %ah, %ch
- cmpb $0x40, %ch
- je 3f // If +-0, jump.
-#ifdef PIC
- LOAD_PIC_REG (dx)
-#endif
- cmpb $0x05, %ch
- je 2f // If +-Inf, jump.
-
- fldt MO(l2e) // log2(e) : x
- fmulp // log2(e)*x
- fld %st // log2(e)*x : log2(e)*x
- frndint // int(log2(e)*x) : log2(e)*x
- fsubr %st, %st(1) // int(log2(e)*x) : fract(log2(e)*x)
- fxch // fract(log2(e)*x) : int(log2(e)*x)
- f2xm1 // 2^fract(log2(e)*x)-1 : int(log2(e)*x)
- fscale // 2^(log2(e)*x)-2^int(log2(e)*x) : int(log2(e)*x)
- fxch // int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fldl MO(one) // 1 : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fscale // 2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fsubrl MO(one) // 1-2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fstp %st(1) // 1-2^int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fsubrp %st, %st(1) // 2^(log2(e)*x)
- ret
-
-2: testl $0x200, %eax // Test sign.
- jz 3f // If positive, jump.
- fstp %st
- fldl MO(minus1) // Set result to -1.0.
-3: ret
-END(__expm1l)
-libm_hidden_def (__expm1l)
-weak_alias (__expm1l, expm1l)
+#define USE_AS_EXPM1L
+#include <e_expl.S>
diff --git a/libc/sysdeps/ieee754/dbl-64/e_exp10.c b/libc/sysdeps/ieee754/dbl-64/e_exp10.c
new file mode 100644
index 000000000..eeb63a698
--- /dev/null
+++ b/libc/sysdeps/ieee754/dbl-64/e_exp10.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+#include <float.h>
+
+static const double log10_high = 0x2.4d7637p0;
+static const double log10_low = 0x7.6aaa2b05ba95cp-28;
+
+double
+__ieee754_exp10 (double arg)
+{
+ int32_t lx;
+ double arg_high, arg_low;
+ double exp_high, exp_low;
+
+ if (!__finite (arg))
+ return __ieee754_exp (arg);
+ if (arg < DBL_MIN_10_EXP - DBL_DIG - 10)
+ return DBL_MIN * DBL_MIN;
+ else if (arg > DBL_MAX_10_EXP + 1)
+ return DBL_MAX * DBL_MAX;
+
+ GET_LOW_WORD (lx, arg);
+ lx &= 0xf8000000;
+ arg_high = arg;
+ SET_LOW_WORD (arg_high, lx);
+ arg_low = arg - arg_high;
+ exp_high = arg_high * log10_high;
+ exp_low = arg_high * log10_low + arg_low * M_LN10;
+ return __ieee754_exp (exp_high) * __ieee754_exp (exp_low);
+}
+strong_alias (__ieee754_exp10, __exp10_finite)
diff --git a/libc/sysdeps/ieee754/dbl-64/s_logb.c b/libc/sysdeps/ieee754/dbl-64/s_logb.c
index 2382fbb41..baa35e14d 100644
--- a/libc/sysdeps/ieee754/dbl-64/s_logb.c
+++ b/libc/sysdeps/ieee754/dbl-64/s_logb.c
@@ -10,10 +10,6 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: s_logb.c,v 1.8 1995/05/10 20:47:50 jtc Exp $";
-#endif
-
/*
* double logb(x)
* IEEE 754 logb. Included to pass IEEE test suite. Not recommend.
@@ -23,20 +19,29 @@ static char rcsid[] = "$NetBSD: s_logb.c,v 1.8 1995/05/10 20:47:50 jtc Exp $";
#include <math.h>
#include <math_private.h>
-double __logb(double x)
+double
+__logb (double x)
{
- int32_t lx,ix;
- EXTRACT_WORDS(ix,lx,x);
- ix &= 0x7fffffff; /* high |x| */
- if((ix|lx)==0) return -1.0/fabs(x);
- if(ix>=0x7ff00000) return x*x;
- if((ix>>=20)==0) /* IEEE 754 logb */
- return -1022.0;
- else
- return (double) (ix-1023);
+ int32_t lx, ix, rix;
+
+ EXTRACT_WORDS (ix, lx, x);
+ ix &= 0x7fffffff; /* high |x| */
+ if ((ix | lx) == 0)
+ return -1.0 / fabs (x);
+ if (ix >= 0x7ff00000)
+ return x * x;
+ if (__builtin_expect ((rix = ix >> 20) == 0, 0))
+ {
+ /* POSIX specifies that denormal number is treated as
+ though it were normalized. */
+ int m1 = (ix == 0) ? 0 : __builtin_clz (ix);
+ int m2 = (lx == 0) ? 0 : __builtin_clz (lx);
+ int ma = (m1 == 0) ? m2 + 32 : m1;
+ return -1022.0 + (double)(11 - ma);
+ }
+ return (double) (rix - 1023);
}
weak_alias (__logb, logb)
#ifdef NO_LONG_DOUBLE
-strong_alias (__logb, __logbl)
-weak_alias (__logb, logbl)
+strong_alias (__logb, __logbl) weak_alias (__logb, logbl)
#endif
diff --git a/libc/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c b/libc/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c
index 2ad6c7ddb..474eeef36 100644
--- a/libc/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c
+++ b/libc/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c
@@ -1,5 +1,5 @@
/* Compute radix independent exponent.
- Copyright (C) 2011 Free Software Foundation, Inc.
+ Copyright (C) 2011, 2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
@@ -25,16 +25,21 @@
double
__logb (double x)
{
- int64_t ix;
+ int64_t ix, ex;
EXTRACT_WORDS64 (ix, x);
ix &= UINT64_C(0x7fffffffffffffff);
if (ix == 0)
return -1.0 / fabs (x);
- unsigned int ex = ix >> 52;
+ ex = ix >> 52;
if (ex == 0x7ff)
return x * x;
- return ex == 0 ? -1022.0 : (double) (ex - 1023);
+ if (__builtin_expect (ex == 0, 0))
+ {
+ int m = (ix == 0) ? 0 : __builtin_clzl (ix);
+ return -1022.0 + (double)(11 -m);
+ }
+ return (double) (ex - 1023);
}
weak_alias (__logb, logb)
#ifdef NO_LONG_DOUBLE
diff --git a/libc/sysdeps/ieee754/flt-32/s_logbf.c b/libc/sysdeps/ieee754/flt-32/s_logbf.c
index b6aa0f057..025c70de7 100644
--- a/libc/sysdeps/ieee754/flt-32/s_logbf.c
+++ b/libc/sysdeps/ieee754/flt-32/s_logbf.c
@@ -13,23 +13,27 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: s_logbf.c,v 1.4 1995/05/10 20:47:51 jtc Exp $";
-#endif
-
#include <math.h>
#include <math_private.h>
-float __logbf(float x)
+float
+__logbf (float x)
{
- int32_t ix;
- GET_FLOAT_WORD(ix,x);
- ix &= 0x7fffffff; /* high |x| */
- if(ix==0) return (float)-1.0/fabsf(x);
- if(ix>=0x7f800000) return x*x;
- if((ix>>=23)==0) /* IEEE 754 logb */
- return -126.0;
- else
- return (float) (ix-127);
+ int32_t ix, rix;
+
+ GET_FLOAT_WORD (ix, x);
+ ix &= 0x7fffffff; /* high |x| */
+ if (ix == 0)
+ return (float) -1.0 / fabsf (x);
+ if (ix >= 0x7f800000)
+ return x * x;
+ if (__builtin_expect ((rix = ix >> 23) == 0, 0))
+ {
+ /* POSIX specifies that denormal number is treated as
+ though it were normalized. */
+ int m = (ix == 0) ? 0 : __builtin_clz (ix);
+ return -126.0 + (float)(8 - m);
+ }
+ return (float) (rix - 127);
}
weak_alias (__logbf, logbf)
diff --git a/libc/sysdeps/ieee754/ldbl-128/e_exp10l.c b/libc/sysdeps/ieee754/ldbl-128/e_exp10l.c
new file mode 100644
index 000000000..503c1de3e
--- /dev/null
+++ b/libc/sysdeps/ieee754/ldbl-128/e_exp10l.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+#include <float.h>
+
+static const long double log10_high = 0x2.4d763776aaa2bp0L;
+static const long double log10_low = 0x5.ba95b58ae0b4c28a38a3fb3e7698p-60L;
+
+long double
+__ieee754_exp10l (long double arg)
+{
+ ieee854_long_double_shape_type u;
+ long double arg_high, arg_low;
+ long double exp_high, exp_low;
+
+ if (!__finitel (arg))
+ return __ieee754_expl (arg);
+ if (arg < LDBL_MIN_10_EXP - LDBL_DIG - 10)
+ return LDBL_MIN * LDBL_MIN;
+ else if (arg > LDBL_MAX_10_EXP + 1)
+ return LDBL_MAX * LDBL_MAX;
+
+ u.value = arg;
+ u.parts64.lsw &= 0xfe00000000000000LL;
+ arg_high = u.value;
+ arg_low = arg - arg_high;
+ exp_high = arg_high * log10_high;
+ exp_low = arg_high * log10_low + arg_low * M_LN10l;
+ return __ieee754_expl (exp_high) * __ieee754_expl (exp_low);
+}
+strong_alias (__ieee754_exp10l, __exp10l_finite)
diff --git a/libc/sysdeps/ieee754/ldbl-128/s_logbl.c b/libc/sysdeps/ieee754/ldbl-128/s_logbl.c
index 0b09b289c..cf6003e05 100644
--- a/libc/sysdeps/ieee754/ldbl-128/s_logbl.c
+++ b/libc/sysdeps/ieee754/ldbl-128/s_logbl.c
@@ -26,16 +26,27 @@ static char rcsid[] = "$NetBSD: $";
#include <math.h>
#include <math_private.h>
-long double __logbl(long double x)
+long double
+__logbl (long double x)
{
- int64_t lx,hx;
- GET_LDOUBLE_WORDS64(hx,lx,x);
- hx &= 0x7fffffffffffffffLL; /* high |x| */
- if((hx|lx)==0) return -1.0/fabs(x);
- if(hx>=0x7fff000000000000LL) return x*x;
- if((hx>>=48)==0) /* IEEE 754 logb */
- return -16382.0;
- else
- return (long double) (hx-0x3fff);
+ int64_t lx, hx, ex;
+
+ GET_LDOUBLE_WORDS64 (hx, lx, x);
+ hx &= 0x7fffffffffffffffLL; /* high |x| */
+ if ((hx | lx) == 0)
+ return -1.0 / fabs (x);
+ if (hx >= 0x7fff000000000000LL)
+ return x * x;
+ if ((ex = hx >> 48) == 0) /* IEEE 754 logb */
+ {
+ /* POSIX specifies that denormal number is treated as
+ though it were normalized. */
+ int m1 = (hx == 0) ? 0 : __builtin_clzll (hx);
+ int m2 = (lx == 0) ? 0 : __builtin_clzll (lx);
+ int ma = (m1 == 0) ? m2 + 64 : m1;
+ return -16382.0 + (long double)(15 - ma);
+ }
+ return (long double) (ex - 16383);
}
+
weak_alias (__logbl, logbl)
diff --git a/libc/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c b/libc/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c
new file mode 100644
index 000000000..b19e6c7f0
--- /dev/null
+++ b/libc/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+#include <float.h>
+
+static const long double log10_high = 0x2.4d763776aaa2cp0L;
+static const long double log10_low = -0xf.a456a4a751f4b3d75c75c04c18p-56L;
+
+long double
+__ieee754_exp10l (long double arg)
+{
+ union ibm_extended_long_double u;
+ long double arg_high, arg_low;
+ long double exp_high, exp_low;
+
+ if (!__finitel (arg))
+ return __ieee754_expl (arg);
+ if (arg < LDBL_MIN_10_EXP - LDBL_DIG - 10)
+ return LDBL_MIN * LDBL_MIN;
+ else if (arg > LDBL_MAX_10_EXP + 1)
+ return LDBL_MAX * LDBL_MAX;
+
+ u.d = arg;
+ arg_high = u.dd[0];
+ arg_low = u.dd[1];
+ exp_high = arg_high * log10_high;
+ exp_low = arg_high * log10_low + arg_low * M_LN10l;
+ return __ieee754_expl (exp_high) * __ieee754_expl (exp_low);
+}
+strong_alias (__ieee754_exp10l, __exp10l_finite)
diff --git a/libc/sysdeps/ieee754/ldbl-128ibm/s_logbl.c b/libc/sysdeps/ieee754/ldbl-128ibm/s_logbl.c
index f38b12997..678b6cad5 100644
--- a/libc/sysdeps/ieee754/ldbl-128ibm/s_logbl.c
+++ b/libc/sysdeps/ieee754/ldbl-128ibm/s_logbl.c
@@ -13,10 +13,6 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: $";
-#endif
-
/*
* long double logbl(x)
* IEEE 754 logb. Included to pass IEEE test suite. Not recommend.
@@ -27,16 +23,27 @@ static char rcsid[] = "$NetBSD: $";
#include <math_private.h>
#include <math_ldbl_opt.h>
-long double __logbl(long double x)
+long double
+__logbl (long double x)
{
- int64_t lx,hx;
- GET_LDOUBLE_WORDS64(hx,lx,x);
- hx &= 0x7fffffffffffffffLL; /* high |x| */
- if((hx|(lx&0x7fffffffffffffffLL))==0) return -1.0/fabs(x);
- if(hx>=0x7ff0000000000000LL) return x*x;
- if((hx>>=52)==0) /* IEEE 754 logb */
- return -1022.0;
- else
- return (long double) (hx-0x3ff);
+ int64_t lx, hx, rhx;
+
+ GET_LDOUBLE_WORDS64 (hx, lx, x);
+ hx &= 0x7fffffffffffffffLL; /* high |x| */
+ if ((hx | (lx & 0x7fffffffffffffffLL)) == 0)
+ return -1.0 / fabs (x);
+ if (hx >= 0x7ff0000000000000LL)
+ return x * x;
+ if (__builtin_expect ((rhx = hx >> 52) == 0, 0))
+ {
+ /* POSIX specifies that denormal number is treated as
+ though it were normalized. */
+ int m1 = (hx == 0) ? 0 : __builtin_clzll (hx);
+ int m2 = (lx == 0) ? 0 : __builtin_clzll (lx);
+ int ma = (m1 == 0) ? m2 + 64 : m1;
+ return -1022.0 + (long double)(11 - ma);
+ }
+ return (long double) (rhx - 1023);
}
+
long_double_symbol (libm, __logbl, logbl);
diff --git a/libc/sysdeps/ieee754/ldbl-96/s_logbl.c b/libc/sysdeps/ieee754/ldbl-96/s_logbl.c
index 95b644c03..d8ad4bcfc 100644
--- a/libc/sysdeps/ieee754/ldbl-96/s_logbl.c
+++ b/libc/sysdeps/ieee754/ldbl-96/s_logbl.c
@@ -14,10 +14,6 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: $";
-#endif
-
/*
* long double logbl(x)
* IEEE 754 logb. Included to pass IEEE test suite. Not recommend.
@@ -27,16 +23,27 @@ static char rcsid[] = "$NetBSD: $";
#include <math.h>
#include <math_private.h>
-long double __logbl(long double x)
+long double
+__logbl (long double x)
{
- int32_t es,lx,ix;
- GET_LDOUBLE_WORDS(es,ix,lx,x);
- es &= 0x7fff; /* exponent */
- if((es|ix|lx)==0) return -1.0/fabs(x);
- if(es==0x7fff) return x*x;
- if(es==0) /* IEEE 754 logb */
- return -16382.0;
- else
- return (long double) (es-0x3fff);
+ int32_t es, lx, ix;
+
+ GET_LDOUBLE_WORDS (es, ix, lx, x);
+ es &= 0x7fff; /* exponent */
+ if ((es | ix | lx) == 0)
+ return -1.0 / fabs (x);
+ if (es == 0x7fff)
+ return x * x;
+ if (es == 0) /* IEEE 754 logb */
+ {
+ /* POSIX specifies that denormal number is treated as
+ though it were normalized. */
+ int m1 = (ix == 0) ? 0 : __builtin_clz (ix);
+ int m2 = (lx == 0) ? 0 : __builtin_clz (lx);
+ int ma = (m1 == 0) ? m2 + 32 : m1;
+ return -16382.0 - (long double)(ma);
+ }
+ return (long double) (es - 16383);
}
+
weak_alias (__logbl, logbl)
diff --git a/libc/sysdeps/mach/bits/libc-lock.h b/libc/sysdeps/mach/bits/libc-lock.h
index 0a627e75f..110e25e96 100644
--- a/libc/sysdeps/mach/bits/libc-lock.h
+++ b/libc/sysdeps/mach/bits/libc-lock.h
@@ -1,5 +1,5 @@
/* libc-internal interface for mutex locks. Mach cthreads version.
- Copyright (C) 1996,97,98,2000,01, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1996-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -115,6 +115,9 @@ struct __libc_once
__libc_lock_unlock (ONCE_CONTROL.lock); \
} while (0)
+/* Get once control variable. */
+#define __libc_once_get(ONCE_CONTROL) ((ONCE_CONTROL).done != 0)
+
#ifdef _LIBC
/* We need portable names for some functions. E.g., when they are
used as argument to __libc_cleanup_region_start. */
diff --git a/libc/sysdeps/mach/hurd/Makefile b/libc/sysdeps/mach/hurd/Makefile
index 80749c257..107eaafb0 100644
--- a/libc/sysdeps/mach/hurd/Makefile
+++ b/libc/sysdeps/mach/hurd/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1993-2004,2009,2011,2012 Free Software Foundation, Inc.
+# Copyright (C) 1993-2012 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -133,6 +133,7 @@ rpcuserlibs := $(common-objpfx)mach/libmachuser.so \
$(common-objpfx)hurd/libhurduser.so
link-rpcuserlibs := $(rpcuserlibs:%user.so=%user-link.so)
$(common-objpfx)libc.so: $(link-rpcuserlibs)
+$(common-objpfx)linkobj/libc.so: $(link-rpcuserlibs)
rpath-dirs += mach hurd
# Make sure the `lib' pass builds the dummy shared objects so
diff --git a/libc/sysdeps/mach/hurd/accept.c b/libc/sysdeps/mach/hurd/accept.c
index 78b5c67d8..52dfdf8ba 100644
--- a/libc/sysdeps/mach/hurd/accept.c
+++ b/libc/sysdeps/mach/hurd/accept.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1992,1993,1994,1997,1999,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2012 Free Software Foundation, Inc.
+
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,72 +16,16 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
#include <sys/socket.h>
-#include <hurd.h>
-#include <hurd/fd.h>
-#include <hurd/socket.h>
/* Await a connection on socket FD.
When a connection arrives, open a new socket to communicate with it,
- set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting
+ set *ADDRARG (which is *ADDR_LEN bytes long) to the address of the connecting
peer and *ADDR_LEN to the address's actual length, and return the
new socket's descriptor, or -1 for errors. */
int
-accept (fd, addrarg, addr_len)
- int fd;
- __SOCKADDR_ARG addrarg;
- socklen_t *addr_len;
+accept (int fd, __SOCKADDR_ARG addrarg, socklen_t *addr_len)
{
- error_t err;
- socket_t new;
- addr_port_t aport;
- struct sockaddr *addr = addrarg.__sockaddr__;
- char *buf = (char *) addr;
- mach_msg_type_number_t buflen;
- int type;
-
- if (err = HURD_DPORT_USE (fd, __socket_accept (port, &new, &aport)))
- return __hurd_dfail (fd, err);
-
- if (addr != NULL)
- {
- buflen = *addr_len;
- err = __socket_whatis_address (aport, &type, &buf, &buflen);
- if (err == EOPNOTSUPP)
- /* If the protocol server can't tell us the address, just return a
- zero-length one. */
- {
- buf = (char *)addr;
- buflen = 0;
- err = 0;
- }
- }
- __mach_port_deallocate (__mach_task_self (), aport);
-
- if (err)
- {
- __mach_port_deallocate (__mach_task_self (), new);
- return __hurd_dfail (fd, err);
- }
-
- if (addr != NULL)
- {
- if (*addr_len > buflen)
- *addr_len = buflen;
-
- if (buf != (char *) addr)
- {
- memcpy (addr, buf, *addr_len);
- __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
- }
-
- if (buflen > 0)
- addr->sa_family = type;
- }
-
- return _hurd_intern_fd (new, O_IGNORE_CTTY, 1);
+ return __libc_accept4 (fd, addrarg, addr_len, 0);
}
libc_hidden_def (accept)
diff --git a/libc/sysdeps/mach/hurd/accept4.c b/libc/sysdeps/mach/hurd/accept4.c
new file mode 100644
index 000000000..eb4f95c9f
--- /dev/null
+++ b/libc/sysdeps/mach/hurd/accept4.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 1992-2012 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <fcntl-internal.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <hurd/socket.h>
+
+/* Await a connection on socket FD.
+ When a connection arrives, open a new socket to communicate with it,
+ set *ADDRARG (which is *ADDR_LEN bytes long) to the address of the connecting
+ peer and *ADDR_LEN to the address's actual length, and return the
+ new socket's descriptor, or -1 for errors. The operation can be influenced
+ by the FLAGS parameter. */
+int
+__libc_accept4 (int fd, __SOCKADDR_ARG addrarg, socklen_t *addr_len, int flags)
+{
+ error_t err;
+ socket_t new;
+ addr_port_t aport;
+ struct sockaddr *addr = addrarg.__sockaddr__;
+ char *buf = (char *) addr;
+ mach_msg_type_number_t buflen;
+ int type;
+
+ flags = sock_to_o_flags (flags);
+
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ return __hurd_fail (EINVAL);
+
+ if (err = HURD_DPORT_USE (fd, __socket_accept (port, &new, &aport)))
+ return __hurd_dfail (fd, err);
+
+ if (addr != NULL)
+ {
+ buflen = *addr_len;
+ err = __socket_whatis_address (aport, &type, &buf, &buflen);
+ if (err == EOPNOTSUPP)
+ /* If the protocol server can't tell us the address, just return a
+ zero-length one. */
+ {
+ buf = (char *)addr;
+ buflen = 0;
+ err = 0;
+ }
+ }
+ __mach_port_deallocate (__mach_task_self (), aport);
+
+ if (! err)
+ {
+ if (flags & O_NONBLOCK)
+ err = __io_set_some_openmodes (new, O_NONBLOCK);
+ /* TODO: do we need special ERR massaging after the previous call? */
+ }
+
+ if (err)
+ {
+ __mach_port_deallocate (__mach_task_self (), new);
+ return __hurd_dfail (fd, err);
+ }
+
+ if (addr != NULL)
+ {
+ if (*addr_len > buflen)
+ *addr_len = buflen;
+
+ if (buf != (char *) addr)
+ {
+ memcpy (addr, buf, *addr_len);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
+ }
+
+ if (buflen > 0)
+ addr->sa_family = type;
+ }
+
+ return _hurd_intern_fd (new, O_IGNORE_CTTY | flags, 1);
+}
+libc_hidden_def (__libc_accept4)
+weak_alias (__libc_accept4, accept4)
diff --git a/libc/sysdeps/mach/hurd/bits/fcntl.h b/libc/sysdeps/mach/hurd/bits/fcntl.h
index 4224bf18f..1d24c7399 100644
--- a/libc/sysdeps/mach/hurd/bits/fcntl.h
+++ b/libc/sysdeps/mach/hurd/bits/fcntl.h
@@ -1,6 +1,5 @@
/* O_*, F_*, FD_* bit values for GNU.
- Copyright (C) 1993,1994,1996,1997,1998,1999,2000,2001,2004,2007
- Free Software Foundation, Inc.
+ Copyright (C) 1993-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -54,7 +53,9 @@
#ifdef __USE_GNU
# define O_NOLINK 0x0040 /* No name mappings on final component. */
# define O_NOTRANS 0x0080 /* No translator on final component. */
+#endif
+#ifdef __USE_XOPEN2K8
# define O_NOFOLLOW 0x00100000 /* Produce ENOENT if file is a symlink. */
# define O_DIRECTORY 0x00200000 /* Produce ENOTDIR if not a directory. */
#endif
@@ -118,7 +119,7 @@
once the file has been opened. */
#define O_TRUNC 0x00010000 /* Truncate file to zero length. */
-#ifdef __USE_GNU
+#ifdef __USE_XOPEN2K8
# define O_CLOEXEC 0x00400000 /* Set FD_CLOEXEC. */
#endif
@@ -158,7 +159,7 @@
#define F_SETFD 2 /* Set file descriptor flags. */
#define F_GETFL 3 /* Get file status flags. */
#define F_SETFL 4 /* Set file status flags. */
-#if defined __USE_BSD || defined __USE_UNIX98
+#if defined __USE_BSD || defined __USE_UNIX98 || defined __USE_XOPEN2K8
# define F_GETOWN 5 /* Get owner (receiver of SIGIO). */
# define F_SETOWN 6 /* Set owner (receiver of SIGIO). */
#endif
@@ -166,7 +167,7 @@
#define F_SETLK 8 /* Set record locking info (non-blocking). */
#define F_SETLKW 9 /* Set record locking info (blocking). */
-#ifdef __USE_GNU
+#ifdef __USE_XOPEN2K8
# define F_DUPFD_CLOEXEC 1030 /* Duplicate, set FD_CLOEXEC on new one. */
#endif
diff --git a/libc/sysdeps/mach/hurd/bits/ioctls.h b/libc/sysdeps/mach/hurd/bits/ioctls.h
index 65f2ec1dd..c4cfce65a 100644
--- a/libc/sysdeps/mach/hurd/bits/ioctls.h
+++ b/libc/sysdeps/mach/hurd/bits/ioctls.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992,93,96,97,98,99,2001,2007 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -157,6 +157,7 @@ enum __ioctl_datum { IOC_8, IOC_16, IOC_32, IOC_64 };
_IOT_foobar is defined either in this file,
or where struct foobar is defined. */
#define _IO(g, n) _IOC (IOC_VOID, (g), (n), 0)
+#define _IOIW(g, n, t) _IOC (IOC_VOID, (g), (n), _IOC_ENCODE_TYPE (t))
#define _IOR(g, n, t) _IOC (IOC_OUT, (g), (n), _IOC_ENCODE_TYPE (t))
#define _IOW(g, n, t) _IOC (IOC_IN, (g), (n), _IOC_ENCODE_TYPE (t))
#define _IOWR(g, n, t) _IOC (IOC_INOUT, (g), (n), _IOC_ENCODE_TYPE (t))
diff --git a/libc/sysdeps/mach/hurd/bits/libc-lock.h b/libc/sysdeps/mach/hurd/bits/libc-lock.h
index af531da54..d18a10c45 100644
--- a/libc/sysdeps/mach/hurd/bits/libc-lock.h
+++ b/libc/sysdeps/mach/hurd/bits/libc-lock.h
@@ -1,5 +1,5 @@
/* libc-internal interface for mutex locks. Hurd version using Mach cthreads.
- Copyright (C) 1996,97,98,2000,01, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1996-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -187,6 +187,9 @@ struct __libc_once
__libc_lock_unlock (ONCE_CONTROL.lock); \
} while (0)
+/* Get once control variable. */
+#define __libc_once_get(ONCE_CONTROL) ((ONCE_CONTROL).done != 0)
+
#ifdef _LIBC
/* We need portable names for some functions. E.g., when they are
used as argument to __libc_cleanup_region_start. */
diff --git a/libc/sysdeps/mach/hurd/bits/posix_opt.h b/libc/sysdeps/mach/hurd/bits/posix_opt.h
index 23d32ce76..3c0830710 100644
--- a/libc/sysdeps/mach/hurd/bits/posix_opt.h
+++ b/libc/sysdeps/mach/hurd/bits/posix_opt.h
@@ -1,5 +1,5 @@
/* Define POSIX options for GNU/Hurd.
- Copyright (C) 1998,2000,2001,2002,2006,2009 Free Software Foundation, Inc.
+ Copyright (C) 1998-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -30,6 +30,9 @@
/* Processes have a saved set-user-ID and a saved set-group-ID. */
#define _POSIX_SAVED_IDS 1
+/* Priority scheduling is not supported. */
+#undef _POSIX_PRIORITY_SCHEDULING
+
/* Synchronizing file data is supported, but msync is missing. */
#undef _POSIX_SYNCHRONIZED_IO
@@ -59,6 +62,14 @@
#undef _POSIX_NO_TRUNC /* Overlong file names get error? */
#undef _POSIX_SYNC_IO /* File supports O_SYNC et al? */
+/* X/Open realtime support is not supported. */
+#undef _XOPEN_REALTIME
+
+/* X/Open thread realtime support is not supported. */
+#undef _XOPEN_REALTIME_THREADS
+
+/* XPG4.2 shared memory is not supported. */
+#undef _XOPEN_SHM
/* We do not have the POSIX threads interface. */
#define _POSIX_THREADS -1
@@ -71,6 +82,12 @@
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
#define _POSIX_THREAD_ATTR_STACKSIZE -1
#define _POSIX_THREAD_ATTR_STACKADDR -1
+#define _POSIX_THREAD_PRIO_INHERIT -1
+#define _POSIX_THREAD_PRIO_PROTECT -1
+#ifdef __USE_XOPEN2K8
+# define _POSIX_THREAD_ROBUST_PRIO_INHERIT -1
+# define _POSIX_THREAD_ROBUST_PRIO_PROTECT -1
+#endif
#define _POSIX_SEMAPHORES -1
/* Real-time signals are not yet supported. */
@@ -78,8 +95,11 @@
/* Asynchronous I/O might supported with the existing ABI. */
#define _POSIX_ASYNCHRONOUS_IO 0
+#undef _POSIX_ASYNC_IO
/* Alternative name for Unix98. */
#define _LFS_ASYNCHRONOUS_IO _POSIX_ASYNCHRONOUS_IO
+/* Support for prioritization is not available. */
+#undef _POSIX_PRIORITIZED_IO
/* The LFS support in asynchronous I/O is also available. */
#define _LFS64_ASYNCHRONOUS_IO _POSIX_ASYNCHRONOUS_IO
@@ -110,6 +130,9 @@
/* We cannot support the Timeouts option without _POSIX_THREADS. */
#define _POSIX_TIMEOUTS -1
+/* We do not support spinlocks. */
+#define _POSIX_SPIN_LOCKS -1
+
/* The `spawn' function family is supported. */
#define _POSIX_SPAWN 200809L
@@ -156,9 +179,4 @@
/* Typed memory objects are not available. */
#define _POSIX_TYPED_MEMORY_OBJECTS -1
-/* No support for priority inheritance or protection so far. */
-#define _POSIX_THREAD_PRIO_INHERIT -1
-#define _POSIX_THREAD_PRIO_PROTECT -1
-
-
#endif /* bits/posix_opt.h */
diff --git a/libc/sysdeps/mach/hurd/bits/socket.h b/libc/sysdeps/mach/hurd/bits/socket.h
new file mode 100644
index 000000000..6d53599b3
--- /dev/null
+++ b/libc/sysdeps/mach/hurd/bits/socket.h
@@ -0,0 +1,362 @@
+/* System-specific socket constants and types. Hurd version.
+ Copyright (C) 1991-2012 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef __BITS_SOCKET_H
+#define __BITS_SOCKET_H 1
+
+#ifndef _SYS_SOCKET_H
+# error "Never include <bits/socket.h> directly; use <sys/socket.h> instead."
+#endif
+
+#define __need_size_t
+#define __need_NULL
+#include <stddef.h>
+
+#include <limits.h> /* XXX Is this allowed? */
+#include <bits/types.h>
+
+/* Type for length arguments in socket calls. */
+#ifndef __socklen_t_defined
+typedef __socklen_t socklen_t;
+# define __socklen_t_defined
+#endif
+
+
+/* Types of sockets. */
+enum __socket_type
+{
+ SOCK_STREAM = 1, /* Sequenced, reliable, connection-based
+ byte streams. */
+#define SOCK_STREAM SOCK_STREAM
+ SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams
+ of fixed maximum length. */
+#define SOCK_DGRAM SOCK_DGRAM
+ SOCK_RAW = 3, /* Raw protocol interface. */
+#define SOCK_RAW SOCK_RAW
+ SOCK_RDM = 4, /* Reliably-delivered messages. */
+#define SOCK_RDM SOCK_RDM
+ SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based,
+ datagrams of fixed maximum length. */
+#define SOCK_SEQPACKET SOCK_SEQPACKET
+
+#define SOCK_MAX (SOCK_SEQPACKET + 1)
+ /* Mask which covers at least up to SOCK_MASK-1. The
+ remaining bits are used as flags. */
+#define SOCK_TYPE_MASK 0xf
+
+ /* Flags to be ORed into the type parameter of socket and socketpair and
+ used for the flags parameter of accept4. */
+
+ SOCK_CLOEXEC = 0x00400000, /* Atomically set close-on-exec flag for the
+ new descriptor(s). */
+#define SOCK_CLOEXEC SOCK_CLOEXEC
+
+ /* Changed from the O_NONBLOCK value (0x8, which is unusable for us as it is
+ conflicting with the original SOCK_* flags' values) to the Linux value
+ (04000). TODO: is there a ``better'' value? */
+ SOCK_NONBLOCK = 0x0800 /* Atomically mark descriptor(s) as
+ non-blocking. */
+#define SOCK_NONBLOCK SOCK_NONBLOCK
+};
+
+/* Protocol families. */
+#define PF_UNSPEC 0 /* Unspecified. */
+#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */
+#define PF_UNIX PF_LOCAL /* Old BSD name for PF_LOCAL. */
+#define PF_FILE PF_LOCAL /* POSIX name for PF_LOCAL. */
+#define PF_INET 2 /* IP protocol family. */
+#define PF_IMPLINK 3 /* ARPAnet IMP protocol. */
+#define PF_PUP 4 /* PUP protocols. */
+#define PF_CHAOS 5 /* MIT Chaos protocols. */
+#define PF_NS 6 /* Xerox NS protocols. */
+#define PF_ISO 7 /* ISO protocols. */
+#define PF_OSI PF_ISO
+#define PF_ECMA 8 /* ECMA protocols. */
+#define PF_DATAKIT 9 /* AT&T Datakit protocols. */
+#define PF_CCITT 10 /* CCITT protocols (X.25 et al). */
+#define PF_SNA 11 /* IBM SNA protocol. */
+#define PF_DECnet 12 /* DECnet protocols. */
+#define PF_DLI 13 /* Direct data link interface. */
+#define PF_LAT 14 /* DEC Local Area Transport protocol. */
+#define PF_HYLINK 15 /* NSC Hyperchannel protocol. */
+#define PF_APPLETALK 16 /* Don't use this. */
+#define PF_ROUTE 17 /* Internal Routing Protocol. */
+#define PF_LINK 18 /* Link layer interface. */
+#define PF_XTP 19 /* eXpress Transfer Protocol (no AF). */
+#define PF_COIP 20 /* Connection-oriented IP, aka ST II. */
+#define PF_CNT 21 /* Computer Network Technology. */
+#define PF_RTIP 22 /* Help Identify RTIP packets. **/
+#define PF_IPX 23 /* Novell Internet Protocol. */
+#define PF_SIP 24 /* Simple Internet Protocol. */
+#define PF_PIP 25 /* Help Identify PIP packets. */
+#define PF_INET6 26 /* IP version 6. */
+#define PF_MAX 27
+
+/* Address families. */
+#define AF_UNSPEC PF_UNSPEC
+#define AF_LOCAL PF_LOCAL
+#define AF_UNIX PF_UNIX
+#define AF_FILE PF_FILE
+#define AF_INET PF_INET
+#define AF_IMPLINK PF_IMPLINK
+#define AF_PUP PF_PUP
+#define AF_CHAOS PF_CHAOS
+#define AF_NS PF_NS
+#define AF_ISO PF_ISO
+#define AF_OSI PF_OSI
+#define AF_ECMA PF_ECMA
+#define AF_DATAKIT PF_DATAKIT
+#define AF_CCITT PF_CCITT
+#define AF_SNA PF_SNA
+#define AF_DECnet PF_DECnet
+#define AF_DLI PF_DLI
+#define AF_LAT PF_LAT
+#define AF_HYLINK PF_HYLINK
+#define AF_APPLETALK PF_APPLETALK
+#define AF_ROUTE PF_ROUTE
+#define AF_LINK PF_LINK
+#define pseudo_AF_XTP PF_XTP
+#define AF_COIP PF_COIP
+#define AF_CNT PF_CNT
+#define pseudo_AF_RTIP PF_RTIP
+#define AF_IPX PF_IPX
+#define AF_SIP PF_SIP
+#define pseudo_AF_PIP PF_PIP
+#define AF_INET6 PF_INET6
+#define AF_MAX PF_MAX
+
+/* Maximum queue length specifiable by listen. */
+#define SOMAXCONN 128 /* 5 on the origional 4.4 BSD. */
+
+/* Get the definition of the macro to define the common sockaddr members. */
+#include <bits/sockaddr.h>
+
+/* Structure describing a generic socket address. */
+struct sockaddr
+ {
+ __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
+ char sa_data[14]; /* Address data. */
+ };
+
+
+/* Structure large enough to hold any socket address (with the historical
+ exception of AF_UNIX). We reserve 128 bytes. */
+#if ULONG_MAX > 0xffffffff
+# define __ss_aligntype __uint64_t
+#else
+# define __ss_aligntype __uint32_t
+#endif
+#define _SS_SIZE 128
+#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype)))
+
+struct sockaddr_storage
+ {
+ __SOCKADDR_COMMON (ss_); /* Address family, etc. */
+ __ss_aligntype __ss_align; /* Force desired alignment. */
+ char __ss_padding[_SS_PADSIZE];
+ };
+
+
+/* Bits in the FLAGS argument to `send', `recv', et al. */
+enum
+ {
+ MSG_OOB = 0x01, /* Process out-of-band data. */
+#define MSG_OOB MSG_OOB
+ MSG_PEEK = 0x02, /* Peek at incoming messages. */
+#define MSG_PEEK MSG_PEEK
+ MSG_DONTROUTE = 0x04, /* Don't use local routing. */
+#define MSG_DONTROUTE MSG_DONTROUTE
+ MSG_EOR = 0x08, /* Data completes record. */
+#define MSG_EOR MSG_EOR
+ MSG_TRUNC = 0x10, /* Data discarded before delivery. */
+#define MSG_TRUNC MSG_TRUNC
+ MSG_CTRUNC = 0x20, /* Control data lost before delivery. */
+#define MSG_CTRUNC MSG_CTRUNC
+ MSG_WAITALL = 0x40, /* Wait for full request or error. */
+#define MSG_WAITALL MSG_WAITALL
+ MSG_DONTWAIT = 0x80, /* This message should be nonblocking. */
+#define MSG_DONTWAIT MSG_DONTWAIT
+ MSG_NOSIGNAL = 0x0400 /* Do not generate SIGPIPE on EPIPE. */
+#define MSG_NOSIGNAL MSG_NOSIGNAL
+ };
+
+
+/* Structure describing messages sent by
+ `sendmsg' and received by `recvmsg'. */
+struct msghdr
+ {
+ void *msg_name; /* Address to send to/receive from. */
+ socklen_t msg_namelen; /* Length of address data. */
+
+ struct iovec *msg_iov; /* Vector of data to send/receive into. */
+ int msg_iovlen; /* Number of elements in the vector. */
+
+ void *msg_control; /* Ancillary data (eg BSD filedesc passing). */
+ socklen_t msg_controllen; /* Ancillary data buffer length. */
+
+ int msg_flags; /* Flags in received message. */
+ };
+
+/* Structure used for storage of ancillary data object information. */
+struct cmsghdr
+ {
+ socklen_t cmsg_len; /* Length of data in cmsg_data plus length
+ of cmsghdr structure. */
+ int cmsg_level; /* Originating protocol. */
+ int cmsg_type; /* Protocol specific type. */
+#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L
+ __extension__ unsigned char __cmsg_data __flexarr; /* Ancillary data. */
+#endif
+ };
+
+/* Ancillary data object manipulation macros. */
+#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L
+# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data)
+#else
+# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1))
+#endif
+
+#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg)
+
+#define CMSG_FIRSTHDR(mhdr) \
+ ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) \
+ ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL)
+
+#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \
+ & (size_t) ~(sizeof (size_t) - 1))
+#define CMSG_SPACE(len) (CMSG_ALIGN (len) \
+ + CMSG_ALIGN (sizeof (struct cmsghdr)))
+#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
+
+extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
+ struct cmsghdr *__cmsg) __THROW;
+#ifdef __USE_EXTERN_INLINES
+# ifndef _EXTERN_INLINE
+# define _EXTERN_INLINE __extern_inline
+# endif
+_EXTERN_INLINE struct cmsghdr *
+__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg))
+{
+ if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr))
+ /* The kernel header does this so there may be a reason. */
+ return NULL;
+
+ __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
+ + CMSG_ALIGN (__cmsg->cmsg_len));
+ if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control
+ + __mhdr->msg_controllen)
+ || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)
+ > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen)))
+ /* No more entries. */
+ return NULL;
+ return __cmsg;
+}
+#endif /* Use `extern inline'. */
+
+/* Socket level message types. */
+enum
+ {
+ SCM_RIGHTS = 0x01, /* Access rights (array of int). */
+#define SCM_RIGHTS SCM_RIGHTS
+ SCM_TIMESTAMP = 0x02, /* Timestamp (struct timeval). */
+#define SCM_TIMESTAMP SCM_TIMESTAMP
+ SCM_CREDS = 0x03 /* Process creds (struct cmsgcred). */
+#define SCM_CREDS SCM_CREDS
+ };
+
+/* Unfortunately, BSD practice dictates this structure be of fixed size.
+ If there are more than CMGROUP_MAX groups, the list is truncated.
+ (On GNU systems, the `cmcred_euid' field is just the first in the
+ list of effective UIDs.) */
+#define CMGROUP_MAX 16
+
+/* Structure delivered by SCM_CREDS. This describes the identity of the
+ sender of the data simultaneously received on the socket. By BSD
+ convention, this is included only when a sender on a AF_LOCAL socket
+ sends cmsg data of this type and size; the sender's structure is
+ ignored, and the system fills in the various IDs of the sender process. */
+struct cmsgcred
+ {
+ __pid_t cmcred_pid;
+ __uid_t cmcred_uid;
+ __uid_t cmcred_euid;
+ __gid_t cmcred_gid;
+ int cmcred_ngroups;
+ __gid_t cmcred_groups[CMGROUP_MAX];
+ };
+
+/* Protocol number used to manipulate socket-level options
+ with `getsockopt' and `setsockopt'. */
+#define SOL_SOCKET 0xffff
+
+/* Socket-level options for `getsockopt' and `setsockopt'. */
+enum
+ {
+ SO_DEBUG = 0x0001, /* Record debugging information. */
+#define SO_DEBUG SO_DEBUG
+ SO_ACCEPTCONN = 0x0002, /* Accept connections on socket. */
+#define SO_ACCEPTCONN SO_ACCEPTCONN
+ SO_REUSEADDR = 0x0004, /* Allow reuse of local addresses. */
+#define SO_REUSEADDR SO_REUSEADDR
+ SO_KEEPALIVE = 0x0008, /* Keep connections alive and send
+ SIGPIPE when they die. */
+#define SO_KEEPALIVE SO_KEEPALIVE
+ SO_DONTROUTE = 0x0010, /* Don't do local routing. */
+#define SO_DONTROUTE SO_DONTROUTE
+ SO_BROADCAST = 0x0020, /* Allow transmission of
+ broadcast messages. */
+#define SO_BROADCAST SO_BROADCAST
+ SO_USELOOPBACK = 0x0040, /* Use the software loopback to avoid
+ hardware use when possible. */
+#define SO_USELOOPBACK SO_USELOOPBACK
+ SO_LINGER = 0x0080, /* Block on close of a reliable
+ socket to transmit pending data. */
+#define SO_LINGER SO_LINGER
+ SO_OOBINLINE = 0x0100, /* Receive out-of-band data in-band. */
+#define SO_OOBINLINE SO_OOBINLINE
+ SO_REUSEPORT = 0x0200, /* Allow local address and port reuse. */
+#define SO_REUSEPORT SO_REUSEPORT
+ SO_SNDBUF = 0x1001, /* Send buffer size. */
+#define SO_SNDBUF SO_SNDBUF
+ SO_RCVBUF = 0x1002, /* Receive buffer. */
+#define SO_RCVBUF SO_RCVBUF
+ SO_SNDLOWAT = 0x1003, /* Send low-water mark. */
+#define SO_SNDLOWAT SO_SNDLOWAT
+ SO_RCVLOWAT = 0x1004, /* Receive low-water mark. */
+#define SO_RCVLOWAT SO_RCVLOWAT
+ SO_SNDTIMEO = 0x1005, /* Send timeout. */
+#define SO_SNDTIMEO SO_SNDTIMEO
+ SO_RCVTIMEO = 0x1006, /* Receive timeout. */
+#define SO_RCVTIMEO SO_RCVTIMEO
+ SO_ERROR = 0x1007, /* Get and clear error status. */
+#define SO_ERROR SO_ERROR
+ SO_STYLE = 0x1008, /* Get socket connection style. */
+#define SO_STYLE SO_STYLE
+ SO_TYPE = SO_STYLE /* Compatible name for SO_STYLE. */
+#define SO_TYPE SO_TYPE
+ };
+
+/* Structure used to manipulate the SO_LINGER option. */
+struct linger
+ {
+ int l_onoff; /* Nonzero to linger on close. */
+ int l_linger; /* Time to linger. */
+ };
+
+#endif /* bits/socket.h */
diff --git a/libc/sysdeps/mach/hurd/bits/stat.h b/libc/sysdeps/mach/hurd/bits/stat.h
index 15fcda117..e6ffda892 100644
--- a/libc/sysdeps/mach/hurd/bits/stat.h
+++ b/libc/sysdeps/mach/hurd/bits/stat.h
@@ -1,5 +1,4 @@
-/* Copyright (C) 1992-1994,1996,1997,1999,2000,2005,2010
- Free Software Foundation, Inc.
+/* Copyright (C) 1992-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -58,12 +57,27 @@ struct stat
__off64_t st_size; /* Size in bytes. */
#endif
- __time_t st_atime; /* Access time, seconds */
- unsigned long int st_atime_usec; /* and microseconds. */
- __time_t st_mtime; /* Modification time, seconds */
- unsigned long int st_mtime_usec; /* and microseconds. */
- __time_t st_ctime; /* Status change time, seconds */
- unsigned long int st_ctime_usec; /* and microseconds. */
+#if defined __USE_MISC || defined __USE_XOPEN2K8
+ /* Nanosecond resolution timestamps are stored in a format
+ equivalent to 'struct timespec'. This is the type used
+ whenever possible but the Unix namespace rules do not allow the
+ identifier 'timespec' to appear in the <sys/stat.h> header.
+ Therefore we have to handle the use of this header in strictly
+ standard-compliant sources special. */
+ struct timespec st_atim; /* Time of last access. */
+ struct timespec st_mtim; /* Time of last modification. */
+ struct timespec st_ctim; /* Time of last status change. */
+# define st_atime st_atim.tv_sec /* Backward compatibility. */
+# define st_mtime st_mtim.tv_sec
+# define st_ctime st_ctim.tv_sec
+#else
+ __time_t st_atime; /* Time of last access. */
+ unsigned long int st_atimensec; /* Nscecs of last access. */
+ __time_t st_mtime; /* Time of last modification. */
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
+ __time_t st_ctime; /* Time of last status change. */
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
+#endif
__blksize_t st_blksize; /* Optimal size for I/O. */
@@ -107,12 +121,24 @@ struct stat64
__off64_t st_size; /* Size in bytes. */
- __time_t st_atime; /* Access time, seconds */
- unsigned long int st_atime_usec; /* and microseconds. */
- __time_t st_mtime; /* Modification time, seconds */
- unsigned long int st_mtime_usec; /* and microseconds. */
- __time_t st_ctime; /* Status change time, seconds */
- unsigned long int st_ctime_usec; /* and microseconds. */
+#if defined __USE_MISC || defined __USE_XOPEN2K8
+ /* Nanosecond resolution timestamps are stored in a format
+ equivalent to 'struct timespec'. This is the type used
+ whenever possible but the Unix namespace rules do not allow the
+ identifier 'timespec' to appear in the <sys/stat.h> header.
+ Therefore we have to handle the use of this header in strictly
+ standard-compliant sources special. */
+ struct timespec st_atim; /* Time of last access. */
+ struct timespec st_mtim; /* Time of last modification. */
+ struct timespec st_ctim; /* Time of last status change. */
+#else
+ __time_t st_atime; /* Time of last access. */
+ unsigned long int st_atimensec; /* Nscecs of last access. */
+ __time_t st_mtime; /* Time of last modification. */
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
+ __time_t st_ctime; /* Time of last status change. */
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
+#endif
__blksize_t st_blksize; /* Optimal size for I/O. */
@@ -130,7 +156,10 @@ struct stat64
};
#endif
-#define _STATBUF_ST_BLKSIZE /* Tell code we have this member. */
+/* Tell code we have these members. */
+#define _STATBUF_ST_BLKSIZE
+/* Nanosecond resolution time values are supported. */
+#define _STATBUF_ST_NSEC
/* Encoding of the file mode. */
diff --git a/libc/sysdeps/mach/hurd/brk.c b/libc/sysdeps/mach/hurd/brk.c
index 275d7bea3..1900277d1 100644
--- a/libc/sysdeps/mach/hurd/brk.c
+++ b/libc/sysdeps/mach/hurd/brk.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,92,93,94,95,96,97,99,2000 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -63,7 +63,7 @@ weak_alias (__brk, brk)
int
_hurd_set_brk (vm_address_t addr)
{
- error_t err;
+ error_t err = 0;
vm_address_t pagend = round_page (addr);
vm_address_t pagebrk = round_page (_hurd_brk);
long int rlimit;
@@ -100,8 +100,22 @@ _hurd_set_brk (vm_address_t addr)
if (pagend > _hurd_data_end)
{
+ vm_address_t alloc_start = _hurd_data_end;
+
/* We didn't allocate enough space! Hopefully we can get some more! */
- err = __vm_allocate (__mach_task_self (), &pagebrk, pagend - pagebrk, 0);
+
+ if (_hurd_data_end > pagebrk)
+ /* First finish allocation. */
+ err = __vm_protect (__mach_task_self (), pagebrk,
+ alloc_start - pagebrk, 0,
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+ if (! err)
+ _hurd_brk = alloc_start;
+
+ if (! err)
+ err = __vm_allocate (__mach_task_self (), &alloc_start,
+ pagend - alloc_start, 0);
+
if (! err)
_hurd_data_end = pagend;
}
diff --git a/libc/sysdeps/mach/hurd/chroot.c b/libc/sysdeps/mach/hurd/chroot.c
index 1a6b1e44d..95bee3317 100644
--- a/libc/sysdeps/mach/hurd/chroot.c
+++ b/libc/sysdeps/mach/hurd/chroot.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,92,93,94,95,97,99,2001 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -37,6 +37,9 @@ chroot (const char *path)
len = strlen (path);
if (len >= 2 && path[len - 2] == '/' && path[len - 1] == '.')
lookup = path;
+ else if (len == 0)
+ /* Special-case empty file name according to POSIX. */
+ return __hurd_fail (ENOENT);
else
{
char *n = alloca (len + 3);
diff --git a/libc/sysdeps/mach/hurd/configure b/libc/sysdeps/mach/hurd/configure
index 37ac6771a..3c90a665a 100755
--- a/libc/sysdeps/mach/hurd/configure
+++ b/libc/sysdeps/mach/hurd/configure
@@ -130,11 +130,6 @@ $as_echo "#define NO_HIDDEN 1" >>confdefs.h
# existing system library, because we are the only system library.
inhibit_glue=yes
-if test "x$prefix" != x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --prefix= (empty) is required for GNU/Hurd to work normally" >&5
-$as_echo "$as_me: WARNING: --prefix= (empty) is required for GNU/Hurd to work normally" >&2;}
-fi
-
case "$machine" in
i386*)
# The default oldest ABI is 2.2.6.
diff --git a/libc/sysdeps/mach/hurd/configure.in b/libc/sysdeps/mach/hurd/configure.in
index 87c07c11d..622014226 100644
--- a/libc/sysdeps/mach/hurd/configure.in
+++ b/libc/sysdeps/mach/hurd/configure.in
@@ -10,10 +10,6 @@ AC_DEFINE([NO_HIDDEN])
# existing system library, because we are the only system library.
inhibit_glue=yes
-if test "x$prefix" != x; then
- AC_MSG_WARN([--prefix= (empty) is required for GNU/Hurd to work normally])
-fi
-
case "$machine" in
i386*)
# The default oldest ABI is 2.2.6.
diff --git a/libc/sysdeps/mach/hurd/dirfd.c b/libc/sysdeps/mach/hurd/dirfd.c
index 587ae7b2f..42dbc7883 100644
--- a/libc/sysdeps/mach/hurd/dirfd.c
+++ b/libc/sysdeps/mach/hurd/dirfd.c
@@ -1,5 +1,5 @@
/* dirfd -- Return the file descriptor used by a DIR stream. Hurd version.
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1995-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,6 +25,8 @@ int
dirfd (DIR *dirp)
{
int fd;
+
+ HURD_CRITICAL_BEGIN;
__mutex_lock (&_hurd_dtable_lock);
for (fd = 0; fd < _hurd_dtablesize; ++fd)
if (_hurd_dtable[fd] == dirp->__fd)
@@ -35,6 +37,7 @@ dirfd (DIR *dirp)
fd = -1;
}
__mutex_unlock (&_hurd_dtable_lock);
+ HURD_CRITICAL_END;
return fd;
}
diff --git a/libc/sysdeps/mach/hurd/dl-sysdep.c b/libc/sysdeps/mach/hurd/dl-sysdep.c
index d928cd247..13b001043 100644
--- a/libc/sysdeps/mach/hurd/dl-sysdep.c
+++ b/libc/sysdeps/mach/hurd/dl-sysdep.c
@@ -1,6 +1,5 @@
/* Operating system support for run-time dynamic linker. Hurd version.
- Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2010
- Free Software Foundation, Inc.
+ Copyright (C) 1995-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,6 +16,10 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* In the static library, this is all handled by dl-support.c
+ or by the vanilla definitions in the rest of the C library. */
+#ifdef SHARED
+
#include <hurd.h>
#include <link.h>
#include <unistd.h>
@@ -315,7 +318,7 @@ open_file (const char *file_name, int flags,
return MACH_PORT_NULL;
}
- assert (!(flags & ~O_READ));
+ assert (!(flags & ~(O_READ | O_CLOEXEC)));
startdir = _dl_hurd_data->portarray[file_name[0] == '/' ?
INIT_PORT_CRDIR : INIT_PORT_CWDIR];
@@ -668,3 +671,5 @@ _dl_init_first (int argc, ...)
{
/* This no-op definition only gets used if libc is not linked in. */
}
+
+#endif /* SHARED */
diff --git a/libc/sysdeps/mach/hurd/dl-sysdep.h b/libc/sysdeps/mach/hurd/dl-sysdep.h
index 671b24183..c64a39d92 100644
--- a/libc/sysdeps/mach/hurd/dl-sysdep.h
+++ b/libc/sysdeps/mach/hurd/dl-sysdep.h
@@ -1,5 +1,5 @@
/* System-specific settings for dynamic linker code. Hurd version.
- Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -24,7 +24,8 @@
#define RTLD_PRIVATE_ERRNO 0
#ifdef SHARED
-/* _dl_argv cannot be attribute_relro, because the stack-switching
+/* _dl_argv and __libc_stack_end cannot be attribute_relro, because the stack-switching
libc initializer for using cthreads might write into it. */
# define DL_ARGV_NOT_RELRO 1
+# define LIBC_STACK_END_NOT_RELRO 1
#endif
diff --git a/libc/sysdeps/mach/hurd/dup2.c b/libc/sysdeps/mach/hurd/dup2.c
index d2329c936..b697a90ec 100644
--- a/libc/sysdeps/mach/hurd/dup2.c
+++ b/libc/sysdeps/mach/hurd/dup2.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991, 92, 93, 94, 95, 97, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2012 Free Software Foundation, Inc.
+
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,119 +16,20 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
-#include <fcntl.h>
#include <unistd.h>
-#include <hurd.h>
-#include <hurd/fd.h>
/* Duplicate FD to FD2, closing the old FD2 and making FD2 be
open on the same file as FD is. Return FD2 or -1. */
int
-__dup2 (fd, fd2)
- int fd;
- int fd2;
+__dup2 (int fd, int fd2)
{
- struct hurd_fd *d;
-
- /* Extract the ports and flags from FD. */
- d = _hurd_fd_get (fd);
- if (d == NULL)
- {
- errno = EBADF;
- return -1;
- }
-
- HURD_CRITICAL_BEGIN;
-
- __spin_lock (&d->port.lock);
- if (d->port.port == MACH_PORT_NULL)
- {
- __spin_unlock (&d->port.lock);
- errno = EBADF;
- fd2 = -1;
- }
- else if (fd2 == fd)
- /* FD is valid and FD2 is already the same; just return it. */
- __spin_unlock (&d->port.lock);
- else
- {
- struct hurd_userlink ulink, ctty_ulink;
- int flags = d->flags;
- io_t ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
- io_t port = _hurd_port_locked_get (&d->port, &ulink); /* Unlocks D. */
-
- if (fd2 < 0)
- {
- errno = EBADF;
- fd2 = -1;
- }
- else
- {
- /* Get a hold of the destination descriptor. */
- struct hurd_fd *d2;
-
- if (fd2 >= _hurd_dtablesize)
- {
- /* The table is not large enough to hold the destination
- descriptor. Enlarge it as necessary to allocate this
- descriptor. */
- __mutex_unlock (&_hurd_dtable_lock);
- /* We still hold FD1's lock, but this is safe because
- _hurd_alloc_fd will only examine the cells starting
- at FD2. */
- d2 = _hurd_alloc_fd (NULL, fd2);
- if (d2)
- __spin_unlock (&d2->port.lock);
- __mutex_lock (&_hurd_dtable_lock);
- }
- else
- {
- d2 = _hurd_dtable[fd2];
- if (d2 == NULL)
- {
- /* Must allocate a new one. We don't initialize the port
- cells with this call so that if it fails (out of
- memory), we will not have already added user
- references for the ports, which we would then have to
- deallocate. */
- d2 = _hurd_dtable[fd2] = _hurd_new_fd (MACH_PORT_NULL,
- MACH_PORT_NULL);
- }
- }
-
- if (d2 == NULL)
- {
- fd2 = -1;
- if (errno == EINVAL)
- errno = EBADF; /* POSIX.1-1990 6.2.1.2 ll 54-55. */
- }
- else
- {
- /* Give the ports each a user ref for the new descriptor. */
- __mach_port_mod_refs (__mach_task_self (), port,
- MACH_PORT_RIGHT_SEND, 1);
- if (ctty != MACH_PORT_NULL)
- __mach_port_mod_refs (__mach_task_self (), ctty,
- MACH_PORT_RIGHT_SEND, 1);
-
- /* Install the ports and flags in the new descriptor slot. */
- __spin_lock (&d2->port.lock);
- d2->flags = flags & ~FD_CLOEXEC; /* Dup clears FD_CLOEXEC. */
- _hurd_port_set (&d2->ctty, ctty);
- _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */
- }
- }
- __mutex_unlock (&_hurd_dtable_lock);
-
- _hurd_port_free (&d->port, &ulink, port);
- if (ctty != MACH_PORT_NULL)
- _hurd_port_free (&d->ctty, &ctty_ulink, port);
- }
+ int flags = 0;
- HURD_CRITICAL_END;
+ if (fd2 == fd)
+ /* See the comment in dup3. */
+ flags = -1;
- return fd2;
+ return __dup3 (fd, fd2, flags);
}
libc_hidden_def (__dup2)
weak_alias (__dup2, dup2)
diff --git a/libc/sysdeps/mach/hurd/dup3.c b/libc/sysdeps/mach/hurd/dup3.c
new file mode 100644
index 000000000..22318705d
--- /dev/null
+++ b/libc/sysdeps/mach/hurd/dup3.c
@@ -0,0 +1,139 @@
+/* Duplicate a file descriptor to a given number, with flags. Hurd version.
+ Copyright (C) 1991-2012 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Duplicate FD to FD2, closing the old FD2 and making FD2 be
+ open on the same file as FD is, and setting FD2's flags according to FLAGS.
+ Return FD2 or -1. */
+int
+__dup3 (int fd, int fd2, int flags)
+{
+ struct hurd_fd *d;
+
+ /* Both passing flags different from O_CLOEXEC and FD2 being the same as FD
+ are invalid. */
+ if ((flags & ~O_CLOEXEC
+ || fd2 == fd)
+ /* ... with the exception in case that dup2 behavior is requested: if FD
+ is valid and FD2 is already the same then just return it. */
+ && ! (flags == -1
+ && fd2 == fd))
+ return __hurd_fail (EINVAL);
+
+ /* Extract the ports and flags from FD. */
+ d = _hurd_fd_get (fd);
+ if (d == NULL)
+ return __hurd_fail (EBADF);
+
+ HURD_CRITICAL_BEGIN;
+
+ __spin_lock (&d->port.lock);
+ if (d->port.port == MACH_PORT_NULL)
+ {
+ __spin_unlock (&d->port.lock);
+ fd2 = __hurd_fail (EBADF);
+ }
+ else if (fd2 == fd)
+ __spin_unlock (&d->port.lock);
+ else
+ {
+ struct hurd_userlink ulink, ctty_ulink;
+ int d_flags = d->flags;
+ io_t ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
+ io_t port = _hurd_port_locked_get (&d->port, &ulink); /* Unlocks D. */
+
+ if (fd2 < 0)
+ fd2 = __hurd_fail (EBADF);
+ else
+ {
+ /* Get a hold of the destination descriptor. */
+ struct hurd_fd *d2;
+
+ __mutex_lock (&_hurd_dtable_lock);
+
+ if (fd2 >= _hurd_dtablesize)
+ {
+ /* The table is not large enough to hold the destination
+ descriptor. Enlarge it as necessary to allocate this
+ descriptor. */
+ __mutex_unlock (&_hurd_dtable_lock);
+ d2 = _hurd_alloc_fd (NULL, fd2);
+ if (d2)
+ __spin_unlock (&d2->port.lock);
+ __mutex_lock (&_hurd_dtable_lock);
+ }
+ else
+ {
+ d2 = _hurd_dtable[fd2];
+ if (d2 == NULL)
+ {
+ /* Must allocate a new one. We don't initialize the port
+ cells with this call so that if it fails (out of
+ memory), we will not have already added user
+ references for the ports, which we would then have to
+ deallocate. */
+ d2 = _hurd_dtable[fd2] = _hurd_new_fd (MACH_PORT_NULL,
+ MACH_PORT_NULL);
+ }
+ }
+ __mutex_unlock (&_hurd_dtable_lock);
+
+ if (d2 == NULL)
+ {
+ fd2 = -1;
+ if (errno == EINVAL)
+ errno = EBADF; /* POSIX.1-1990 6.2.1.2 ll 54-55. */
+ }
+ else
+ {
+ /* Give the ports each a user ref for the new descriptor. */
+ __mach_port_mod_refs (__mach_task_self (), port,
+ MACH_PORT_RIGHT_SEND, 1);
+ if (ctty != MACH_PORT_NULL)
+ __mach_port_mod_refs (__mach_task_self (), ctty,
+ MACH_PORT_RIGHT_SEND, 1);
+
+ /* Install the ports and flags in the new descriptor slot. */
+ __spin_lock (&d2->port.lock);
+ if (flags & O_CLOEXEC)
+ d2->flags = d_flags | FD_CLOEXEC;
+ else
+ /* dup clears FD_CLOEXEC. */
+ d2->flags = d_flags & ~FD_CLOEXEC;
+ _hurd_port_set (&d2->ctty, ctty);
+ _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */
+ }
+ }
+
+ _hurd_port_free (&d->port, &ulink, port);
+ if (ctty != MACH_PORT_NULL)
+ _hurd_port_free (&d->ctty, &ctty_ulink, port);
+ }
+
+ HURD_CRITICAL_END;
+
+ return fd2;
+}
+libc_hidden_def (__dup3)
+weak_alias (__dup3, dup3)
diff --git a/libc/sysdeps/mach/hurd/i386/Makefile b/libc/sysdeps/mach/hurd/i386/Makefile
index 0eef17e8f..5f988097c 100644
--- a/libc/sysdeps/mach/hurd/i386/Makefile
+++ b/libc/sysdeps/mach/hurd/i386/Makefile
@@ -2,3 +2,7 @@ ifeq ($(subdir),misc)
sysdep_routines += ioperm
sysdep_headers += sys/io.h
endif
+
+ifeq ($(subdir),debug)
+gen-as-const-headers += signal-defines.sym
+endif
diff --git a/libc/sysdeps/mach/hurd/i386/____longjmp_chk.S b/libc/sysdeps/mach/hurd/i386/____longjmp_chk.S
new file mode 100644
index 000000000..f499fbd1e
--- /dev/null
+++ b/libc/sysdeps/mach/hurd/i386/____longjmp_chk.S
@@ -0,0 +1,107 @@
+/* Copyright (C) 2001-2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <asm-syntax.h>
+
+#include <signal-defines.h>
+/* #include <signal.h> */
+#define SS_ONSTACK 1
+
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+ .type longjmp_msg,@object
+longjmp_msg:
+ .string "longjmp causes uninitialized stack frame"
+ .size longjmp_msg, .-longjmp_msg
+
+
+#ifdef PIC
+# define CALL_FAIL movl %ebx, %ecx; /* TODO: what's this mov good for? */ \
+ cfi_register(%ebx,%ecx); \
+ LOAD_PIC_REG (bx); \
+ leal longjmp_msg@GOTOFF(%ebx), %eax; \
+ call HIDDEN_JUMPTARGET(__fortify_fail)
+#else
+# define CALL_FAIL movl $longjmp_msg, %eax; \
+ call HIDDEN_JUMPTARGET(__fortify_fail)
+#endif
+
+
+ .text
+ENTRY (____longjmp_chk)
+ movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */
+
+ /* Save the return address now. */
+ movl (JB_PC*4)(%ecx), %edx
+ /* Get the stack pointer. */
+ movl (JB_SP*4)(%ecx), %edi
+ cfi_undefined(%edi)
+ PTR_DEMANGLE (%edx)
+ PTR_DEMANGLE (%edi)
+
+ cmpl %edi, %esp
+ /* Jumping to a higher-address frame is always allowed. */
+ jbe .Lok
+
+ /* Passing here, we're either about to do something invalid, or we're
+ executing on an alternative signal stack. */
+
+ /* TODO: need locking? */
+ /* struct hurd_sigstate * _hurd_self_sigstate (void) */
+ call _hurd_self_sigstate
+ /* TODO: %eax and %eax->sigaltstack are always valid? */
+
+ testl $SS_ONSTACK, (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%eax)
+ /* Fail if SS_ONSTACK is not set. */
+ jz .Lfail
+
+ movl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%eax), %ebx
+ addl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%eax), %ebx
+ subl %edi, %ebx
+ cmpl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%eax), %ebx
+ /* TODO: comment this calculation. */
+ jae .Lok
+
+.Lfail: CALL_FAIL
+
+.Lok: /* We add unwind information for the target here. */
+ cfi_def_cfa(%ecx, 0)
+ cfi_register(%eip, %edx)
+ cfi_register(%esp, %edi)
+ cfi_offset(%ebx, JB_BX*4)
+ cfi_offset(%esi, JB_SI*4)
+ cfi_offset(%edi, JB_DI*4)
+ cfi_offset(%ebp, JB_BP*4)
+
+ movl 8(%esp), %eax /* Second argument is return value. */
+ movl %edi, %esp
+
+ /* Restore registers. */
+ movl (JB_BX*4)(%ecx), %ebx
+ movl (JB_SI*4)(%ecx), %esi
+ movl (JB_DI*4)(%ecx), %edi
+ movl (JB_BP*4)(%ecx), %ebp
+ cfi_restore(%ebx)
+ cfi_restore(%esi)
+ cfi_restore(%edi)
+ cfi_restore(%ebp)
+
+ /* Jump to saved PC. */
+ jmp *%edx
+END (____longjmp_chk)
diff --git a/libc/sysdeps/mach/hurd/i386/init-first.c b/libc/sysdeps/mach/hurd/i386/init-first.c
index 4785e8dbe..fa4e3d9f6 100644
--- a/libc/sysdeps/mach/hurd/i386/init-first.c
+++ b/libc/sysdeps/mach/hurd/i386/init-first.c
@@ -122,7 +122,7 @@ init1 (int argc, char *arg0, ...)
{
#ifndef SHARED
/* We may need to see our own phdrs, e.g. for TLS setup.
- Try the usual kludge to find the headers without help from
+ Try the usual kludge to find the headers without help from
the exec server. */
extern const void _start;
const ElfW(Ehdr) *const ehdr = &_start;
@@ -214,6 +214,8 @@ init (int *data)
void switch_stacks (void);
+ __libc_stack_end = newsp;
+
/* Copy per-thread variables from that temporary
area onto the new cthread stack. */
memcpy (__hurd_threadvar_location_from_sp (0, newsp),
@@ -225,7 +227,7 @@ init (int *data)
#ifdef SHARED
/* And readjust the dynamic linker's idea of where the argument
- vector lives. */
+ vector lives. */
assert (_dl_argv == argv);
_dl_argv = (void *) (newsp + 1);
#endif
@@ -244,9 +246,16 @@ init (int *data)
/* Push the user code address on the top of the new stack. It will
be the return address for `init1'; we will jump there with NEWSP
as the stack pointer. */
- *--newsp = data[-1];
- ((void **) data)[-1] = switch_stacks;
- /* Force NEWSP into %ecx and &init1 into %eax, which are not restored
+ /* The following expression would typically be written as
+ ``__builtin_return_address (0)''. But, for example, GCC 4.4.6 doesn't
+ recognize that this read operation may alias the following write
+ operation, and thus is free to reorder the two, clobbering the
+ original return address. */
+ *--newsp = *((int *) __builtin_frame_address (0) + 1);
+ /* GCC 4.4.6 also wants us to force loading *NEWSP already here. */
+ asm volatile ("# %0" : : "X" (*newsp));
+ *((void **) __builtin_frame_address (0) + 1) = &switch_stacks;
+ /* Force NEWSP into %eax and &init1 into %ecx, which are not restored
by function return. */
asm volatile ("# a %0 c %1" : : "a" (newsp), "c" (&init1));
}
@@ -273,8 +282,15 @@ init (int *data)
/* The argument data is just above the stack frame we will unwind by
returning. Mutate our own return address to run the code below. */
- usercode = data[-1];
- data[-1] = (int) &call_init1;
+ /* The following expression would typically be written as
+ ``__builtin_return_address (0)''. But, for example, GCC 4.4.6 doesn't
+ recognize that this read operation may alias the following write
+ operation, and thus is free to reorder the two, clobbering the
+ original return address. */
+ usercode = *((int *) __builtin_frame_address (0) + 1);
+ /* GCC 4.4.6 also wants us to force loading USERCODE already here. */
+ asm volatile ("# %0" : : "X" (usercode));
+ *((void **) __builtin_frame_address (0) + 1) = &call_init1;
/* Force USERCODE into %eax and &init1 into %ecx, which are not
restored by function return. */
asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1));
@@ -322,11 +338,12 @@ first_init (void)
stack set up just as the user will see it, so it can switch stacks. */
void
-_dl_init_first (void)
+_dl_init_first (int argc, ...)
{
first_init ();
- init ((int *) __builtin_frame_address (0) + 2);
+ /* If we use ``__builtin_frame_address (0) + 2'' here, GCC gets confused. */
+ init (&argc);
}
#endif
@@ -360,15 +377,17 @@ _hurd_stack_setup (void)
void doinit (intptr_t *data)
{
/* This function gets called with the argument data at TOS. */
- void doinit1 (void)
+ void doinit1 (int argc, ...)
{
- init ((int *) __builtin_frame_address (0) + 2);
+ /* If we use ``__builtin_frame_address (0) + 2'' here, GCC gets
+ confused. */
+ init ((int *) &argc);
}
/* Push the user return address after the argument data, and then
- jump to `doinit1' (above), so it is as if __libc_init_first's
- caller had called `doinit1' with the argument data already on the
- stack. */
+ jump to `doinit1' (above), so it is as if __libc_init_first's
+ caller had called `doinit1' with the argument data already on the
+ stack. */
*--data = caller;
asm volatile ("movl %0, %%esp\n" /* Switch to new outermost stack. */
"movl $0, %%ebp\n" /* Clear outermost frame pointer. */
diff --git a/libc/sysdeps/mach/hurd/i386/signal-defines.sym b/libc/sysdeps/mach/hurd/i386/signal-defines.sym
new file mode 100644
index 000000000..9521bd723
--- /dev/null
+++ b/libc/sysdeps/mach/hurd/i386/signal-defines.sym
@@ -0,0 +1,10 @@
+#include <hurd/signal.h>
+#include <signal.h>
+
+--
+
+HURD_SIGSTATE__SIGALTSTACK__OFFSET offsetof(struct hurd_sigstate, sigaltstack)
+
+SIGALTSTACK__SS_SP__OFFSET offsetof(struct sigaltstack, ss_sp)
+SIGALTSTACK__SS_SIZE__OFFSET offsetof(struct sigaltstack, ss_size)
+SIGALTSTACK__SS_FLAGS__OFFSET offsetof(struct sigaltstack, ss_flags)
diff --git a/libc/sysdeps/mach/hurd/ioctl.c b/libc/sysdeps/mach/hurd/ioctl.c
index beffe4365..543d437c1 100644
--- a/libc/sysdeps/mach/hurd/ioctl.c
+++ b/libc/sysdeps/mach/hurd/ioctl.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1992,93,94,95,96,97,99,2000,2002,2005
- Free Software Foundation, Inc.
+/* Copyright (C) 1992-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -88,7 +87,7 @@ __ioctl (int fd, unsigned long int request, ...)
void *p;
#endif
- void *arg;
+ void *arg = NULL;
error_t err;
@@ -111,7 +110,7 @@ __ioctl (int fd, unsigned long int request, ...)
if (_IOC_INOUT (request) & IOC_IN)
{
/* We don't want to advance ARG since it will be used to copy out
- too if IOC_OUT is also set. */
+ too if IOC_OUT is also set. */
void *argptr = arg;
/* Pack an argument into the message buffer. */
@@ -139,7 +138,7 @@ __ioctl (int fd, unsigned long int request, ...)
in (_IOT_COUNT1 (type), _IOT_TYPE1 (type));
in (_IOT_COUNT2 (type), _IOT_TYPE2 (type));
}
- else if (_IOC_INOUT (request) == IOC_VOID)
+ else if (_IOC_INOUT (request) == IOC_VOID && _IOT_COUNT0 (type) != 0)
{
/* The RPC takes a single integer_t argument.
Rather than pointing to the value, ARG is the value itself. */
@@ -208,11 +207,15 @@ __ioctl (int fd, unsigned long int request, ...)
return msg.header.RetCode;
}
- va_list ap;
+ if (_IOT_COUNT0 (type) != 0)
+ {
+ /* Data need either be sent, received, or even both. */
+ va_list ap;
- va_start (ap, request);
- arg = va_arg (ap, void *);
- va_end (ap);
+ va_start (ap, request);
+ arg = va_arg (ap, void *);
+ va_end (ap);
+ }
{
/* Check for a registered handler for REQUEST. */
diff --git a/libc/sysdeps/mach/hurd/kernel-features.h b/libc/sysdeps/mach/hurd/kernel-features.h
index 07caf31f2..96a0d568f 100644
--- a/libc/sysdeps/mach/hurd/kernel-features.h
+++ b/libc/sysdeps/mach/hurd/kernel-features.h
@@ -1,5 +1,5 @@
/* Set flags signalling availability of certain operating system features.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,11 +20,6 @@
Almost none of these are used outside of sysdeps/unix/sysv/linux code.
But those referring to POSIX-level features like O_* flags can be. */
-#include <fcntl.h>
-
-/* If a system defines the O_CLOEXEC constant but it is sometimes ignored,
- it must override this file to define __ASSUME_O_CLOEXEC conditionally
- (or not at all) to indicate when O_CLOEXEC actually works. */
-#ifdef O_CLOEXEC
-# define __ASSUME_O_CLOEXEC 1
-#endif
+#define __ASSUME_O_CLOEXEC 1
+#define __ASSUME_DUP3 1
+#define __ASSUME_ACCEPT4 1
diff --git a/libc/sysdeps/mach/hurd/mkdir.c b/libc/sysdeps/mach/hurd/mkdir.c
index d3627ee5e..8ad648e0a 100644
--- a/libc/sysdeps/mach/hurd/mkdir.c
+++ b/libc/sysdeps/mach/hurd/mkdir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,93,94,95,96,97,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -19,6 +19,7 @@
#include <stddef.h>
#include <sys/stat.h>
#include <hurd.h>
+#include <string.h>
/* Create a directory named FILE_NAME with protections MODE. */
int
@@ -28,7 +29,10 @@ __mkdir (file_name, mode)
{
error_t err;
const char *name;
- file_t parent = __directory_name_split (file_name, (char **) &name);
+ file_t parent;
+ if (!strcmp (file_name, "/"))
+ return __hurd_fail (EEXIST);
+ parent = __directory_name_split (file_name, (char **) &name);
if (parent == MACH_PORT_NULL)
return -1;
err = __dir_mkdir (parent, name, mode & ~_hurd_umask);
diff --git a/libc/sysdeps/mach/hurd/mkdirat.c b/libc/sysdeps/mach/hurd/mkdirat.c
index 9201f7d35..d6d672ead 100644
--- a/libc/sysdeps/mach/hurd/mkdirat.c
+++ b/libc/sysdeps/mach/hurd/mkdirat.c
@@ -1,6 +1,5 @@
/* Create a directory named relative to another open directory. Hurd version.
- Copyright (C) 1991,1993,1994,1995,1996,1997,2002,2006
- Free Software Foundation, Inc.
+ Copyright (C) 1991-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -22,6 +21,7 @@
#include <sys/stat.h>
#include <hurd.h>
#include <hurd/fd.h>
+#include <string.h>
int
mkdirat (fd, path, mode)
@@ -31,7 +31,10 @@ mkdirat (fd, path, mode)
{
error_t err;
const char *name;
- file_t parent = __directory_name_split_at (fd, path, (char **) &name);
+ file_t parent;
+ if (!strcmp (path, "/"))
+ return __hurd_fail (EEXIST);
+ parent = __directory_name_split_at (fd, path, (char **) &name);
if (parent == MACH_PORT_NULL)
return -1;
err = __dir_mkdir (parent, name, mode & ~_hurd_umask);
diff --git a/libc/sysdeps/mach/hurd/mlock.c b/libc/sysdeps/mach/hurd/mlock.c
index 2cb3e5632..47bafaae1 100644
--- a/libc/sysdeps/mach/hurd/mlock.c
+++ b/libc/sysdeps/mach/hurd/mlock.c
@@ -1,5 +1,5 @@
/* mlock -- guarantee pages are resident in memory. Mach/Hurd version.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -39,7 +39,7 @@ mlock (const void *addr, size_t len)
page = trunc_page ((vm_address_t) addr);
len = round_page ((vm_address_t) addr + len) - page;
err = __vm_wire (hostpriv, __mach_task_self (), page, len,
- VM_PROT_ALL); /* XXX ? */
+ VM_PROT_READ);
__mach_port_deallocate (__mach_task_self (), hostpriv);
return err ? __hurd_fail (err) : 0;
diff --git a/libc/sysdeps/mach/hurd/openat.c b/libc/sysdeps/mach/hurd/openat.c
index 69d257c18..c6fcf49d8 100644
--- a/libc/sysdeps/mach/hurd/openat.c
+++ b/libc/sysdeps/mach/hurd/openat.c
@@ -1,5 +1,5 @@
/* openat -- Open a file named relative to an open directory. Hurd version.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -34,14 +34,14 @@ __openat (fd, file, oflag)
const char *file;
int oflag;
{
- int mode;
+ mode_t mode;
io_t port;
if (oflag & O_CREAT)
{
va_list arg;
va_start (arg, oflag);
- mode = va_arg (arg, int);
+ mode = va_arg (arg, mode_t);
va_end (arg);
}
else
diff --git a/libc/sysdeps/mach/hurd/opendir.c b/libc/sysdeps/mach/hurd/opendir.c
index 217d4c85d..175944418 100644
--- a/libc/sysdeps/mach/hurd/opendir.c
+++ b/libc/sysdeps/mach/hurd/opendir.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1993,1994,1995,1996,1997,1998,2001,2003,2005,2006
- Free Software Foundation, Inc.
+/* Copyright (C) 1993-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -29,6 +28,7 @@
#include <stdio.h>
#include <hurd.h>
#include <hurd/fd.h>
+#include <not-cancel.h>
#include "dirstream.h"
@@ -50,9 +50,11 @@ _hurd_fd_opendir (struct hurd_fd *d)
return NULL;
/* Set the descriptor to close on exec. */
+ HURD_CRITICAL_BEGIN;
__spin_lock (&d->port.lock);
d->flags |= FD_CLOEXEC;
__spin_unlock (&d->port.lock);
+ HURD_CRITICAL_END;
dirp->__fd = d;
dirp->__data = dirp->__ptr = NULL;
@@ -66,10 +68,45 @@ _hurd_fd_opendir (struct hurd_fd *d)
}
+DIR *
+internal_function
+__opendirat (int dfd, const char *name)
+{
+ if (name[0] == '\0')
+ {
+ /* POSIX.1-1990 says an empty name gets ENOENT;
+ but `open' might like it fine. */
+ __set_errno (ENOENT);
+ return NULL;
+ }
+
+ int flags = O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC;
+ int fd;
+#ifdef IS_IN_rtld
+ assert (dfd == AT_FDCWD);
+ fd = open_not_cancel_2 (name, flags);
+#else
+ fd = openat_not_cancel_3 (dfd, name, flags);
+#endif
+ if (fd < 0)
+ return NULL;
+
+ /* Extract the pointer to the descriptor structure. */
+ DIR *dirp = _hurd_fd_opendir (_hurd_fd_get (fd));
+ if (dirp == NULL)
+ __close (fd);
+
+ return dirp;
+}
+
+
/* Open a directory stream on NAME. */
DIR *
__opendir (const char *name)
{
+#if 0 /* TODO. */
+ return __opendirat (AT_FDCWD, name);
+#else
if (name[0] == '\0')
{
/* POSIX.1-1990 says an empty name gets ENOENT;
@@ -88,5 +125,6 @@ __opendir (const char *name)
__close (fd);
return dirp;
+#endif
}
weak_alias (__opendir, opendir)
diff --git a/libc/sysdeps/mach/hurd/readlinkat.c b/libc/sysdeps/mach/hurd/readlinkat.c
new file mode 100644
index 000000000..c46522a48
--- /dev/null
+++ b/libc/sysdeps/mach/hurd/readlinkat.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 1991-2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/paths.h>
+#include <hurd/fd.h>
+#include <fcntl.h>
+#include <string.h>
+
+/* Read the contents of the symbolic link FILE_NAME relative to FD into no more
+ than LEN bytes of BUF. The contents are not null-terminated.
+ Returns the number of characters read, or -1 for errors. */
+ssize_t
+readlinkat (fd, file_name, buf, len)
+ int fd;
+ const char *file_name;
+ char *buf;
+ size_t len;
+{
+ error_t err;
+ file_t file;
+ struct stat64 st;
+
+ file = __file_name_lookup_at (fd, 0, file_name, O_READ | O_NOLINK, 0);
+ if (file == MACH_PORT_NULL)
+ return -1;
+
+ err = __io_stat (file, &st);
+ if (! err)
+ if (S_ISLNK (st.st_mode))
+ {
+ char *rbuf = buf;
+
+ err = __io_read (file, &rbuf, &len, 0, len);
+ if (!err && rbuf != buf)
+ {
+ memcpy (buf, rbuf, len);
+ __vm_deallocate (__mach_task_self (), (vm_address_t)rbuf, len);
+ }
+ }
+ else
+ err = EINVAL;
+
+ __mach_port_deallocate (__mach_task_self (), file);
+
+ return err ? __hurd_fail (err) : len;
+}
+libc_hidden_def (readlinkat)
diff --git a/libc/sysdeps/mach/hurd/recvfrom.c b/libc/sysdeps/mach/hurd/recvfrom.c
index f59133611..3a094aa0d 100644
--- a/libc/sysdeps/mach/hurd/recvfrom.c
+++ b/libc/sysdeps/mach/hurd/recvfrom.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1997, 1999, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -54,7 +54,7 @@ __recvfrom (fd, buf, n, flags, addrarg, addr_len)
return __hurd_sockfail (fd, flags, err);
/* Get address data for the returned address port if requested. */
- if (addr != NULL)
+ if (addr != NULL && addrport != MACH_PORT_NULL)
{
char *buf = (char *) addr;
mach_msg_type_number_t buflen = *addr_len;
@@ -88,6 +88,8 @@ __recvfrom (fd, buf, n, flags, addrarg, addr_len)
if (buflen > 0)
addr->sa_family = type;
}
+ else if (addr_len != NULL)
+ *addr_len = 0;
__mach_port_deallocate (__mach_task_self (), addrport);
diff --git a/libc/sysdeps/mach/hurd/setitimer.c b/libc/sysdeps/mach/hurd/setitimer.c
index a7b2e29d1..00cd0cc44 100644
--- a/libc/sysdeps/mach/hurd/setitimer.c
+++ b/libc/sysdeps/mach/hurd/setitimer.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1994,1995,1996,1997,2000,2001,2005
- Free Software Foundation, Inc.
+/* Copyright (C) 1994-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -219,7 +218,7 @@ setitimer_locked (const struct itimerval *new, struct itimerval *old,
/* Start up the itimer thread running `timer_thread' (below). */
if (err = __thread_create (__mach_task_self (),
&_hurd_itimer_thread))
- return __hurd_fail (err);
+ goto out;
_hurd_itimer_thread_stack_base = 0; /* Anywhere. */
_hurd_itimer_thread_stack_size = __vm_page_size; /* Small stack. */
if (err = __mach_setup_thread (__mach_task_self (),
diff --git a/libc/sysdeps/mach/hurd/setresgid.c b/libc/sysdeps/mach/hurd/setresgid.c
index 9d5885bed..eebd364fc 100644
--- a/libc/sysdeps/mach/hurd/setresgid.c
+++ b/libc/sysdeps/mach/hurd/setresgid.c
@@ -1,5 +1,5 @@
/* setresgid -- set real group ID, effective group ID, and saved-set group ID
- Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -28,7 +28,6 @@ __setresgid (gid_t rgid, gid_t egid, gid_t sgid)
{
auth_t newauth;
error_t err;
- gid_t agids[2] = { rgid, sgid };
HURD_CRITICAL_BEGIN;
__mutex_lock (&_hurd_id.lock);
@@ -37,31 +36,78 @@ __setresgid (gid_t rgid, gid_t egid, gid_t sgid)
if (!err)
{
/* Make a new auth handle which has EGID as the first element in the
- list of effective gids. */
+ list of effective gids. */
- if (_hurd_id.gen.ngids > 0)
+ uid_t *newgen, *newaux;
+ uid_t auxs[2] = { rgid, sgid };
+ size_t ngen, naux;
+
+ newgen = _hurd_id.gen.gids;
+ ngen = _hurd_id.gen.ngids;
+ if (egid != -1)
+ {
+ if (_hurd_id.gen.ngids == 0)
+ {
+ /* No effective gids now. The new set will be just UID. */
+ newgen = &egid;
+ ngen = 1;
+ }
+ else
+ {
+ _hurd_id.gen.gids[0] = egid;
+ _hurd_id.valid = 0;
+ }
+ }
+
+ newaux = _hurd_id.aux.gids;
+ naux = _hurd_id.aux.ngids;
+ if (rgid != -1)
{
- _hurd_id.gen.gids[0] = egid;
- _hurd_id.valid = 0;
+ if (_hurd_id.aux.ngids == 0)
+ {
+ newaux = &rgid;
+ naux = 1;
+ }
+ else
+ {
+ _hurd_id.aux.gids[0] = rgid;
+ _hurd_id.valid = 0;
+ }
}
- if (_hurd_id.aux.ngids > 1)
+
+ if (sgid != -1)
{
- _hurd_id.aux.gids[0] = rgid;
- _hurd_id.aux.gids[1] = sgid;
- _hurd_id.valid = 0;
+ if (rgid == -1)
+ {
+ if (_hurd_id.aux.ngids >= 1)
+ auxs[0] = _hurd_id.aux.gids[0];
+ else if (_hurd_id.gen.ngids >= 1)
+ auxs[0] = _hurd_id.gen.gids[0];
+ else
+ /* Not even an effective GID.
+ Fall back to the only GID we have. */
+ auxs[0] = sgid;
+ }
+ if (_hurd_id.aux.ngids <= 1)
+ {
+ /* No saved gids now. The new set will be just UID. */
+ newaux = auxs;
+ naux = 2;
+ }
+ else
+ {
+ _hurd_id.aux.gids[1] = sgid;
+ _hurd_id.valid = 0;
+ }
}
err = __USEPORT (AUTH, __auth_makeauth
(port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
_hurd_id.gen.uids, _hurd_id.gen.nuids,
_hurd_id.aux.uids, _hurd_id.aux.nuids,
- _hurd_id.gen.ngids ? _hurd_id.gen.gids : &egid,
- _hurd_id.gen.ngids ?: 1,
- _hurd_id.aux.ngids > 1 ? _hurd_id.aux.gids : agids,
- _hurd_id.aux.ngids > 1 ? _hurd_id.aux.ngids : 2,
+ newgen, ngen, newaux, naux,
&newauth));
}
-
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
diff --git a/libc/sysdeps/mach/hurd/setresuid.c b/libc/sysdeps/mach/hurd/setresuid.c
index 35aea8587..751763f5a 100644
--- a/libc/sysdeps/mach/hurd/setresuid.c
+++ b/libc/sysdeps/mach/hurd/setresuid.c
@@ -1,5 +1,5 @@
/* setresuid -- set real user ID, effective user ID, and saved-set user ID
- Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -28,7 +28,6 @@ __setresuid (uid_t ruid, uid_t euid, uid_t suid)
{
auth_t newauth;
error_t err;
- uid_t auids[2] = { ruid, suid };
HURD_CRITICAL_BEGIN;
__mutex_lock (&_hurd_id.lock);
@@ -37,26 +36,74 @@ __setresuid (uid_t ruid, uid_t euid, uid_t suid)
if (!err)
{
/* Make a new auth handle which has EUID as the first element in the
- list of effective uids. */
+ list of effective uids. */
- if (_hurd_id.gen.nuids > 0)
+ uid_t *newgen, *newaux;
+ uid_t auxs[2] = { ruid, suid };
+ size_t ngen, naux;
+
+ newgen = _hurd_id.gen.uids;
+ ngen = _hurd_id.gen.nuids;
+ if (euid != -1)
{
- _hurd_id.gen.uids[0] = euid;
- _hurd_id.valid = 0;
+ if (_hurd_id.gen.nuids == 0)
+ {
+ /* No effective uids now. The new set will be just UID. */
+ newgen = &euid;
+ ngen = 1;
+ }
+ else
+ {
+ _hurd_id.gen.uids[0] = euid;
+ _hurd_id.valid = 0;
+ }
}
- if (_hurd_id.aux.nuids > 1)
+
+ newaux = _hurd_id.aux.uids;
+ naux = _hurd_id.aux.nuids;
+ if (ruid != -1)
+ {
+ if (_hurd_id.aux.nuids == 0)
+ {
+ newaux = &ruid;
+ naux = 1;
+ }
+ else
+ {
+ _hurd_id.aux.uids[0] = ruid;
+ _hurd_id.valid = 0;
+ }
+ }
+
+ if (suid != -1)
{
- _hurd_id.aux.uids[0] = ruid;
- _hurd_id.aux.uids[1] = suid;
- _hurd_id.valid = 0;
+ if (ruid == -1)
+ {
+ if (_hurd_id.aux.nuids >= 1)
+ auxs[0] = _hurd_id.aux.uids[0];
+ else if (_hurd_id.gen.nuids >= 1)
+ auxs[0] = _hurd_id.gen.uids[0];
+ else
+ /* Not even an effective UID.
+ Fall back to the only UID we have. */
+ auxs[0] = suid;
+ }
+ if (_hurd_id.aux.nuids <= 1)
+ {
+ /* No saved uids now. The new set will be just UID. */
+ newaux = auxs;
+ naux = 2;
+ }
+ else
+ {
+ _hurd_id.aux.uids[1] = suid;
+ _hurd_id.valid = 0;
+ }
}
err = __USEPORT (AUTH, __auth_makeauth
(port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
- _hurd_id.gen.nuids ? _hurd_id.gen.uids : &euid,
- _hurd_id.gen.nuids ?: 1,
- _hurd_id.aux.nuids > 1 ? _hurd_id.aux.uids : auids,
- _hurd_id.aux.nuids > 1 ? _hurd_id.aux.nuids : 2,
+ newgen, ngen, newaux, naux,
_hurd_id.gen.gids, _hurd_id.gen.ngids,
_hurd_id.aux.gids, _hurd_id.aux.ngids,
&newauth));
diff --git a/libc/sysdeps/mach/hurd/xmknodat.c b/libc/sysdeps/mach/hurd/xmknodat.c
index acd1a8c68..645f22280 100644
--- a/libc/sysdeps/mach/hurd/xmknodat.c
+++ b/libc/sysdeps/mach/hurd/xmknodat.c
@@ -1,6 +1,5 @@
/* Create a device file relative to an open directory. Hurd version.
- Copyright (C) 1991,1992,1993,1994,1995,1996,1999,2002,2005,2006
- Free Software Foundation, Inc.
+ Copyright (C) 1991-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -34,7 +33,7 @@
int
__xmknodat (int vers, int fd, const char *path, mode_t mode, dev_t *dev)
{
- error_t err;
+ error_t errnode, err;
file_t dir, node;
char *name;
char buf[100], *bp;
@@ -94,7 +93,7 @@ __xmknodat (int vers, int fd, const char *path, mode_t mode, dev_t *dev)
return -1;
/* Create a new, unlinked node in the target directory. */
- err = __dir_mkfile (dir, O_WRITE, (mode & ~S_IFMT) & ~_hurd_umask, &node);
+ errnode = err = __dir_mkfile (dir, O_WRITE, (mode & ~S_IFMT) & ~_hurd_umask, &node);
if (! err && translator != NULL)
/* Set the node's translator to make it a device. */
@@ -109,7 +108,8 @@ __xmknodat (int vers, int fd, const char *path, mode_t mode, dev_t *dev)
err = __dir_link (dir, node, name, 1);
__mach_port_deallocate (__mach_task_self (), dir);
- __mach_port_deallocate (__mach_task_self (), node);
+ if (! errnode)
+ __mach_port_deallocate (__mach_task_self (), node);
if (err)
return __hurd_fail (err);
diff --git a/libc/sysdeps/mach/hurd/xstatconv.c b/libc/sysdeps/mach/hurd/xstatconv.c
index db704c6f3..ebe6471ac 100644
--- a/libc/sysdeps/mach/hurd/xstatconv.c
+++ b/libc/sysdeps/mach/hurd/xstatconv.c
@@ -1,5 +1,5 @@
/* Convert between `struct stat' format, and `struct stat64' format.
- Copyright (C) 2000,01,02 Free Software Foundation, Inc.
+ Copyright (C) 2000-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -41,12 +41,9 @@ xstat64_conv (struct stat *buf, const struct stat64 *buf64)
buf->st_uid = buf64->st_uid;
buf->st_gid = buf64->st_gid;
buf->st_size = buf64->st_size;
- buf->st_atime = buf64->st_atime;
- buf->st_atime_usec = buf64->st_atime_usec;
- buf->st_mtime = buf64->st_mtime;
- buf->st_mtime_usec = buf64->st_mtime_usec;
- buf->st_ctime = buf64->st_ctime;
- buf->st_ctime_usec = buf64->st_ctime_usec;
+ buf->st_atim = buf64->st_atim;
+ buf->st_mtim = buf64->st_mtim;
+ buf->st_ctim = buf64->st_ctim;
buf->st_blksize = buf64->st_blksize;
buf->st_blocks = buf64->st_blocks;
buf->st_author = buf64->st_author;
diff --git a/libc/sysdeps/mach/nanosleep.c b/libc/sysdeps/mach/nanosleep.c
index 0192ff0bd..a1ba19c17 100644
--- a/libc/sysdeps/mach/nanosleep.c
+++ b/libc/sysdeps/mach/nanosleep.c
@@ -1,5 +1,5 @@
/* nanosleep -- sleep for a period specified with a struct timespec
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -27,6 +27,15 @@ __nanosleep (const struct timespec *requested_time,
{
mach_port_t recv;
struct timeval before, after;
+
+ if (requested_time->tv_sec < 0
+ || requested_time->tv_nsec < 0
+ || requested_time->tv_nsec >= 1000000000)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
const mach_msg_timeout_t ms
= requested_time->tv_sec * 1000
+ (requested_time->tv_nsec + 999999) / 1000000;
@@ -35,16 +44,22 @@ __nanosleep (const struct timespec *requested_time,
if (remaining && __gettimeofday (&before, NULL) < 0)
return -1;
- (void) __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
- 0, 0, recv, ms, MACH_PORT_NULL);
+ error_t err = __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
+ 0, 0, recv, ms, MACH_PORT_NULL);
__mach_port_destroy (mach_task_self (), recv);
- if (remaining && __gettimeofday (&after, NULL) < 0)
- return -1;
-
- if (remaining)
+ if (err == EMACH_RCV_INTERRUPTED)
{
- timersub (&after, &before, &after);
- TIMEVAL_TO_TIMESPEC (&after, remaining);
+ if (remaining && __gettimeofday (&after, NULL) >= 0)
+ {
+ struct timeval req_time, elapsed, rem;
+ TIMESPEC_TO_TIMEVAL (&req_time, requested_time);
+ timersub (&after, &before, &elapsed);
+ timersub (&req_time, &elapsed, &rem);
+ TIMEVAL_TO_TIMESPEC (&rem, remaining);
+ }
+
+ errno = EINTR;
+ return -1;
}
return 0;
diff --git a/libc/sysdeps/posix/getaddrinfo.c b/libc/sysdeps/posix/getaddrinfo.c
index 1a023f91f..2eca2ae0e 100644
--- a/libc/sysdeps/posix/getaddrinfo.c
+++ b/libc/sysdeps/posix/getaddrinfo.c
@@ -2604,7 +2604,7 @@ getaddrinfo (const char *name, const char *service,
__libc_lock_define_initialized (static, lock);
__libc_lock_lock (lock);
- if (old_once && gaiconf_reload_flag)
+ if (__libc_once_get (old_once) && gaiconf_reload_flag)
gaiconf_reload ();
qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
__libc_lock_unlock (lock);
diff --git a/libc/sysdeps/posix/getcwd.c b/libc/sysdeps/posix/getcwd.c
index 6c41977eb..1dc45e8ee 100644
--- a/libc/sysdeps/posix/getcwd.c
+++ b/libc/sysdeps/posix/getcwd.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-1999,2011-2012 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -173,6 +173,7 @@ extern char *alloca ();
#if defined _LIBC
# include <not-cancel.h>
+# include <kernel-features.h>
#else
# define openat64_not_cancel_3(dfd, name, mode) openat64 (dfd, name, mode)
# define close_not_cancel_no_status(fd) close (fd)
diff --git a/libc/sysdeps/powerpc/memmove.c b/libc/sysdeps/powerpc/memmove.c
index 4887ae356..89182838e 100644
--- a/libc/sysdeps/powerpc/memmove.c
+++ b/libc/sysdeps/powerpc/memmove.c
@@ -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; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
#include <string.h>
#include <memcopy.h>
diff --git a/libc/sysdeps/sparc/fpu/bits/fenv.h b/libc/sysdeps/sparc/fpu/bits/fenv.h
index 2168de582..0e2a9b9e6 100644
--- a/libc/sysdeps/sparc/fpu/bits/fenv.h
+++ b/libc/sysdeps/sparc/fpu/bits/fenv.h
@@ -76,9 +76,9 @@ typedef unsigned long int fenv_t;
/* For internal use only: access the fp state register. */
#if __WORDSIZE == 64
-# define __fenv_stfsr(X) __asm__ ("stx %%fsr,%0" : "=m" (X))
+# define __fenv_stfsr(X) __asm__ __volatile__ ("stx %%fsr,%0" : "=m" (X))
# define __fenv_ldfsr(X) __asm__ __volatile__ ("ldx %0,%%fsr" : : "m" (X))
#else
-# define __fenv_stfsr(X) __asm__ ("st %%fsr,%0" : "=m" (X))
+# define __fenv_stfsr(X) __asm__ __volatile__ ("st %%fsr,%0" : "=m" (X))
# define __fenv_ldfsr(X) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (X))
#endif
diff --git a/libc/sysdeps/sparc/fpu/fpu_control.h b/libc/sysdeps/sparc/fpu/fpu_control.h
index c8bb50373..26c08e956 100644
--- a/libc/sysdeps/sparc/fpu/fpu_control.h
+++ b/libc/sysdeps/sparc/fpu/fpu_control.h
@@ -59,11 +59,11 @@
typedef unsigned long int fpu_control_t;
#if __WORDSIZE == 64
-# define _FPU_GETCW(cw) __asm__ ("stx %%fsr,%0" : "=m" (*&cw))
-# define _FPU_SETCW(cw) __asm__ ("ldx %0,%%fsr" : : "m" (*&cw))
+# define _FPU_GETCW(cw) __asm__ __volatile__ ("stx %%fsr,%0" : "=m" (*&cw))
+# define _FPU_SETCW(cw) __asm__ __volatile__ ("ldx %0,%%fsr" : : "m" (*&cw))
#else
-# define _FPU_GETCW(cw) __asm__ ("st %%fsr,%0" : "=m" (*&cw))
-# define _FPU_SETCW(cw) __asm__ ("ld %0,%%fsr" : : "m" (*&cw))
+# define _FPU_GETCW(cw) __asm__ __volatile__ ("st %%fsr,%0" : "=m" (*&cw))
+# define _FPU_SETCW(cw) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (*&cw))
#endif
/* Default control word set at startup. */
diff --git a/libc/sysdeps/sparc/fpu/libm-test-ulps b/libc/sysdeps/sparc/fpu/libm-test-ulps
index 080441e91..c9030879d 100644
--- a/libc/sysdeps/sparc/fpu/libm-test-ulps
+++ b/libc/sysdeps/sparc/fpu/libm-test-ulps
@@ -1,9 +1,18 @@
# Begin of automatic generation
# acos_downward
+Test "acos_downward (-0) == pi/2":
+float: 1
+ifloat: 1
Test "acos_downward (-0.5) == M_PI_6l*4.0":
double: 1
idouble: 1
+Test "acos_downward (-1) == pi":
+float: 1
+ifloat: 1
+Test "acos_downward (0) == pi/2":
+float: 1
+ifloat: 1
Test "acos_downward (0.5) == M_PI_6l*2.0":
double: 1
float: 1
@@ -13,9 +22,18 @@ ildouble: 1
ldouble: 1
# acos_towardzero
+Test "acos_towardzero (-0) == pi/2":
+float: 1
+ifloat: 1
Test "acos_towardzero (-0.5) == M_PI_6l*4.0":
double: 1
idouble: 1
+Test "acos_towardzero (-1) == pi":
+float: 1
+ifloat: 1
+Test "acos_towardzero (0) == pi/2":
+float: 1
+ifloat: 1
Test "acos_towardzero (0.5) == M_PI_6l*2.0":
double: 1
float: 1
@@ -24,6 +42,17 @@ ifloat: 1
ildouble: 1
ldouble: 1
+# acos_upward
+Test "acos_upward (-0) == pi/2":
+ildouble: 1
+ldouble: 1
+Test "acos_upward (-1) == pi":
+ildouble: 1
+ldouble: 1
+Test "acos_upward (0) == pi/2":
+ildouble: 1
+ldouble: 1
+
# asin_downward
Test "asin_downward (-0.5) == -pi/6":
double: 1
@@ -1224,6 +1253,14 @@ double: 2
float: 1
idouble: 2
ifloat: 1
+Test "exp10 (-305) == 1.0e-305":
+double: 1
+idouble: 1
+Test "exp10 (-36) == 1.0e-36":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
Test "exp10 (0.75) == 5.62341325190349080394951039776481231":
double: 1
float: 1
@@ -1236,6 +1273,12 @@ idouble: 6
ifloat: 2
ildouble: 1
ldouble: 1
+Test "exp10 (36) == 1.0e36":
+double: 1
+idouble: 1
+Test "exp10 (4932) == 1.0e4932":
+ildouble: 1
+ldouble: 1
# exp2
Test "exp2 (100.5) == 1.792728671193156477399422023278661496394e+30":
@@ -1284,6 +1327,9 @@ idouble: 1
ifloat: 1
ildouble: 1
ldouble: 1
+Test "expm1 (500.0) == 1.4035922178528374107397703328409120821806e+217":
+double: 1
+idouble: 1
# gamma
Test "gamma (-0.5) == log(2*sqrt(pi))":
@@ -2093,6 +2139,10 @@ ifloat: 1
ildouble: 1
ldouble: 1
+Function: "acos_upward":
+ildouble: 1
+ldouble: 1
+
Function: "asin_downward":
double: 1
float: 1
diff --git a/libc/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_floor-vis3.S b/libc/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_floor-vis3.S
index d7e5d24c1..dfaf55458 100644
--- a/libc/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_floor-vis3.S
+++ b/libc/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_floor-vis3.S
@@ -56,10 +56,9 @@ ENTRY (__floor_vis3)
fnegd ZERO, SIGN_BIT
- stx %o2, [%sp + 72]
+ movxtod %o2, %f16
fabsd %f0, %f14
- ldd [%sp + 72], %f16
fcmpd %fcc3, %f14, %f16
fmovduge %fcc3, ZERO, %f16
diff --git a/libc/sysdeps/sparc/sysdep.h b/libc/sysdeps/sparc/sysdep.h
index 2702620be..bcffec94f 100644
--- a/libc/sysdeps/sparc/sysdep.h
+++ b/libc/sysdeps/sparc/sysdep.h
@@ -58,21 +58,34 @@ __sparc_get_pc_thunk.reg: \
.previous; \
.endif;
-/* Even when v9 we use a call sequence instead of using "rd %pc" because
+/* The "-4" and "+4" offsets against _GLOBAL_OFFSET_TABLE_ are
+ critical since they represent the offset from the thunk call to the
+ instruction containing the _GLOBAL_OFFSET_TABLE_ reference.
+ Therefore these instructions cannot be moved around without
+ appropriate adjustments to those offsets.
+
+ Furthermore, these expressions are special in another regard. When
+ the assembler sees a reference to _GLOBAL_OFFSET_TABLE_ inside of
+ a %hi() or %lo(), it emits a PC-relative relocation. This causes
+ R_SPARC_HI22 to turn into R_SPARC_PC22, and R_SPARC_LO10 to turn into
+ R_SPARC_PC10, respectively.
+
+ Even when v9 we use a call sequence instead of using "rd %pc" because
RDPC is extremely expensive and incurs a full pipeline flush. */
-#define SETUP_PIC_REG(reg) \
- SPARC_PIC_THUNK(reg) \
+#define SPARC_PIC_THUNK_CALL(reg) \
sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %##reg; \
call __sparc_get_pc_thunk.reg; \
or %##reg, %lo(_GLOBAL_OFFSET_TABLE_+4), %##reg;
+#define SETUP_PIC_REG(reg) \
+ SPARC_PIC_THUNK(reg) \
+ SPARC_PIC_THUNK_CALL(reg)
+
#define SETUP_PIC_REG_LEAF(reg, tmp) \
SPARC_PIC_THUNK(reg) \
- sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %##reg; \
mov %o7, %##tmp; \
- call __sparc_get_pc_thunk.reg; \
- or %##reg, %lo(_GLOBAL_OFFSET_TABLE_+4), %##reg; \
+ SPARC_PIC_THUNK_CALL(reg); \
mov %##tmp, %o7;
#undef ENTRY
diff --git a/libc/sysdeps/unix/syscalls.list b/libc/sysdeps/unix/syscalls.list
index 5c696b31c..39c40ed7f 100644
--- a/libc/sysdeps/unix/syscalls.list
+++ b/libc/sysdeps/unix/syscalls.list
@@ -10,7 +10,7 @@ chroot - chroot i:s chroot
close - close Ci:i __libc_close __close close
dup - dup i:i __dup dup
dup2 - dup2 i:ii __dup2 dup2
-dup3 - dup3 i:iii dup3
+dup3 - dup3 i:iii __dup3 dup3
fchdir - fchdir i:i __fchdir fchdir
fchmod - fchmod i:ii __fchmod fchmod
fchown - fchown i:iii __fchown fchown
diff --git a/libc/sysdeps/unix/sysv/linux/configure b/libc/sysdeps/unix/sysv/linux/configure
index 31031613d..d571d0b62 100644
--- a/libc/sysdeps/unix/sysv/linux/configure
+++ b/libc/sysdeps/unix/sysv/linux/configure
@@ -382,38 +382,6 @@ fi
if test -n "$sysheaders"; then
CPPFLAGS=$OLD_CPPFLAGS
fi
-# The Linux filesystem standard prescribes where to place "essential"
-# files. I.e., when the installation prefix is "/usr" we have to place
-# shared library objects and the configuration files on the root partition
-# in /lib and /etc.
-case "$prefix" in
-/usr | /usr/)
- # 64-bit libraries on bi-arch platforms go in /lib64 instead of /lib.
- # Allow earlier configure scripts to handle libc_cv_slibdir, libdir,
- # and libc_cv_localedir.
- test -n "$libc_cv_slibdir" || \
- case $machine in
- sparc/sparc64 | x86_64* | powerpc/powerpc64 | s390/s390-64)
- libc_cv_slibdir="/lib64"
- if test "$libdir" = '${exec_prefix}/lib'; then
- libdir='${exec_prefix}/lib64';
- # Locale data can be shared between 32bit and 64bit libraries
- libc_cv_localedir='${exec_prefix}/lib/locale'
- fi
- ;;
- *)
- libc_cv_slibdir="/lib"
- ;;
- esac
- # Allow the user to override the path with --sysconfdir
- if test $sysconfdir = '${prefix}/etc'; then
- libc_cv_sysconfdir=/etc
- else
- libc_cv_sysconfdir=$sysconfdir
- fi
- libc_cv_rootsbindir="/sbin"
- ;;
-esac
# Under Linux the NPTL add-on should be available.
case $add_ons in
diff --git a/libc/sysdeps/unix/sysv/linux/configure.in b/libc/sysdeps/unix/sysv/linux/configure.in
index 556ca8451..916d64a60 100644
--- a/libc/sysdeps/unix/sysv/linux/configure.in
+++ b/libc/sysdeps/unix/sysv/linux/configure.in
@@ -121,38 +121,6 @@ fi
if test -n "$sysheaders"; then
CPPFLAGS=$OLD_CPPFLAGS
fi
-# The Linux filesystem standard prescribes where to place "essential"
-# files. I.e., when the installation prefix is "/usr" we have to place
-# shared library objects and the configuration files on the root partition
-# in /lib and /etc.
-case "$prefix" in
-/usr | /usr/)
- # 64-bit libraries on bi-arch platforms go in /lib64 instead of /lib.
- # Allow earlier configure scripts to handle libc_cv_slibdir, libdir,
- # and libc_cv_localedir.
- test -n "$libc_cv_slibdir" || \
- case $machine in
- sparc/sparc64 | x86_64* | powerpc/powerpc64 | s390/s390-64)
- libc_cv_slibdir="/lib64"
- if test "$libdir" = '${exec_prefix}/lib'; then
- libdir='${exec_prefix}/lib64';
- # Locale data can be shared between 32bit and 64bit libraries
- libc_cv_localedir='${exec_prefix}/lib/locale'
- fi
- ;;
- *)
- libc_cv_slibdir="/lib"
- ;;
- esac
- # Allow the user to override the path with --sysconfdir
- if test $sysconfdir = '${prefix}/etc'; then
- libc_cv_sysconfdir=/etc
- else
- libc_cv_sysconfdir=$sysconfdir
- fi
- libc_cv_rootsbindir="/sbin"
- ;;
-esac
# Under Linux the NPTL add-on should be available.
case $add_ons in
diff --git a/libc/sysdeps/unix/sysv/linux/syscalls.list b/libc/sysdeps/unix/sysv/linux/syscalls.list
index f6e6653d3..eef6d82b5 100644
--- a/libc/sysdeps/unix/sysv/linux/syscalls.list
+++ b/libc/sysdeps/unix/sysv/linux/syscalls.list
@@ -1,6 +1,7 @@
# File name Caller Syscall name Args Strong name Weak names
adjtimex adjtime adjtimex i:p __adjtimex adjtimex ntp_adjtime __adjtimex_internal
+alarm - alarm i:i alarm
bdflush EXTRA bdflush i:ii bdflush
capget EXTRA capget i:pp capget
capset EXTRA capset i:pp capset
@@ -71,12 +72,14 @@ setfsuid EXTRA setfsuid i:i setfsuid
setpgid - setpgid i:ii __setpgid setpgid
sigaltstack - sigaltstack i:PP __sigaltstack sigaltstack
splice EXTRA splice Ci:iPiPii splice
+stime - stime i:p stime
sysinfo EXTRA sysinfo i:p sysinfo
swapon - swapon i:si __swapon swapon
swapoff - swapoff i:s __swapoff swapoff
tee EXTRA tee Ci:iiii tee
unshare EXTRA unshare i:i unshare
uselib EXTRA uselib i:s uselib
+utime - utime i:sP utime
vmsplice EXTRA vmsplice Ci:iPii vmsplice
wait4 - wait4 i:iWiP __wait4 wait4
diff --git a/libc/sysdeps/unix/sysv/syscalls.list b/libc/sysdeps/unix/sysv/syscalls.list
deleted file mode 100644
index c508dd0ec..000000000
--- a/libc/sysdeps/unix/sysv/syscalls.list
+++ /dev/null
@@ -1,9 +0,0 @@
-# File name Caller Syscall name # args Strong name Weak names
-
-alarm - alarm i:i alarm
-pause - pause Ci: pause
-setrlimit - setrlimit i:ip __setrlimit setrlimit
-settimeofday - settimeofday i:PP __settimeofday settimeofday
-stime - stime i:p stime
-ulimit - ulimit i:ii ulimit
-utime - utime i:sP utime
diff --git a/libc/sysdeps/x86_64/Makefile b/libc/sysdeps/x86_64/Makefile
index b989f6a97..81c9128a9 100644
--- a/libc/sysdeps/x86_64/Makefile
+++ b/libc/sysdeps/x86_64/Makefile
@@ -21,6 +21,19 @@ sysdep-dl-routines += tlsdesc dl-tlsdesc
sysdep_routines += tlsdesc dl-tlsdesc
sysdep-rtld-routines += tlsdesc dl-tlsdesc
+tests += tst-quad1 tst-quad2
+modules-names += tst-quadmod1 tst-quadmod2
+
+$(objpfx)tst-quad1: $(objpfx)tst-quadmod1.so
+$(objpfx)tst-quad2: $(objpfx)tst-quadmod2.so
+
+quad-pie-test += tst-quad1pie tst-quad2pie
+tests += $(quad-pie-test)
+tests-pie += $(quad-pie-test)
+
+$(objpfx)tst-quad1pie: $(objpfx)tst-quadmod1pie.o
+$(objpfx)tst-quad2pie: $(objpfx)tst-quadmod2pie.o
+
tests: $(objpfx)tst-xmmymm.out
$(objpfx)tst-xmmymm.out: ../sysdeps/x86_64/tst-xmmymm.sh $(objpfx)ld.so
@echo "Checking ld.so for SSE register use. This will take a few seconds..."
diff --git a/libc/sysdeps/x86_64/dl-machine.h b/libc/sysdeps/x86_64/dl-machine.h
index 8ceb479de..32814b14f 100644
--- a/libc/sysdeps/x86_64/dl-machine.h
+++ b/libc/sysdeps/x86_64/dl-machine.h
@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. x86-64 version.
- Copyright (C) 2001-2006, 2008-2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2001-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>.
@@ -29,7 +29,7 @@
/* Return nonzero iff ELF header is compatible with the running host. */
static inline int __attribute__ ((unused))
-elf_machine_matches_host (const Elf64_Ehdr *ehdr)
+elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
{
return ehdr->e_machine == EM_X86_64;
}
@@ -38,24 +38,24 @@ elf_machine_matches_host (const Elf64_Ehdr *ehdr)
/* Return the link-time address of _DYNAMIC. Conveniently, this is the
first element of the GOT. This must be inlined in a function which
uses global data. */
-static inline Elf64_Addr __attribute__ ((unused))
+static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_dynamic (void)
{
- Elf64_Addr addr;
+ ElfW(Addr) addr;
/* This works because we have our GOT address available in the small PIC
model. */
- addr = (Elf64_Addr) &_DYNAMIC;
+ addr = (ElfW(Addr)) &_DYNAMIC;
return addr;
}
/* Return the run-time load address of the shared object. */
-static inline Elf64_Addr __attribute__ ((unused))
+static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_load_address (void)
{
- Elf64_Addr addr;
+ ElfW(Addr) addr;
/* The easy way is just the same as on x86:
leaq _dl_start, %0
@@ -89,8 +89,8 @@ static inline int __attribute__ ((unused, always_inline))
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf64_Addr *got;
- extern void _dl_runtime_resolve (Elf64_Word) attribute_hidden;
- extern void _dl_runtime_profile (Elf64_Word) attribute_hidden;
+ extern void _dl_runtime_resolve (ElfW(Word)) attribute_hidden;
+ extern void _dl_runtime_profile (ElfW(Word)) attribute_hidden;
if (l->l_info[DT_JMPREL] && lazy)
{
@@ -105,9 +105,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
if (got[1])
{
l->l_mach.plt = got[1] + l->l_addr;
- l->l_mach.gotplt = (Elf64_Addr) &got[3];
+ l->l_mach.gotplt = (ElfW(Addr)) &got[3];
}
- got[1] = (Elf64_Addr) l; /* Identify this shared object. */
+ /* Identify this shared object. */
+ *(ElfW(Addr) *) (got + 1) = (ElfW(Addr)) l;
/* The got[2] entry contains the address of a function which gets
called to get the address of a so far unresolved function and
@@ -117,7 +118,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
end in this function. */
if (__builtin_expect (profile, 0))
{
- got[2] = (Elf64_Addr) &_dl_runtime_profile;
+ *(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_profile;
if (GLRO(dl_profile) != NULL
&& _dl_name_match_p (GLRO(dl_profile), l))
@@ -128,12 +129,12 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
else
/* This function will get called to fix up the GOT entry indicated by
the offset on the stack, and then jump to the resolved address. */
- got[2] = (Elf64_Addr) &_dl_runtime_resolve;
+ *(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_resolve;
}
if (l->l_info[ADDRIDX (DT_TLSDESC_GOT)] && lazy)
- *(Elf64_Addr*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_GOT)]) + l->l_addr)
- = (Elf64_Addr) &_dl_tlsdesc_resolve_rela;
+ *(ElfW(Addr)*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_GOT)]) + l->l_addr)
+ = (ElfW(Addr)) &_dl_tlsdesc_resolve_rela;
return lazy;
}
@@ -210,7 +211,7 @@ _dl_start_user:\n\
// XXX This is a work-around for a broken linker. Remove!
#define ELF_MACHINE_IRELATIVE R_X86_64_IRELATIVE
-/* The x86-64 never uses Elf64_Rel relocations. */
+/* The x86-64 never uses Elf64_Rel/Elf32_Rel relocations. */
#define ELF_MACHINE_NO_REL 1
/* We define an initialization function. This is called very early in
@@ -225,19 +226,19 @@ dl_platform_init (void)
GLRO(dl_platform) = NULL;
}
-static inline Elf64_Addr
+static inline ElfW(Addr)
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
- const Elf64_Rela *reloc,
- Elf64_Addr *reloc_addr, Elf64_Addr value)
+ const ElfW(Rela) *reloc,
+ ElfW(Addr) *reloc_addr, ElfW(Addr) value)
{
return *reloc_addr = value;
}
/* Return the final value of a PLT relocation. On x86-64 the
JUMP_SLOT relocation ignores the addend. */
-static inline Elf64_Addr
-elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
- Elf64_Addr value)
+static inline ElfW(Addr)
+elf_machine_plt_value (struct link_map *map, const ElfW(Rela) *reloc,
+ ElfW(Addr) value)
{
return value;
}
@@ -256,12 +257,12 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
auto inline void
__attribute__ ((always_inline))
-elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
- const Elf64_Sym *sym, const struct r_found_version *version,
+elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
+ const ElfW(Sym) *sym, const struct r_found_version *version,
void *const reloc_addr_arg, int skip_ifunc)
{
- Elf64_Addr *const reloc_addr = reloc_addr_arg;
- const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
+ ElfW(Addr) *const reloc_addr = reloc_addr_arg;
+ const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
# if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
if (__builtin_expect (r_type == R_X86_64_RELATIVE, 0))
@@ -282,23 +283,30 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
}
else
# endif
+# if !defined RTLD_BOOTSTRAP
+ /* l_addr + r_addend may be > 0xffffffff and R_X86_64_RELATIVE64
+ relocation updates the whole 64-bit entry. */
+ if (__builtin_expect (r_type == R_X86_64_RELATIVE64, 0))
+ *(Elf64_Addr *) reloc_addr = (Elf64_Addr) map->l_addr + reloc->r_addend;
+ else
+# endif
if (__builtin_expect (r_type == R_X86_64_NONE, 0))
return;
else
{
# ifndef RTLD_BOOTSTRAP
- const Elf64_Sym *const refsym = sym;
+ const ElfW(Sym) *const refsym = sym;
# endif
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
- Elf64_Addr value = (sym == NULL ? 0
- : (Elf64_Addr) sym_map->l_addr + sym->st_value);
+ ElfW(Addr) value = (sym == NULL ? 0
+ : (ElfW(Addr)) sym_map->l_addr + sym->st_value);
if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
0)
&& __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
&& __builtin_expect (!skip_ifunc, 1))
- value = ((Elf64_Addr (*) (void)) value) ();
+ value = ((ElfW(Addr) (*) (void)) value) ();
switch (r_type)
{
@@ -327,7 +335,19 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
/* During relocation all TLS symbols are defined and used.
Therefore the offset is already correct. */
if (sym != NULL)
- *reloc_addr = sym->st_value + reloc->r_addend;
+ {
+ value = sym->st_value + reloc->r_addend;
+# ifdef __ILP32__
+ /* This relocation type computes a signed offset that is
+ usually negative. The symbol and addend values are 32
+ bits but the GOT entry is 64 bits wide and the whole
+ 64-bit entry is used as a signed quantity, so we need
+ to sign-extend the computed value to 64 bits. */
+ *(Elf64_Sxword *) reloc_addr = (Elf64_Sxword) (Elf32_Sword) value;
+# else
+ *reloc_addr = value;
+# endif
+ }
# endif
break;
case R_X86_64_TLSDESC:
@@ -377,15 +397,26 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
/* We know the offset of the object the symbol is contained in.
It is a negative value which will be added to the
thread pointer. */
- *reloc_addr = (sym->st_value + reloc->r_addend
- - sym_map->l_tls_offset);
+ value = (sym->st_value + reloc->r_addend
+ - sym_map->l_tls_offset);
+# ifdef __ILP32__
+ /* The symbol and addend values are 32 bits but the GOT
+ entry is 64 bits wide and the whole 64-bit entry is used
+ as a signed quantity, so we need to sign-extend the
+ computed value to 64 bits. */
+ *(Elf64_Sxword *) reloc_addr = (Elf64_Sxword) (Elf32_Sword) value;
+# else
+ *reloc_addr = value;
+# endif
}
break;
# endif
# ifndef RTLD_BOOTSTRAP
case R_X86_64_64:
- *reloc_addr = value + reloc->r_addend;
+ /* value + r_addend may be > 0xffffffff and R_X86_64_64
+ relocation updates the whole 64-bit entry. */
+ *(Elf64_Addr *) reloc_addr = (Elf64_Addr) value + reloc->r_addend;
break;
case R_X86_64_32:
value += reloc->r_addend;
@@ -411,7 +442,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
# ifndef RESOLVE_CONFLICT_FIND_MAP
/* Not needed for dl-conflict.c. */
case R_X86_64_PC32:
- value += reloc->r_addend - (Elf64_Addr) reloc_addr;
+ value += reloc->r_addend - (ElfW(Addr)) reloc_addr;
*(unsigned int *) reloc_addr = value;
if (__builtin_expect (value != (int) value, 0))
{
@@ -439,7 +470,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
# endif
case R_X86_64_IRELATIVE:
value = map->l_addr + reloc->r_addend;
- value = ((Elf64_Addr (*) (void)) value) ();
+ value = ((ElfW(Addr) (*) (void)) value) ();
*reloc_addr = value;
break;
default:
@@ -452,22 +483,31 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
auto inline void
__attribute ((always_inline))
-elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
+elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
void *const reloc_addr_arg)
{
- Elf64_Addr *const reloc_addr = reloc_addr_arg;
- assert (ELF64_R_TYPE (reloc->r_info) == R_X86_64_RELATIVE);
- *reloc_addr = l_addr + reloc->r_addend;
+ ElfW(Addr) *const reloc_addr = reloc_addr_arg;
+#if !defined RTLD_BOOTSTRAP
+ /* l_addr + r_addend may be > 0xffffffff and R_X86_64_RELATIVE64
+ relocation updates the whole 64-bit entry. */
+ if (__builtin_expect (ELFW(R_TYPE) (reloc->r_info) == R_X86_64_RELATIVE64, 0))
+ *(Elf64_Addr *) reloc_addr = (Elf64_Addr) l_addr + reloc->r_addend;
+ else
+#endif
+ {
+ assert (ELFW(R_TYPE) (reloc->r_info) == R_X86_64_RELATIVE);
+ *reloc_addr = l_addr + reloc->r_addend;
+ }
}
auto inline void
__attribute ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf64_Addr l_addr, const Elf64_Rela *reloc,
+ ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
int skip_ifunc)
{
- Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
- const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
+ ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
+ const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
/* Check for unexpected PLT reloc type. */
if (__builtin_expect (r_type == R_X86_64_JUMP_SLOT, 1))
@@ -477,7 +517,7 @@ elf_machine_lazy_rel (struct link_map *map,
else
*reloc_addr =
map->l_mach.plt
- + (((Elf64_Addr) reloc_addr) - map->l_mach.gotplt) * 2;
+ + (((ElfW(Addr)) reloc_addr) - map->l_mach.gotplt) * 2;
}
else if (__builtin_expect (r_type == R_X86_64_TLSDESC, 1))
{
@@ -490,9 +530,9 @@ elf_machine_lazy_rel (struct link_map *map,
}
else if (__builtin_expect (r_type == R_X86_64_IRELATIVE, 0))
{
- Elf64_Addr value = map->l_addr + reloc->r_addend;
+ ElfW(Addr) value = map->l_addr + reloc->r_addend;
if (__builtin_expect (!skip_ifunc, 1))
- value = ((Elf64_Addr (*) (void)) value) ();
+ value = ((ElfW(Addr) (*) (void)) value) ();
*reloc_addr = value;
}
else
diff --git a/libc/sysdeps/x86_64/dl-trampoline.S b/libc/sysdeps/x86_64/dl-trampoline.S
index 769166286..6185ba487 100644
--- a/libc/sysdeps/x86_64/dl-trampoline.S
+++ b/libc/sysdeps/x86_64/dl-trampoline.S
@@ -20,6 +20,10 @@
#include <sysdep.h>
#include <link-defines.h>
+#if (RTLD_SAVESPACE_SSE % 32) != 0
+# error RTLD_SAVESPACE_SSE must be aligned to 32 bytes
+#endif
+
.text
.globl _dl_runtime_resolve
.type _dl_runtime_resolve, @function
diff --git a/libc/sysdeps/x86_64/fpu/bits/mathinline.h b/libc/sysdeps/x86_64/fpu/bits/mathinline.h
index c072f16a2..49a199b60 100644
--- a/libc/sysdeps/x86_64/fpu/bits/mathinline.h
+++ b/libc/sysdeps/x86_64/fpu/bits/mathinline.h
@@ -79,7 +79,11 @@ __MATH_INLINE long int
__NTH (lrintf (float __x))
{
long int __res;
- __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
+ /* Mark as volatile since the result is dependend on the state of
+ the SSE control register (the rounding mode). Otherwise GCC might
+ remove these assembler instructions since it does not know about
+ the rounding mode change and cannot currently be told. */
+ __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
return __res;
}
# endif
@@ -88,7 +92,11 @@ __MATH_INLINE long int
__NTH (lrint (double __x))
{
long int __res;
- __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
+ /* Mark as volatile since the result is dependend on the state of
+ the SSE control register (the rounding mode). Otherwise GCC might
+ remove these assembler instructions since it does not know about
+ the rounding mode change and cannot currently be told. */
+ __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
return __res;
}
# endif
@@ -97,14 +105,22 @@ __MATH_INLINE long long int
__NTH (llrintf (float __x))
{
long long int __res;
- __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
+ /* Mark as volatile since the result is dependend on the state of
+ the SSE control register (the rounding mode). Otherwise GCC might
+ remove these assembler instructions since it does not know about
+ the rounding mode change and cannot currently be told. */
+ __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
return __res;
}
__MATH_INLINE long long int
__NTH (llrint (double __x))
{
long long int __res;
- __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
+ /* Mark as volatile since the result is dependend on the state of
+ the SSE control register (the rounding mode). Otherwise GCC might
+ remove these assembler instructions since it does not know about
+ the rounding mode change and cannot currently be told. */
+ __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
return __res;
}
# endif
@@ -176,14 +192,22 @@ __MATH_INLINE double
__NTH (rint (double __x))
{
double __res;
- __asm ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x));
+ /* Mark as volatile since the result is dependend on the state of
+ the SSE control register (the rounding mode). Otherwise GCC might
+ remove these assembler instructions since it does not know about
+ the rounding mode change and cannot currently be told. */
+ __asm __volatile__ ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x));
return __res;
}
__MATH_INLINE float
__NTH (rintf (float __x))
{
float __res;
- __asm ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x));
+ /* Mark as volatile since the result is dependend on the state of
+ the SSE control register (the rounding mode). Otherwise GCC might
+ remove these assembler instructions since it does not know about
+ the rounding mode change and cannot currently be told. */
+ __asm __volatile__ ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x));
return __res;
}
@@ -193,14 +217,22 @@ __MATH_INLINE double
__NTH (nearbyint (double __x))
{
double __res;
- __asm ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
+ /* Mark as volatile since the result is dependend on the state of
+ the SSE control register (the rounding mode). Otherwise GCC might
+ remove these assembler instructions since it does not know about
+ the rounding mode change and cannot currently be told. */
+ __asm __volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
return __res;
}
__MATH_INLINE float
__NTH (nearbyintf (float __x))
{
float __res;
- __asm ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
+ /* Mark as volatile since the result is dependend on the state of
+ the SSE control register (the rounding mode). Otherwise GCC might
+ remove these assembler instructions since it does not know about
+ the rounding mode change and cannot currently be told. */
+ __asm __volatile__ ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
return __res;
}
# endif
diff --git a/libc/sysdeps/x86_64/fpu/e_exp10l.S b/libc/sysdeps/x86_64/fpu/e_exp10l.S
new file mode 100644
index 000000000..d843e2b5e
--- /dev/null
+++ b/libc/sysdeps/x86_64/fpu/e_exp10l.S
@@ -0,0 +1,2 @@
+#define USE_AS_EXP10L
+#include <e_expl.S>
diff --git a/libc/sysdeps/x86_64/fpu/e_expl.S b/libc/sysdeps/x86_64/fpu/e_expl.S
index d497b2897..e6b842bf2 100644
--- a/libc/sysdeps/x86_64/fpu/e_expl.S
+++ b/libc/sysdeps/x86_64/fpu/e_expl.S
@@ -24,9 +24,33 @@
#include <machine/asm.h>
+#ifdef USE_AS_EXP10L
+# define IEEE754_EXPL __ieee754_exp10l
+# define EXPL_FINITE __exp10l_finite
+# define FLDLOG fldl2t
+#elif defined USE_AS_EXPM1L
+# define IEEE754_EXPL __expm1l
+# undef EXPL_FINITE
+# define FLDLOG fldl2e
+#else
+# define IEEE754_EXPL __ieee754_expl
+# define EXPL_FINITE __expl_finite
+# define FLDLOG fldl2e
+#endif
+
.section .rodata.cst16,"aM",@progbits,16
.p2align 4
+#ifdef USE_AS_EXP10L
+ ASM_TYPE_DIRECTIVE(c0,@object)
+c0: .byte 0, 0, 0, 0, 0, 0, 0x9a, 0xd4, 0x00, 0x40
+ .byte 0, 0, 0, 0, 0, 0
+ ASM_SIZE_DIRECTIVE(c0)
+ ASM_TYPE_DIRECTIVE(c1,@object)
+c1: .byte 0x58, 0x92, 0xfc, 0x15, 0x37, 0x9a, 0x97, 0xf0, 0xef, 0x3f
+ .byte 0, 0, 0, 0, 0, 0
+ ASM_SIZE_DIRECTIVE(c1)
+#else
ASM_TYPE_DIRECTIVE(c0,@object)
c0: .byte 0, 0, 0, 0, 0, 0, 0xaa, 0xb8, 0xff, 0x3f
.byte 0, 0, 0, 0, 0, 0
@@ -35,6 +59,7 @@ c0: .byte 0, 0, 0, 0, 0, 0, 0xaa, 0xb8, 0xff, 0x3f
c1: .byte 0x20, 0xfa, 0xee, 0xc2, 0x5f, 0x70, 0xa5, 0xec, 0xed, 0x3f
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(c1)
+#endif
ASM_TYPE_DIRECTIVE(csat,@object)
csat: .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0e, 0x40
.byte 0, 0, 0, 0, 0, 0
@@ -47,14 +72,22 @@ csat: .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0e, 0x40
#endif
.text
-ENTRY(__ieee754_expl)
+ENTRY(IEEE754_EXPL)
+#ifdef USE_AS_EXPM1L
+ movzwl 8+8(%rsp), %eax
+ xorb $0x80, %ah // invert sign bit (now 1 is "positive")
+ cmpl $0xc006, %eax // is num positive and exp >= 6 (number is >= 128.0)?
+ jae HIDDEN_JUMPTARGET (__expl) // (if num is denormal, it is at least >= 64.0)
+#endif
fldt 8(%rsp)
/* I added the following ugly construct because expl(+-Inf) resulted
in NaN. The ugliness results from the bright minds at Intel.
For the i686 the code can be written better.
-- drepper@cygnus.com. */
fxam /* Is NaN or +-Inf? */
+#ifndef USE_AS_EXPM1L
movzwl 8+8(%rsp), %eax
+#endif
andl $0x7fff, %eax
cmpl $0x400d, %eax
jle 3f
@@ -72,8 +105,17 @@ ENTRY(__ieee754_expl)
andb $2, %ah
jz 3f
fchs
-3: fldl2e /* 1 log2(e) */
- fmul %st(1), %st /* 1 x log2(e) */
+3:
+#ifdef USE_AS_EXPM1L
+ /* Test for +-0 as argument. */
+ fstsw %ax
+ movb $0x45, %dh
+ andb %ah, %dh
+ cmpb $0x40, %dh
+ je 2f
+#endif
+ FLDLOG /* 1 log2(base) */
+ fmul %st(1), %st /* 1 x log2(base) */
frndint /* 1 i */
fld %st(1) /* 2 x */
frndint /* 2 xi */
@@ -89,18 +131,40 @@ ENTRY(__ieee754_expl)
fldt MO(c1) /* 4 */
fmul %st(4), %st /* 4 c1 * x */
faddp %st, %st(1) /* 3 f = f + c1 * x */
- f2xm1 /* 3 2^(fract(x * log2(e))) - 1 */
+ f2xm1 /* 3 2^(fract(x * log2(base))) - 1 */
+#ifdef USE_AS_EXPM1L
+ fstp %st(1) /* 2 */
+ fscale /* 2 scale factor is st(1); base^x - 2^i */
+ fxch /* 2 i */
+ fld1 /* 3 1.0 */
+ fscale /* 3 2^i */
+ fld1 /* 4 1.0 */
+ fsubrp %st, %st(1) /* 3 2^i - 1.0 */
+ fstp %st(1) /* 2 */
+ faddp %st, %st(1) /* 1 base^x - 1.0 */
+#else
fld1 /* 4 1.0 */
- faddp /* 3 2^(fract(x * log2(e))) */
+ faddp /* 3 2^(fract(x * log2(base))) */
fstp %st(1) /* 2 */
- fscale /* 2 scale factor is st(1); e^x */
+ fscale /* 2 scale factor is st(1); base^x */
fstp %st(1) /* 1 */
+#endif
fstp %st(1) /* 0 */
jmp 2f
1: testl $0x200, %eax /* Test sign. */
jz 2f /* If positive, jump. */
fstp %st
+#ifdef USE_AS_EXPM1L
+ fld1
+ fchs
+#else
fldz /* Set result to 0. */
+#endif
2: ret
-END(__ieee754_expl)
-strong_alias (__ieee754_expl, __expl_finite)
+END(IEEE754_EXPL)
+#ifdef USE_AS_EXPM1L
+libm_hidden_def (__expm1l)
+weak_alias (__expm1l, expm1l)
+#else
+strong_alias (IEEE754_EXPL, EXPL_FINITE)
+#endif
diff --git a/libc/sysdeps/x86_64/fpu/libm-test-ulps b/libc/sysdeps/x86_64/fpu/libm-test-ulps
index 9a1e80ed8..9bb26d1fe 100644
--- a/libc/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/libc/sysdeps/x86_64/fpu/libm-test-ulps
@@ -7,15 +7,21 @@ ldouble: 1
# acos_downward
Test "acos_downward (-0) == pi/2":
+float: 1
+ifloat: 1
ildouble: 1
ldouble: 1
Test "acos_downward (-0.5) == M_PI_6l*4.0":
double: 1
idouble: 1
Test "acos_downward (-1) == pi":
+float: 1
+ifloat: 1
ildouble: 1
ldouble: 1
Test "acos_downward (0) == pi/2":
+float: 1
+ifloat: 1
ildouble: 1
ldouble: 1
Test "acos_downward (0.5) == M_PI_6l*2.0":
@@ -26,15 +32,21 @@ ifloat: 1
# acos_towardzero
Test "acos_towardzero (-0) == pi/2":
+float: 1
+ifloat: 1
ildouble: 1
ldouble: 1
Test "acos_towardzero (-0.5) == M_PI_6l*4.0":
double: 1
idouble: 1
Test "acos_towardzero (-1) == pi":
+float: 1
+ifloat: 1
ildouble: 1
ldouble: 1
Test "acos_towardzero (0) == pi/2":
+float: 1
+ifloat: 1
ildouble: 1
ldouble: 1
Test "acos_towardzero (0.5) == M_PI_6l*2.0":
@@ -1275,6 +1287,12 @@ idouble: 2
ifloat: 1
ildouble: 1
ldouble: 1
+Test "exp10 (-305) == 1.0e-305":
+double: 1
+idouble: 1
+Test "exp10 (-36) == 1.0e-36":
+double: 1
+idouble: 1
Test "exp10 (0.75) == 5.62341325190349080394951039776481231":
double: 1
float: 1
@@ -1289,6 +1307,9 @@ idouble: 6
ifloat: 2
ildouble: 8
ldouble: 8
+Test "exp10 (36) == 1.0e36":
+double: 1
+idouble: 1
# exp_downward
Test "exp_downward (1) == e":
@@ -1337,6 +1358,9 @@ ifloat: 1
Test "expm1 (11356.25) == 9.05128237311923300051376115753226014206e+4931":
ildouble: 1
ldouble: 1
+Test "expm1 (500.0) == 1.4035922178528374107397703328409120821806e+217":
+double: 1
+idouble: 1
# gamma
Test "gamma (-0.5) == log(2*sqrt(pi))":
@@ -1810,62 +1834,47 @@ Test "sincos (pi/6, &sin_res, &cos_res) puts 0.866025403784438646763723170752936
float: 1
ifloat: 1
-# sinh
-Test "sinh (0x8p-32) == 1.86264514923095703232705808926175479e-9":
-ildouble: 1
-ldouble: 1
-
# sinh_downward
Test "sinh_downward (22) == 1792456423.065795780701106568345764104225":
float: 1
ifloat: 1
-ildouble: 4
-ldouble: 4
+ildouble: 2
+ldouble: 2
Test "sinh_downward (23) == 4872401723.124451299966006944252978187305":
float: 1
ifloat: 1
+ildouble: 2
+ldouble: 2
Test "sinh_downward (24) == 13244561064.92173614705070540368454568168":
float: 1
ifloat: 1
-ildouble: 5
-ldouble: 5
-
-# sinh_tonearest
-Test "sinh_tonearest (22) == 1792456423.065795780701106568345764104225":
-ildouble: 3
-ldouble: 3
-Test "sinh_tonearest (23) == 4872401723.124451299966006944252978187305":
-ildouble: 1
-ldouble: 1
-Test "sinh_tonearest (24) == 13244561064.92173614705070540368454568168":
-ildouble: 6
-ldouble: 6
+ildouble: 2
+ldouble: 2
# sinh_towardzero
Test "sinh_towardzero (22) == 1792456423.065795780701106568345764104225":
float: 1
ifloat: 1
-ildouble: 4
-ldouble: 4
+ildouble: 2
+ldouble: 2
Test "sinh_towardzero (23) == 4872401723.124451299966006944252978187305":
float: 1
ifloat: 1
+ildouble: 2
+ldouble: 2
Test "sinh_towardzero (24) == 13244561064.92173614705070540368454568168":
float: 1
ifloat: 1
-ildouble: 5
-ldouble: 5
+ildouble: 2
+ldouble: 2
# sinh_upward
Test "sinh_upward (22) == 1792456423.065795780701106568345764104225":
-ildouble: 16
-ldouble: 16
+ildouble: 1
+ldouble: 1
Test "sinh_upward (23) == 4872401723.124451299966006944252978187305":
-ildouble: 27
-ldouble: 27
-Test "sinh_upward (24) == 13244561064.92173614705070540368454568168":
-ildouble: 7
-ldouble: 7
+ildouble: 1
+ldouble: 1
# tan
Test "tan (0x1p16383) == 0.422722393732022337800504160054440141575":
@@ -2712,29 +2721,21 @@ ifloat: 1
ildouble: 1
ldouble: 1
-Function: "sinh":
-ildouble: 1
-ldouble: 1
-
Function: "sinh_downward":
float: 1
ifloat: 1
-ildouble: 5
-ldouble: 5
-
-Function: "sinh_tonearest":
-ildouble: 6
-ldouble: 6
+ildouble: 2
+ldouble: 2
Function: "sinh_towardzero":
float: 1
ifloat: 1
-ildouble: 5
-ldouble: 5
+ildouble: 2
+ldouble: 2
Function: "sinh_upward":
-ildouble: 27
-ldouble: 27
+ildouble: 1
+ldouble: 1
Function: "tan":
double: 1
diff --git a/libc/sysdeps/x86_64/fpu/s_expm1l.S b/libc/sysdeps/x86_64/fpu/s_expm1l.S
index 1380f34f0..7fbd99b0d 100644
--- a/libc/sysdeps/x86_64/fpu/s_expm1l.S
+++ b/libc/sysdeps/x86_64/fpu/s_expm1l.S
@@ -1,85 +1,2 @@
-/* ix87 specific implementation of exp(x)-1.
- Copyright (C) 1996,1997,2001,2002,2008,2009,2012 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
- Based on code by John C. Bowman <bowman@ipp-garching.mpg.de>.
- Corrections by H.J. Lu (hjl@gnu.ai.mit.edu), 1997.
-
- 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/>. */
-
- /* Using: e^x - 1 = 2^(x * log2(e)) - 1 */
-
-#include <machine/asm.h>
-
- .section .rodata
-
- .align ALIGNARG(4)
- ASM_TYPE_DIRECTIVE(minus1,@object)
-minus1: .double -1.0
- ASM_SIZE_DIRECTIVE(minus1)
- ASM_TYPE_DIRECTIVE(one,@object)
-one: .double 1.0
- ASM_SIZE_DIRECTIVE(one)
- ASM_TYPE_DIRECTIVE(l2e,@object)
-l2e: .tfloat 1.442695040888963407359924681002
- ASM_SIZE_DIRECTIVE(l2e)
-
-#ifdef PIC
-#define MO(op) op##(%rip)
-#else
-#define MO(op) op
-#endif
-
- .text
-ENTRY(__expm1l)
- movzwl 8+8(%rsp), %eax // load sign bit and 15-bit exponent
- xorb $0x80, %ah // invert sign bit (now 1 is "positive")
- cmpl $0xc006, %eax // is num positive and exp >= 6 (number is >= 128.0)?
- jae __expl // (if num is denormal, it is at least >= 64.0)
-
- fldt 8(%rsp) // x
- fxam // Is NaN or +-Inf?
- fstsw %ax
- movb $0x45, %ch
- andb %ah, %ch
- cmpb $0x40, %ch
- je 3f // If +-0, jump.
- cmpb $0x05, %ch
- je 2f // If +-Inf, jump.
-
- fldt MO(l2e) // log2(e) : x
- fmulp // log2(e)*x
- fld %st // log2(e)*x : log2(e)*x
- frndint // int(log2(e)*x) : log2(e)*x
- fsubr %st, %st(1) // int(log2(e)*x) : fract(log2(e)*x)
- fxch // fract(log2(e)*x) : int(log2(e)*x)
- f2xm1 // 2^fract(log2(e)*x)-1 : int(log2(e)*x)
- fscale // 2^(log2(e)*x)-2^int(log2(e)*x) : int(log2(e)*x)
- fxch // int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fldl MO(one) // 1 : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fscale // 2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fsubrl MO(one) // 1-2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fstp %st(1) // 1-2^int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
- fsubrp %st, %st(1) // 2^(log2(e)*x)-1
- ret
-
-2: testl $0x200, %eax // Test sign.
- jz 3f // If positive, jump.
- fstp %st
- fldl MO(minus1) // Set result to -1.0.
-3: ret
-END(__expm1l)
-libm_hidden_def (__expm1l)
-weak_alias (__expm1l, expm1l)
+#define USE_AS_EXPM1L
+#include <e_expl.S>
diff --git a/libc/sysdeps/x86_64/tst-quad1.c b/libc/sysdeps/x86_64/tst-quad1.c
new file mode 100644
index 000000000..a8567ea8a
--- /dev/null
+++ b/libc/sysdeps/x86_64/tst-quad1.c
@@ -0,0 +1,25 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+extern void foo (void);
+
+int
+main (void)
+{
+ foo ();
+ return 0;
+}
diff --git a/libc/sysdeps/x86_64/tst-quad1pie.c b/libc/sysdeps/x86_64/tst-quad1pie.c
new file mode 100644
index 000000000..f5fd45f9b
--- /dev/null
+++ b/libc/sysdeps/x86_64/tst-quad1pie.c
@@ -0,0 +1 @@
+#include "tst-quad1.c"
diff --git a/libc/sysdeps/x86_64/tst-quad2.c b/libc/sysdeps/x86_64/tst-quad2.c
new file mode 100644
index 000000000..f5fd45f9b
--- /dev/null
+++ b/libc/sysdeps/x86_64/tst-quad2.c
@@ -0,0 +1 @@
+#include "tst-quad1.c"
diff --git a/libc/sysdeps/x86_64/tst-quad2pie.c b/libc/sysdeps/x86_64/tst-quad2pie.c
new file mode 100644
index 000000000..a15d8d36a
--- /dev/null
+++ b/libc/sysdeps/x86_64/tst-quad2pie.c
@@ -0,0 +1 @@
+#include "tst-quad2.c"
diff --git a/libc/sysdeps/x86_64/tst-quadmod1.S b/libc/sysdeps/x86_64/tst-quadmod1.S
new file mode 100644
index 000000000..0e691be80
--- /dev/null
+++ b/libc/sysdeps/x86_64/tst-quadmod1.S
@@ -0,0 +1,44 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef BIAS
+# define BIAS 0x7fffffff
+#endif
+
+ .section .data.rel,"aw",@progbits
+ .align 8
+.Ljmp:
+ .quad func + BIAS
+ .text
+ .globl func
+ .type func, @function
+func:
+ .cfi_startproc
+ xorl %edi, %edi
+ jmp exit@PLT
+ .cfi_endproc
+ .size func, .-func
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ .cfi_def_cfa_register 6
+ movq .Ljmp(%rip), %rax
+ subq $BIAS, %rax
+ jmp *%rax
+ .cfi_endproc
+ .size foo, .-foo
diff --git a/libc/sysdeps/x86_64/tst-quadmod1pie.S b/libc/sysdeps/x86_64/tst-quadmod1pie.S
new file mode 100644
index 000000000..c671d0cda
--- /dev/null
+++ b/libc/sysdeps/x86_64/tst-quadmod1pie.S
@@ -0,0 +1,2 @@
+#define BIAS 0x7fff0000
+#include "tst-quadmod1.S"
diff --git a/libc/sysdeps/x86_64/tst-quadmod2.S b/libc/sysdeps/x86_64/tst-quadmod2.S
new file mode 100644
index 000000000..38ab9598b
--- /dev/null
+++ b/libc/sysdeps/x86_64/tst-quadmod2.S
@@ -0,0 +1,43 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef BIAS
+# define BIAS 0x7fff0000
+#endif
+
+ .section .data.rel.local,"aw",@progbits
+ .align 8
+.Ljmp:
+ .quad func + BIAS
+ .text
+ .type func, @function
+func:
+ .cfi_startproc
+ xorl %edi, %edi
+ jmp exit@PLT
+ .cfi_endproc
+ .size func, .-func
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ .cfi_def_cfa_register 6
+ movq .Ljmp(%rip), %rax
+ subq $BIAS, %rax
+ jmp *%rax
+ .cfi_endproc
+ .size foo, .-foo
diff --git a/libc/sysdeps/x86_64/tst-quadmod2pie.S b/libc/sysdeps/x86_64/tst-quadmod2pie.S
new file mode 100644
index 000000000..609183fe5
--- /dev/null
+++ b/libc/sysdeps/x86_64/tst-quadmod2pie.S
@@ -0,0 +1 @@
+#include "tst-quadmod2.S"