]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
linux: Fix vDSO macros build with time64 interfaces
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 13 Dec 2019 20:30:15 +0000 (17:30 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 3 Jan 2020 13:02:05 +0000 (10:02 -0300)
As indicated on libc-help [1] the ec138c67cb commit broke 32-bit
builds when configured with --enable-kernel=5.1 or higher.  The
scenario 10 from [2] might also occur in this configuration and
INLINE_VSYSCALL will try to use the vDSO symbol and
HAVE_CLOCK_GETTIME64_VSYSCALL does not set HAVE_VSYSCALL prior its
usage.

Also, there is no easy way to just enable the code to use one
vDSO symbol since the macro INLINE_VSYSCALL is redefined if
HAVE_VSYSCALL is set.

Instead of adding more pre-processor handling and making the code
even more convoluted, this patch removes the requirement of defining
HAVE_VSYSCALL before including sysdep-vdso.h to enable vDSO usage.

The INLINE_VSYSCALL is now expected to be issued inside a
HAVE_*_VSYSCALL check, since it will try to use the internal vDSO
pointers.

Both clock_getres and clock_gettime vDSO code for time64_t were
removed since there is no vDSO setup code for the symbol (an
architecture can not set HAVE_CLOCK_GETTIME64_VSYSCALL).

Checked on i686-linux-gnu (default and with --enable-kernel=5.1),
x86_64-linux-gnu, aarch64-linux-gnu, and powerpc64le-linux-gnu.
I also checked against a build to mips64-linux-gnu and
sparc64-linux-gnu.

[1] https://sourceware.org/ml/libc-help/2019-12/msg00014.html
[2] https://sourceware.org/ml/libc-alpha/2019-12/msg00142.html

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
sysdeps/unix/sysv/linux/aarch64/gettimeofday.c
sysdeps/unix/sysv/linux/clock_getres.c
sysdeps/unix/sysv/linux/clock_gettime.c
sysdeps/unix/sysv/linux/getcpu.c
sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
sysdeps/unix/sysv/linux/powerpc/time.c
sysdeps/unix/sysv/linux/sched_getcpu.c
sysdeps/unix/sysv/linux/sysdep-vdso.h
sysdeps/unix/sysv/linux/x86/gettimeofday.c
sysdeps/unix/sysv/linux/x86/time.c

index c53c223a73eb4badc2d72512865283ddc7ac8afa..d50faac054da8da40bfcabf165579274d101d5da 100644 (file)
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 /* Used as a fallback in the ifunc resolver if VDSO is not available
index f55cf39d310f226f1a0a62b728143163d8592854..d3cabfcb2fd2d69d2c70dbbe5bf24bc69e19f28c 100644 (file)
@@ -20,9 +20,6 @@
 #include <errno.h>
 #include <time.h>
 
-#ifdef HAVE_CLOCK_GETRES_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 #include <shlib-compat.h>
 #include <kernel-features.h>
@@ -32,23 +29,34 @@ int
 __clock_getres64 (clockid_t clock_id, struct __timespec64 *res)
 {
 #ifdef __ASSUME_TIME64_SYSCALLS
-# ifndef __NR_clock_getres_time64
-  return INLINE_VSYSCALL (clock_getres, 2, clock_id, res);
+  /* 64 bit ABIs or Newer 32-bit ABIs that only support 64-bit time_t.  */
+# ifdef __NR_clock_getres_time64
+  return INLINE_SYSCALL_CALL (clock_getres_time64, clock_id, res);
 # else
-  return INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res);
+#  ifdef HAVE_CLOCK_GETRES_VSYSCALL
+  return INLINE_VSYSCALL (clock_getres, 2, clock_id, res);
+#  else
+  return INLINE_SYSCALL_CALL (clock_getres, clock_id, res);
+#  endif
 # endif
 #else
+  int r;
+  /* Old 32-bit ABI with possible 64-bit time_t support.  */
 # ifdef __NR_clock_getres_time64
