about summary refs log tree commit diff
path: root/sysdeps/unix
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/make-syscalls.sh142
-rw-r--r--sysdeps/unix/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/dl-vdso.h11
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/gettimeofday.c7
-rw-r--r--sysdeps/unix/sysv/linux/s390/gettimeofday.c7
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/gettimeofday.c25
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list2
7 files changed, 131 insertions, 65 deletions
diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh
index 48aab629f5..cedce3193c 100644
--- a/sysdeps/unix/make-syscalls.sh
+++ b/sysdeps/unix/make-syscalls.sh
@@ -64,10 +64,67 @@ done`
 # Any calls left?
 test -n "$calls" || exit 0
 
+# This uses variables $weak and $strong.
+emit_weak_aliases()
+{
+  # A shortcoming in the current gas is that it will only allow one
+  # version-alias per symbol.  So we create new strong aliases as needed.
+  vcount=""
+
+  for name in $weak; do
+    case $name in
+      *@@*)
+	base=`echo $name | sed 's/@@.*//'`
+	ver=`echo $name | sed 's/.*@@//'`
+	if test -z "$vcount" ; then
+	  source=$strong
+	  vcount=1
+	else
+	  source="${strong}_${vcount}"
+	  vcount=`expr $vcount + 1`
+	  echo "	 echo 'strong_alias ($strong, $source)'; \\"
+	fi
+	echo "	 echo 'default_symbol_version($source, $base, $ver)'; \\"
+	;;
+      *@*)
+	base=`echo $name | sed 's/@.*//'`
+	ver=`echo $name | sed 's/.*@//'`
+	if test -z "$vcount" ; then
+	  source=$strong
+	  vcount=1
+	else
+	  source="${strong}_${vcount}"
+	  vcount=`expr $vcount + 1`
+	  echo "	 echo 'strong_alias ($strong, $source)'; \\"
+	fi
+	echo "	 echo 'symbol_version ($source, $base, $ver)'; \\"
+	;;
+      !*)
+	name=`echo $name | sed 's/.//'`
+	echo "	 echo 'strong_alias ($strong, $name)'; \\"
+	echo "	 echo 'libc_hidden_def ($name)'; \\"
+	;;
+      *)
+	echo "	 echo 'weak_alias ($strong, $name)'; \\"
+	echo "	 echo 'libc_hidden_weak ($name)'; \\"
+	;;
+    esac
+  done
+}
+
+
 # Emit rules to compile the syscalls remaining in $calls.
 echo "$calls" |
 while read file srcfile caller syscall args strong weak; do
 
+  vdso_syscall=
+  case x"$syscall" in
+  *:*@*)
+    vdso_syscall="${syscall#*:}"
+    syscall="${syscall%:*}"
+    ;;
+  esac
+
   case x"$syscall" in
   x-) callnum=_ ;;
   *)
@@ -144,13 +201,14 @@ while read file srcfile caller syscall args strong weak; do
   # Emit a compilation rule for this syscall.
   if test $shared_only = t; then
     # The versioned symbols are only in the shared library.
-    echo "\
-shared-only-routines += $file
-\$(objpfx)${file}.os: \\"
+    echo "shared-only-routines += $file"
+    test -n "$vdso_syscall" || echo "\$(objpfx)${file}.os: \\"
   else
+    object_suffixes='$(object-suffixes)'
+    test -z "$vdso_syscall" || object_suffixes='$(object-suffixes-noshared)'
     echo "\
 \$(foreach p,\$(sysd-rules-targets),\
-\$(foreach o,\$(object-suffixes),\$(objpfx)\$(patsubst %,\$p,$file)\$o)): \\"
+\$(foreach o,${object_suffixes},\$(objpfx)\$(patsubst %,\$p,$file)\$o)): \\"
   fi
 
   echo "		\$(..)sysdeps/unix/make-syscalls.sh"
@@ -178,55 +236,43 @@ shared-only-routines += $file
   esac
 
   # Append any weak aliases or versions defined for this syscall function.
-
-  # A shortcoming in the current gas is that it will only allow one
-  # version-alias per symbol.  So we create new strong aliases as needed.
-  vcount=""
-
-  for name in $weak; do
-    case $name in
-      *@@*)
-	base=`echo $name | sed 's/@@.*//'`
-	ver=`echo $name | sed 's/.*@@//'`
-	if test -z "$vcount" ; then
-	  source=$strong
-	  vcount=1
-	else
-	  source="${strong}_${vcount}"
-	  vcount=`expr $vcount + 1`
-	  echo "	 echo 'strong_alias ($strong, $source)'; \\"
-	fi
-	echo "	 echo 'default_symbol_version($source, $base, $ver)'; \\"
-	;;
-      *@*)
-	base=`echo $name | sed 's/@.*//'`
-	ver=`echo $name | sed 's/.*@//'`
-	if test -z "$vcount" ; then
-	  source=$strong
-	  vcount=1
-	else
-	  source="${strong}_${vcount}"
-	  vcount=`expr $vcount + 1`
-	  echo "	 echo 'strong_alias ($strong, $source)'; \\"
-	fi
-	echo "	 echo 'symbol_version ($source, $base, $ver)'; \\"
-	;;
-      !*)
-	name=`echo $name | sed 's/.//'`
-	echo "	 echo 'strong_alias ($strong, $name)'; \\"
-	echo "	 echo 'libc_hidden_def ($name)'; \\"
-	;;
-      *)
-	echo "	 echo 'weak_alias ($strong, $name)'; \\"
-	echo "	 echo 'libc_hidden_weak ($name)'; \\"
-	;;
-    esac
-  done
+  emit_weak_aliases
 
   # And finally, pipe this all into the compiler.
   echo '	) | $(compile-syscall) '"\
 \$(foreach p,\$(patsubst %$file,%,\$(basename \$(@F))),\$(\$(p)CPPFLAGS))"
 
+  if test -n "$vdso_syscall"; then
+    # In the shared library, we're going to emit an IFUNC using a vDSO function.
+    # $vdso_syscall looks like "name@KERNEL_X.Y" where "name" is the symbol
+    # name in the vDSO and KERNEL_X.Y is its symbol version.
+    vdso_symbol="${vdso_syscall%@*}"
+    vdso_symver="${vdso_syscall#*@}"
+    vdso_symver="${vdso_symver//./_}"
+    echo "\
+\$(foreach p,\$(sysd-rules-targets),\$(objpfx)\$(patsubst %,\$p,$file).os): \\
+		\$(..)sysdeps/unix/make-syscalls.sh\
+	\$(make-target-directory)
+	(echo '#include <dl-vdso.h>'; \\
+	 echo 'extern void *${strong}_ifunc (void) __asm (\"${strong}\");'; \\
+	 echo 'void *'; \\
+	 echo '${strong}_ifunc (void)'; \\
+	 echo '{'; \\
+	 echo '  PREPARE_VERSION_KNOWN (symver, ${vdso_symver});'; \\
+	 echo '  return _dl_vdso_vsym (\"${vdso_symbol}\", &symver);'; \\
+	 echo '}'; \\
+	 echo 'asm (\".type ${strong}, %gnu_indirect_function\");'; \\"
+    # This is doing "libc_hidden_def (${strong})", but the compiler
+    # doesn't know that we've defined ${strong} in the same file, so
+    # we can't do it the normal way.
+    echo "\
+	 echo 'asm (\".globl __GI_${strong}\\n\"'; \\
+	 echo '     \"__GI_${strong} = ${strong}\");'; \\"
+    emit_weak_aliases
+    echo '	) | $(compile-stdin.c) '"\
+\$(foreach p,\$(patsubst %$file,%,\$(basename \$(@F))),\$(\$(p)CPPFLAGS))"
+  fi
+
   if test $shared_only = t; then
     # The versioned symbols are only in the shared library.
     echo endif
diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
index 39c40ed7f6..bd780f5695 100644
--- a/sysdeps/unix/syscalls.list
+++ b/sysdeps/unix/syscalls.list
@@ -26,7 +26,7 @@ getpid		-	getpid		Ei:	__getpid	getpid
 getpriority	-	getpriority	i:ii	getpriority
 getrlimit	-	getrlimit	i:ip	__getrlimit	getrlimit
 getrusage	-	getrusage	i:ip	__getrusage	getrusage
-gettimeofday	-	gettimeofday	i:PP	__gettimeofday	gettimeofday __gettimeofday_internal
+gettimeofday	-	gettimeofday	i:pP	__gettimeofday	gettimeofday
 getuid		-	getuid		Ei:	__getuid	getuid
 ioctl		-	ioctl		i:iiI	__ioctl		ioctl
 kill		-	kill		i:ii	__kill		kill
diff --git a/sysdeps/unix/sysv/linux/dl-vdso.h b/sysdeps/unix/sysv/linux/dl-vdso.h
index c30671de72..4149bacdce 100644
--- a/sysdeps/unix/sysv/linux/dl-vdso.h
+++ b/sysdeps/unix/sysv/linux/dl-vdso.h
@@ -33,6 +33,17 @@
   /* We don't have a specific file where the symbol can be found.  */	      \
   var.filename = NULL
 
+/* Use this for the known version sets defined below, where we
+   record their precomputed hash values only once, in this file.  */
+#define PREPARE_VERSION_KNOWN(var, vname) \
+  PREPARE_VERSION (var, VDSO_NAME_##vname, VDSO_HASH_##vname)
+
+#define VDSO_NAME_LINUX_2_6	"LINUX_2.6"
+#define VDSO_HASH_LINUX_2_6	61765110
+#define VDSO_NAME_LINUX_2_6_15	"LINUX_2.6.15"
+#define VDSO_HASH_LINUX_2_6_15	123718565
+#define VDSO_NAME_LINUX_2_6_29	"LINUX_2.6.29"
+#define VDSO_HASH_LINUX_2_6_29	123718585
 
 /* Functions for resolving symbols in the VDSO link map.  */
 extern void *_dl_vdso_vsym (const char *name,
diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
index b2ef2da973..737613516f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005-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,7 +22,6 @@
 #include <time.h>
 #include <hp-timing.h>
 
-#undef __gettimeofday
 #include <bits/libc-vdso.h>
 
 /* Get the current time of day and timezone information,
@@ -36,6 +35,6 @@ __gettimeofday (tv, tz)
 {
   return INLINE_VSYSCALL (gettimeofday, 2, CHECK_1 (tv), CHECK_1 (tz));
 }
-
-INTDEF (__gettimeofday)
+libc_hidden_def (__gettimeofday)
 weak_alias (__gettimeofday, gettimeofday)
+libc_hidden_weak (gettimeofday)
diff --git a/sysdeps/unix/sysv/linux/s390/gettimeofday.c b/sysdeps/unix/sysv/linux/s390/gettimeofday.c
index 63faef85b6..efbf1e8110 100644
--- a/sysdeps/unix/sysv/linux/s390/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/s390/gettimeofday.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2008-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,7 +22,6 @@
 #include <time.h>
 #include <hp-timing.h>
 
-#undef __gettimeofday
 #include <bits/libc-vdso.h>
 
 /* Get the current time of day and timezone information,
@@ -36,6 +35,6 @@ __gettimeofday (tv, tz)
 {
   return INLINE_VSYSCALL (gettimeofday, 2, CHECK_1 (tv), CHECK_1 (tz));
 }
-
-INTDEF (__gettimeofday)
+libc_hidden_def (__gettimeofday)
 weak_alias (__gettimeofday, gettimeofday)
+libc_hidden_weak (gettimeofday)
diff --git a/sysdeps/unix/sysv/linux/x86_64/gettimeofday.c b/sysdeps/unix/sysv/linux/x86_64/gettimeofday.c
index e41fddb297..d52f938e71 100644
--- a/sysdeps/unix/sysv/linux/x86_64/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/x86_64/gettimeofday.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2007, 2011 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
@@ -15,13 +15,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <dl-vdso.h>
+#include <sys/time.h>
 
+#ifdef SHARED
 
-#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000ul
+# include <dl-vdso.h>
 
+# define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000ul
 
-#ifdef SHARED
 void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday");
 
 void *
@@ -33,9 +34,16 @@ gettimeofday_ifunc (void)
   return (_dl_vdso_vsym ("__vdso_gettimeofday", &linux26)
 	  ?: (void *) VSYSCALL_ADDR_vgettimeofday);
 }
-__asm (".type __gettimeofday, %gnu_indirect_function");
+asm (".type __gettimeofday, %gnu_indirect_function");
+
+/* This is doing "libc_hidden_def (__gettimeofday)" but the compiler won't
+   let us do it in C because it doesn't know we're defining __gettimeofday
+   here in this file.  */
+asm (".globl __GI___gettimeofday\n"
+     "__GI___gettimeofday = __gettimeofday");
+
 #else
-# include <sys/time.h>
+
 # include <sysdep.h>
 # include <errno.h>
 
@@ -44,7 +52,8 @@ __gettimeofday (struct timeval *tv, struct timezone *tz)
 {
   return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
 }
-#endif
+libc_hidden_def (__gettimeofday)
 
+#endif
 weak_alias (__gettimeofday, gettimeofday)
-strong_alias (__gettimeofday, __gettimeofday_internal)
+libc_hidden_weak (gettimeofday)
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list b/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list
index 7edb6fd618..2cc58af2df 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list
@@ -1,6 +1,8 @@
 # File name	Caller	Syscall name	# args	Strong name	Weak names
 
 fallocate	-	fallocate	Ci:iiii	fallocate	fallocate64
+gettimeofday	-	gettimeofday:__vdso_gettimeofday@LINUX_2.6	i:pP	__gettimeofday	gettimeofday
 posix_fadvise	-	fadvise64	Vi:iiii	posix_fadvise	posix_fadvise64
 preadv		-	preadv		Ci:ipii	preadv		preadv64
 pwritev		-	pwritev		Ci:ipii	pwritev		pwritev64
+time		-	time:__vdso_time@LINUX_2.6			Ei:P	time