-  int ret = INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res);
-  if (ret == 0 || errno != ENOSYS)
-    return ret;
+  r = INLINE_SYSCALL_CALL (clock_getres_time64, clock_id, res);
+  if (r == 0 || errno != ENOSYS)
+    return r;
 # endif
+  /* Fallback code that uses 32-bit support.  */
   struct timespec ts32;
-  int retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);
-  if (! retval && res)
+# ifdef HAVE_CLOCK_GETRES_VSYSCALL
+  r = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);
+# else
+  r = INLINE_SYSCALL_CALL (clock_getres, clock_id, &ts32);
+# endif
+  if (r == 0)
     *res = valid_timespec_to_timespec64 (ts32);
-
-  return retval;
+  return r;
 #endif
 }
 
@@ -60,7 +68,7 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
   int retval;
 
   retval = __clock_getres64 (clock_id, &ts64);
-  if (! retval && res)
+  if (retval == 0 && res != NULL)
     *res = valid_timespec64_to_timespec (ts64);
 
   return retval;
index fe6de68620ffb744533a3d857aa630f3ec4e3320..74aadbfbd4ea601c3a8af1a7716dde390f6e4382 100644 (file)
 #include <errno.h>
 #include <time.h>
 #include "kernel-posix-cpu-timers.h"
-
-#ifdef HAVE_CLOCK_GETTIME_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 #include <shlib-compat.h>
@@ -34,22 +30,34 @@ int
 __clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
 {
 #ifdef __ASSUME_TIME64_SYSCALLS
-# ifndef __NR_clock_gettime64
-#  define __NR_clock_gettime64   __NR_clock_gettime
-#  define __vdso_clock_gettime64 __vdso_clock_gettime
+  /* 64 bit ABIs or Newer 32-bit ABIs that only support 64-bit time_t.  */
+# ifdef __NR_clock_gettime64
+  return INLINE_SYSCALL_CALL (clock_gettime64, clock_id, tp);
+# else
+#  ifdef HAVE_CLOCK_GETTIME_VSYSCALL
+  return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp);
+#  else
+  return INLINE_SYSCALL_CALL (clock_gettime, clock_id, tp);
+#  endif
 # endif
-   return INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);
 #else
-# if defined HAVE_CLOCK_GETTIME64_VSYSCALL
-  int ret64 = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);
-  if (ret64 == 0 || errno != ENOSYS)
-    return ret64;
+  int r;
+  /* Old 32-bit ABI with possible 64-bit time_t support.  */
+# ifdef __NR_clock_gettime64
+  r = INLINE_SYSCALL_CALL (clock_gettime64, clock_id, tp);
+  if (r == 0 || errno != ENOSYS)
+    return r;
 # endif
+  /* Fallback code that uses 32-bit support.  */
   struct timespec tp32;
-  int ret = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &tp32);
-  if (ret == 0)
+# ifdef HAVE_CLOCK_GETTIME_VSYSCALL
+  r = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &tp32);
+# else
+  r = INLINE_SYSCALL_CALL (clock_gettime, clock_id, &tp32);
+# endif
+  if (r == 0)
     *tp = valid_timespec_to_timespec64 (tp32);
-  return ret;
+  return r;
 #endif
 }
 
index c16652d954ced0219e4f9edecbd9e44868b27021..db381d33a8e4d6f17f4b3473454e19a099128578 100644 (file)
 #include <errno.h>
 #include <sched.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETCPU_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 int
 __getcpu (unsigned int *cpu, unsigned int *node)
 {
-#ifdef __NR_getcpu
+#ifdef HAVE_GETCPU_VSYSCALL
   return INLINE_VSYSCALL (getcpu, 3, cpu, node, NULL);
 #else
-  __set_errno (ENOSYS);
-  return -1;
+  return INLINE_SYSCALL_CALL (getcpu, cpu, node, NULL);
 #endif
 }
 weak_alias (__getcpu, getcpu)
index ff3949124ac1f78b5ff2627c51ab67e39596c16e..6f68b11f74223ad925fda8ebb06faab314b01758 100644 (file)
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 static int
index 253dfd5b8d10add63974544edc5232e7e393ecd1..e226f4479b402bade1fd85ebed2513873a449119 100644 (file)
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_TIME_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 static time_t
index 2eb99ec4b5308f2137748ded7906e81d6a59dd50..c019cfb3cfb74ae6a240707b63c1be23e4a99b03 100644 (file)
 #include <errno.h>
 #include <sched.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETCPU_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 int
 sched_getcpu (void)
 {
-#ifdef __NR_getcpu
   unsigned int cpu;
-  int r = INLINE_VSYSCALL (getcpu, 3, &cpu, NULL, NULL);
-
-  return r == -1 ? r : cpu;
+  int r = -1;
+#ifdef HAVE_GETCPU_VSYSCALL
+  r = INLINE_VSYSCALL (getcpu, 3, &cpu, NULL, NULL);
 #else
-  __set_errno (ENOSYS);
-  return -1;
+  r = INLINE_SYSCALL_CALL (getcpu, &cpu, NULL, NULL);
 #endif
+  return r == -1 ? r : cpu;
 }
index 3af56cd3b4ec89b51d37888c1ed0aa09cbb58e80..f0cc384d78a12bf25aa70fff3cacebdba9b61956 100644 (file)
 # define SYSDEP_VDSO_LINUX_H
 
 #include <dl-vdso.h>
+#include <libc-vdso.h>
 
 #ifndef INTERNAL_VSYSCALL_CALL
 # define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)                   \
      funcptr (args)
 #endif
 
-#ifdef HAVE_VSYSCALL
-
-# include <libc-vdso.h>
-
-# define INLINE_VSYSCALL(name, nr, args...)                                  \
+#define INLINE_VSYSCALL(name, nr, args...)                                   \
   ({                                                                         \
     __label__ out;                                                           \
     __label__ iserr;                                                         \
     sc_ret;                                                                  \
   })
 
-# define INTERNAL_VSYSCALL(name, err, nr, args...)                           \
-  ({                                                                         \
-    __label__ out;                                                           \
-    long v_ret;                                                                      \
-                                                                             \
-    __typeof (__vdso_##name) vdsop = __vdso_##name;                          \
-    PTR_DEMANGLE (vdsop);                                                    \
-    if (vdsop != NULL)                                                       \
-      {                                                                              \
-       v_ret = INTERNAL_VSYSCALL_CALL (vdsop, err, nr, ##args);              \
-       if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err)                            \
-           || INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS)                 \
-         goto out;                                                           \
-      }                                                                              \
-    v_ret = INTERNAL_SYSCALL (name, err, nr, ##args);                        \
-  out:                                                                       \
-    v_ret;                                                                   \
-  })
-#else
-
-# define INLINE_VSYSCALL(name, nr, args...) \
-   INLINE_SYSCALL (name, nr, ##args)
-# define INTERNAL_VSYSCALL(name, err, nr, args...) \
-   INTERNAL_SYSCALL (name, err, nr, ##args)
-
-#endif /* USE_VSYSCALL && defined HAVE_VSYSCALL */
-
 #endif /* SYSDEP_VDSO_LINUX_H  */
index 7b12219d62f4038b789c91930148fcd9a72220c6..3fb4e8d1c42ee22d311e53646a158613fee8afcc 100644 (file)
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 static int
index 0cb70a781622d7e5b56e629db01a1ad3a357fcf9..9074f1e10e08a75f7f07a95bf1de6b02bd261685 100644 (file)
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_TIME_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 static time_t
 time_vsyscall (time_t *t)
 {
+#ifdef HAVE_TIME_VSYSCALL
   return INLINE_VSYSCALL (time, 1, t);
+#else
+  return INLINE_SYSCALL_CALL (time, t);
+#endif
 }
 
 #ifdef SHARED