@@ -74,10 +74,6 @@ _init (int argc, char **argv, char **envp)
_dl_non_dynamic_init ();
#endif
-#ifdef VDSO_SETUP
- VDSO_SETUP ();
-#endif
-
__init_misc (argc, argv, envp);
/* Initialize ctype data. */
@@ -34,6 +34,8 @@
#include <unsecvars.h>
#include <hp-timing.h>
#include <stackinfo.h>
+#include <dl-vdso.h>
+#include <dl-vdso-setup.h>
extern char *__progname;
char **_dl_argv = &__progname; /* This is checked for some error messages. */
@@ -201,6 +203,8 @@ struct link_map *_dl_sysinfo_map;
# include "get-dynamic-info.h"
#endif
#include "setup-vdso.h"
+/* Define the vDSO function pointers. */
+#include <dl-vdso-setup.c>
/* During the program run we must not modify the global data of
loaded shared object simultanously in two threads. Therefore we
@@ -315,6 +319,9 @@ _dl_non_dynamic_init (void)
so they can influence _dl_init_paths. */
setup_vdso (NULL, NULL);
+ /* With vDSO setup we can initialize the function pointers. */
+ setup_vdso_pointers ();
+
/* Initialize the data structures for the search paths for shared
objects. */
_dl_init_paths (getenv ("LD_LIBRARY_PATH"));
@@ -39,6 +39,8 @@
#include <dl-osinfo.h>
#include <dl-procinfo.h>
#include <dl-prop.h>
+#include <dl-vdso.h>
+#include <dl-vdso-setup.h>
#include <tls.h>
#include <stap-probe.h>
#include <stackinfo.h>
@@ -833,7 +835,7 @@ security_init (void)
_dl_random = NULL;
}
-#include "setup-vdso.h"
+#include <setup-vdso.h>
/* The library search path. */
static const char *library_path attribute_relro;
@@ -1538,6 +1540,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
so they can influence _dl_init_paths. */
setup_vdso (main_map, &first_preload);
+ /* With vDSO setup we can initialize the function pointers. */
+ setup_vdso_pointers ();
+
#ifdef DL_SYSDEP_OSCHECK
DL_SYSDEP_OSCHECK (_dl_fatal_printf);
#endif
@@ -28,6 +28,7 @@
#include <sys/mman.h>
#include <sys/uio.h>
#include <unistd.h>
+#include <time.h>
#if INTERPOSE_THREADS
#include <pthread.h>
@@ -96,6 +97,7 @@ struct __attribute__ ((aligned (__alignof__ (max_align_t)))) allocation_header
{
size_t allocation_index;
size_t allocation_size;
+ struct timespec ts;
};
/* Array of known allocations, to track invalid frees. */
@@ -166,6 +168,9 @@ malloc_internal (size_t size)
.allocation_index = index,
.allocation_size = allocation_size
};
+ /* BZ#24967: Check if calling a symbol which may use the vDSO does not fail.
+ The CLOCK_REALTIME should be supported on all systems. */
+ clock_gettime (CLOCK_REALTIME, &allocations[index]->ts);
return allocations[index] + 1;
}
new file mode 100644
@@ -0,0 +1 @@
+/* Empty. */
new file mode 100644
@@ -0,0 +1,28 @@
+/* ELF symbol initialization functions for VDSO objects.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _DL_VDSO_INIT_H
+#define _DL_VDSO_INIT_H
+
+/* Initialize the VDSO functions pointers. */
+static inline void __attribute__ ((always_inline))
+setup_vdso_pointers (void)
+{
+}
+
+#endif
new file mode 100644
@@ -0,0 +1,30 @@
+/* ELF symbol resolve functions for VDSO objects.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _DL_VDSO_H
+#define _DL_VDSO_H 1
+
+/* Function for resolving symbols in the VDSO link map. Return the
+ address of the vdso symbol NAME. */
+static inline void *
+dl_vdso_vsym (const char *name)
+{
+ return NULL;
+}
+
+#endif
@@ -601,6 +601,12 @@ struct rtld_global_ro
/* At startup time we set up the normal DSO data structure for it,
and this points to it. */
EXTERN struct link_map *_dl_sysinfo_map;
+
+# define PROCINFO_DECL
+# ifndef PROCINFO_CLASS
+# define PROCINFO_CLASS EXTERN
+# endif
+# include <dl-vdso-setup.c>
#endif
/* Mask for more hardware capabilities that are available on some
@@ -51,14 +51,14 @@ struct signal_frame_32 {
/* We don't care about the rest, since IP value is at 'mctx' field. */
};
-static inline int
+static inline bool
is_sigtramp_address (void *nip)
{
#ifdef HAVE_SIGTRAMP_RT32
- if (nip == VDSO_SYMBOL (sigtramp32))
- return 1;
+ if (nip == GLRO (dl_vdso_sigtramp_32))
+ return true;
#endif
- return 0;
+ return false;
}
struct rt_signal_frame_32 {
@@ -68,14 +68,14 @@ struct rt_signal_frame_32 {
/* We don't care about the rest, since IP value is at 'uc' field. */
};
-static inline int
+static inline bool
is_sigtramp_address_rt (void * nip)
{
#ifdef HAVE_SIGTRAMP_32
- if (nip == VDSO_SYMBOL (sigtramp_rt32))
- return 1;
+ if (nip == GLRO (dl_vdso_sigtramp_rt32))
+ return true;
#endif
- return 0;
+ return false;
}
int
@@ -54,14 +54,14 @@ struct signal_frame_64 {
/* We don't care about the rest, since the IP value is at 'uc' field. */
};
-static inline int
+static inline bool
is_sigtramp_address (void *nip)
{
#ifdef HAVE_SIGTRAMP_RT64
- if (nip == VDSO_SYMBOL (sigtramp_rt64))
- return 1;
+ if (nip == GLRO (dl_vdso_sigtramp_rt64))
+ return true;
#endif
- return 0;
+ return false;
}
int
@@ -5,7 +5,6 @@ shared-only-routines += libc-__read_tp
endif
ifeq ($(subdir),elf)
-sysdep_routines += dl-vdso
sysdep-rtld-routines += __read_tp
ifeq ($(build-shared),yes)
# This is needed for DSO loading from static binaries.
@@ -22,10 +22,6 @@
#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
@@ -36,16 +32,16 @@ __gettimeofday_vsyscall (struct timeval *restrict tv, void *restrict tz)
if (__glibc_unlikely (tz != 0))
memset (tz, 0, sizeof *tz);
- return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+ int ret = INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+ if (ret != -1)
+ return ret;
+ return INLINE_SYSCALL_CALL (gettimeofday, tv, tz);
}
#ifdef SHARED
-# include <dl-vdso.h>
-# include <sysdep-vdso.h>
-
# define INIT_ARCH()
libc_ifunc (__gettimeofday,
- (get_vdso_symbol (HAVE_GETTIMEOFDAY_VSYSCALL)
+ (GLRO(dl_vdso_gettimeofday)
?: __gettimeofday_vsyscall))
#else
@@ -1,5 +1,4 @@
ifeq ($(subdir),elf)
-sysdep_routines += dl-vdso
sysdep-rtld-routines += aeabi_read_tp libc-do-syscall
endif
@@ -20,36 +20,40 @@
#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>
/* Get resolution of clock. */
int
__clock_getres64 (clockid_t clock_id, struct __timespec64 *res)
{
+ int ret = -1;
#ifdef __ASSUME_TIME64_SYSCALLS
# ifndef __NR_clock_getres_time64
- return INLINE_VSYSCALL (clock_getres, 2, clock_id, res);
+# ifdef HAVE_CLOCK_GETRES_VSYSCALL
+ ret = INLINE_VSYSCALL (clock_getres, 2, clock_id, res);
+# endif
+ if (ret == -1)
+ ret = INLINE_SYSCALL (clock_getres, 2, clock_id, res);
# else
- return INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res);
+ ret = INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res);
# endif
#else
# ifdef __NR_clock_getres_time64
- int ret = INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res);
+ ret = INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res);
if (ret == 0 || errno != ENOSYS)
return ret;
# endif
struct timespec ts32;
- int retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);
- if (! retval && res)
+# ifdef HAVE_CLOCK_GETRES_VSYSCALL
+ ret = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);
+# endif
+ if (ret == -1)
+ ret = INLINE_SYSCALL (clock_getres, 2, clock_id, &ts32);
+ if (ret == 0 && res)
*res = valid_timespec_to_timespec64 (ts32);
-
- return retval;
#endif
+ return ret;
}
#if __TIMESIZE != 64
@@ -67,6 +71,7 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
}
#endif
+#include <shlib-compat.h>
versioned_symbol (libc, __clock_getres, clock_getres, GLIBC_2_17);
/* clock_getres moved to libc in version 2.17;
old binaries may expect the symbol version it had in librt. */
@@ -20,22 +20,22 @@
#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>
-
/* Get current value of CLOCK and store it in TP. */
int
__clock_gettime (clockid_t clock_id, struct timespec *tp)
{
- return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp);
+#ifdef HAVE_CLOCK_GETTIME_VSYSCALL
+ int ret = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp);
+ if (ret != -1)
+ return ret;
+#endif
+ return INLINE_SYSCALL_CALL (clock_gettime, clock_id, tp);
}
libc_hidden_def (__clock_gettime)
+#include <shlib-compat.h>
versioned_symbol (libc, __clock_gettime, clock_gettime, GLIBC_2_17);
/* clock_gettime moved to libc in version 2.17;
old binaries may expect the symbol version it had in librt. */
new file mode 100644
@@ -0,0 +1,77 @@
+/* Data for vDSO support. Linux version.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+/* This file is included in three different modes for both static (libc.a)
+ and shared (rtld) modes:
+
+ 1. PROCINFO_DECL is defined, meaning we are only interested in
+ declarations. For static it requires use the extern keywork along with
+ the attribute_relro while for shared it will be embedded in the
+ rtld_global_ro.
+
+ 2. PROCINFO_DECL and SHARED are not defined. Nothing to do, the default
+ zero initializion is suffice.
+
+ 3. PROCINFO_DECL is not defined while SHARED is. Similar to 2., the zero
+ initialization of rtld_global_ro is suffice. */
+
+#ifndef PROCINFO_CLASS
+# define PROCINFO_CLASS
+#endif
+
+#ifndef SHARED
+# define RELRO attribute_relro
+#else
+# define RELRO
+#endif
+
+#if defined PROCINFO_DECL || !defined SHARED
+# ifdef HAVE_CLOCK_GETTIME_VSYSCALL
+PROCINFO_CLASS void *_dl_vdso_clock_gettime RELRO;
+#endif
+# ifdef HAVE_GETTIMEOFDAY_VSYSCALL
+PROCINFO_CLASS void *_dl_vdso_gettimeofday RELRO;
+#endif
+# ifdef HAVE_TIME_VSYSCALL
+PROCINFO_CLASS void *_dl_vdso_time RELRO;
+# endif
+# ifdef HAVE_GETCPU_VSYSCALL
+PROCINFO_CLASS void *_dl_vdso_getcpu_kernel RELRO;
+# endif
+# ifdef HAVE_CLOCK_GETRES_VSYSCALL
+PROCINFO_CLASS void *_dl_vdso_clock_getres RELRO;
+# endif
+
+/* PowerPC specific ones. */
+# ifdef HAVE_GET_TBFREQ
+PROCINFO_CLASS void *_dl_vdso_get_tbfreq RELRO;
+# endif
+# ifdef HAVE_SIGTRAMP_RT64
+PROCINFO_CLASS void *_dl_vdso_sigtramp_rt64 RELRO;
+# endif
+# ifdef HAVE_SIGTRAMP_RT32
+PROCINFO_CLASS void *_dl_vdso_sigtramp_rt32 RELRO;
+# endif
+# ifdef HAVE_SIGTRAMP_32
+PROCINFO_CLASS void *_dl_vdso_sigtramp_32 RELRO;
+# endif
+#endif
+
+#undef RELRO
+#undef PROCINFO_DECL
+#undef PROCINFO_CLASS
new file mode 100644
@@ -0,0 +1,55 @@
+/* ELF symbol initialization functions for VDSO objects. Linux version.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _DL_VDSO_INIT_H
+#define _DL_VDSO_INIT_H
+
+/* Initialize the VDSO functions pointers. */
+static inline void __attribute__ ((always_inline))
+setup_vdso_pointers (void)
+{
+#ifdef HAVE_CLOCK_GETTIME_VSYSCALL
+ GLRO(dl_vdso_clock_gettime) = dl_vdso_vsym (HAVE_CLOCK_GETTIME_VSYSCALL);
+#endif
+#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
+ GLRO(dl_vdso_gettimeofday) = dl_vdso_vsym (HAVE_GETTIMEOFDAY_VSYSCALL);
+#endif
+#ifdef HAVE_TIME_VSYSCALL
+ GLRO(dl_vdso_time) = dl_vdso_vsym (HAVE_TIME_VSYSCALL);
+#endif
+#ifdef HAVE_GETCPU_VSYSCALL
+ GLRO(dl_vdso_getcpu_kernel) = dl_vdso_vsym (HAVE_GETCPU_VSYSCALL);
+#endif
+#ifdef HAVE_CLOCK_GETRES_VSYSCALL
+ GLRO(dl_vdso_clock_getres) = dl_vdso_vsym (HAVE_CLOCK_GETRES_VSYSCALL);
+#endif
+#ifdef HAVE_GET_TBFREQ
+ GLRO(dl_vdso_get_tbfreq) = dl_vdso_vsym (HAVE_GET_TBFREQ);
+#endif
+#ifdef HAVE_SIGTRAMP_RT64
+ GLRO(dl_vdso_sigtramp_rt64) = dl_vdso_vsym (HAVE_SIGTRAMP_RT64);
+#endif
+#ifdef HAVE_SIGTRAMP_RT32
+ GLRO(dl_vdso_sigtramp_rt32) = dl_vdso_vsym (HAVE_SIGTRAMP_RT32);
+#endif
+#ifdef HAVE_SIGTRAMP_32
+ GLRO(dl_vdso_sigtramp_32) = dl_vdso_vsym (HAVE_SIGTRAMP_32);
+#endif
+}
+
+#endif
deleted file mode 100644
@@ -1,48 +0,0 @@
-/* ELF symbol resolve functions for VDSO objects.
- Copyright (C) 2005-2019 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
- <https://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include <ldsodefs.h>
-
-
-void *
-_dl_vdso_vsym (const char *name, const struct r_found_version *vers)
-{
- struct link_map *map = GLRO (dl_sysinfo_map);
- void *value = NULL;
-
-
- if (map != NULL)
- {
- /* Use a WEAK REF so we don't error out if the symbol is not found. */
- ElfW (Sym) wsym;
- memset (&wsym, 0, sizeof (ElfW (Sym)));
- wsym.st_info = (unsigned char) ELFW (ST_INFO (STB_WEAK, STT_NOTYPE));
-
- /* Search the scope of the vdso map. */
- const ElfW (Sym) *ref = &wsym;
- lookup_t result = GLRO (dl_lookup_symbol_x) (name, map, &ref,
- map->l_local_scope,
- vers, 0, 0, NULL);
-
- if (ref != NULL)
- value = DL_SYMBOL_ADDRESS (result, ref);
- }
-
- return value;
-}
@@ -22,11 +22,6 @@
#include <ldsodefs.h>
#include <dl-hash.h>
-/* Functions for resolving symbols in the VDSO link map. */
-extern void *_dl_vdso_vsym (const char *name,
- const struct r_found_version *version)
- attribute_hidden;
-
/* If the architecture support vDSO it should define which is the expected
kernel version and hash value through both VDSO_NAME and VDSO_HASH
(usually defined at architecture sysdep.h). */
@@ -38,19 +33,26 @@ extern void *_dl_vdso_vsym (const char *name,
# define VDSO_HASH 0
#endif
+/* Functions for resolving symbols in the VDSO link map. */
static inline void *
-get_vdso_symbol (const char *symbol)
+dl_vdso_vsym (const char *name)
{
+ struct link_map *map = GLRO (dl_sysinfo_map);
+ if (map == NULL)
+ return NULL;
+
+ /* Use a WEAK REF so we don't error out if the symbol is not found. */
+ ElfW (Sym) wsym = { 0 };
+ wsym.st_info = (unsigned char) ELFW (ST_INFO (STB_WEAK, STT_NOTYPE));
+
struct r_found_version rfv = { VDSO_NAME, VDSO_HASH, 1, NULL };
- return _dl_vdso_vsym (symbol, &rfv);
-}
-static inline void *
-get_vdso_mangle_symbol (const char *symbol)
-{
- void *vdsop = get_vdso_symbol (symbol);
- PTR_MANGLE (vdsop);
- return vdsop;
+ /* Search the scope of the vdso map. */
+ const ElfW (Sym) *ref = &wsym;
+ lookup_t result = GLRO (dl_lookup_symbol_x) (name, map, &ref,
+ map->l_local_scope,
+ &rfv, 0, 0, NULL);
+ return ref != NULL ? DL_SYMBOL_ADDRESS (result, ref) : NULL;
}
#endif /* dl-vdso.h */
@@ -18,21 +18,19 @@
#include <errno.h>
#include <sched.h>
#include <sysdep.h>
-
-#ifdef HAVE_GETCPU_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
#include <sysdep-vdso.h>
+int getcpu_kernel (unsigned *cpu, unsigned *node, void *tcache);
+
int
__getcpu (unsigned int *cpu, unsigned int *node)
{
-#ifdef __NR_getcpu
- return INLINE_VSYSCALL (getcpu, 3, cpu, node, NULL);
-#else
- __set_errno (ENOSYS);
- return -1;
+#ifdef HAVE_GETCPU_VSYSCALL
+ int ret = INLINE_VSYSCALL (getcpu_kernel, 3, cpu, node, NULL);
+ if (ret != -1)
+ return ret;
#endif
+ return INLINE_SYSCALL_CALL (getcpu, cpu, node, NULL);
}
weak_alias (__getcpu, getcpu)
libc_hidden_def (__getcpu)
deleted file mode 100644
@@ -1,80 +0,0 @@
-/* vDSO internal symbols. Linux generic version.
- Copyright (C) 2019 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 <dl-vdso.h>
-#include <libc-vdso.h>
-
-/* vDSO symbol used on clock_gettime implementation. */
-#ifdef HAVE_CLOCK_GETTIME_VSYSCALL
-int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *)
- attribute_hidden;
-#endif
-/* vDSO symbol used on clock_getres implementation. */
-#ifdef HAVE_CLOCK_GETRES_VSYSCALL
-int (*VDSO_SYMBOL(clock_getres)) (clockid_t, struct timespec *)
- attribute_hidden;
-#endif
-/* vDSO symbol used on gettimeofday implementation. */
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-int (*VDSO_SYMBOL (gettimeofday)) (struct timeval *, void *)
- attribute_hidden;
-#endif
-/* vDSO symbol used on GNU extension getcpu implementation. */
-#ifdef HAVE_GETCPU_VSYSCALL
-long int (*VDSO_SYMBOL(getcpu)) (unsigned *, unsigned *, void *)
- attribute_hidden;
-#endif
-/* vDSO symbol used on time implementation. */
-#ifdef HAVE_TIME_VSYSCALL
-time_t (*VDSO_SYMBOL(time)) (time_t *) attribute_hidden;
-#endif
-
-static inline void
-__libc_vdso_platform_setup (void)
-{
-#ifdef HAVE_CLOCK_GETTIME_VSYSCALL
- VDSO_SYMBOL(clock_gettime)
- = get_vdso_mangle_symbol (HAVE_CLOCK_GETTIME_VSYSCALL);
-#endif
-
-#ifdef HAVE_CLOCK_GETRES_VSYSCALL
- VDSO_SYMBOL(clock_getres)
- = get_vdso_mangle_symbol (HAVE_CLOCK_GETRES_VSYSCALL);
-#endif
-
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
- VDSO_SYMBOL(gettimeofday)
- = get_vdso_mangle_symbol (HAVE_GETTIMEOFDAY_VSYSCALL);
-#endif
-
-#ifdef HAVE_GETCPU_VSYSCALL
- VDSO_SYMBOL(getcpu) = get_vdso_mangle_symbol (HAVE_GETCPU_VSYSCALL);
-#endif
-
-#ifdef HAVE_TIME_VSYSCALL
- VDSO_SYMBOL(time) = get_vdso_mangle_symbol (HAVE_TIME_VSYSCALL);
-#endif
-
-#ifdef VDSO_SETUP_ARCH
- VDSO_SETUP_ARCH ();
-#endif
-}
-
-#define VDSO_SETUP __libc_vdso_platform_setup
-
-#include <csu/init-first.c>
deleted file mode 100644
@@ -1,51 +0,0 @@
-/* Copyright (C) 2009-2019 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
- <https://www.gnu.org/licenses/>. */
-
-#ifndef _LIBC_VDSO_H
-#define _LIBC_VDSO_H
-
-#define VDSO_SYMBOL(__name) __vdso_##__name
-
-/* Adjust the return IFUNC value from a vDSO symbol accordingly required
- by the ELFv1 ABI. It is used by the architecture to create an ODP
- entry since the kernel vDSO does not provide it. */
-#ifndef VDSO_IFUNC_RET
-# define VDSO_IFUNC_RET(__value) (__value)
-#endif
-
-#ifdef HAVE_CLOCK_GETTIME_VSYSCALL
-extern int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *)
- attribute_hidden;
-#endif
-#ifdef HAVE_CLOCK_GETRES_VSYSCALL
-extern int (*VDSO_SYMBOL(clock_getres)) (clockid_t, struct timespec *)
- attribute_hidden;
-#endif
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-extern int (*VDSO_SYMBOL (gettimeofday)) (struct timeval *, void *)
- attribute_hidden;
-#endif
-#ifdef HAVE_GETCPU_VSYSCALL
-extern long int (*VDSO_SYMBOL(getcpu)) (unsigned *, unsigned *, void *)
- attribute_hidden;
-#endif
-#ifdef HAVE_TIME_VSYSCALL
-extern time_t (*VDSO_SYMBOL(time)) (time_t *) attribute_hidden;
-#endif
-
-#endif /* _LIBC_VDSO_H */
@@ -60,8 +60,6 @@ ifeq ($(subdir),elf)
ifeq ($(build-shared),yes)
# This is needed for DSO loading from static binaries.
sysdep-dl-routines += dl-static
-
-sysdep_routines += dl-vdso
endif
# If the compiler doesn't use GNU.stack note,
# this test is expected to fail.
@@ -23,19 +23,3 @@
#define HAVE_CLOCK_GETTIME_VSYSCALL "__vdso_clock_gettime"
#define HAVE_GETTIMEOFDAY_VSYSCALL "__vdso_gettimeofday"
#define HAVE_CLOCK_GETRES_VSYSCALL "__vdso_clock_getres"
-
-#ifndef __ASSEMBLER__
-
-/* Standard MIPS syscalls have an error flag, and return a positive errno
- when the error flag is set. Emulate this behaviour for vsyscalls so that
- the INTERNAL_SYSCALL_{ERROR_P,ERRNO} macros work correctly. */
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
- ({ \
- long _ret = funcptr (args); \
- err = ((unsigned long) (_ret) >= (unsigned long) -4095L); \
- if (err) \
- _ret = -_ret; \
- _ret; \
- })
-
-#endif /* __ASSEMBLER__ */
@@ -13,7 +13,6 @@ gen-as-const-headers += ucontext_i.sym
endif
ifeq ($(subdir),elf)
-sysdep_routines += dl-vdso
ifeq ($(build-shared),yes)
# This is needed for DSO loading from static binaries.
sysdep-dl-routines += dl-static
@@ -21,7 +21,7 @@
#include <libc-internal.h>
#include <not-cancel.h>
-#include <libc-vdso.h>
+#include <sysdep-vdso.h>
static uint64_t
get_timebase_freq_fallback (void)
@@ -101,12 +101,9 @@ uint64_t
__get_timebase_freq (void)
{
/* The vDSO does not have a fallback mechanism (such calling a syscall). */
- __typeof (VDSO_SYMBOL (get_tbfreq)) vdsop = VDSO_SYMBOL (get_tbfreq);
- PTR_DEMANGLE (vdsop);
- if (vdsop == NULL)
- return get_timebase_freq_fallback ();
-
- INTERNAL_SYSCALL_DECL (err);
- return INTERNAL_VSYSCALL_CALL_TYPE (vdsop, err, uint64_t, 0);
+ uint64_t (*vdsop) (void) = GLRO(dl_vdso_get_tbfreq);
+ if (vdsop != NULL)
+ return INTERNAL_VSYSCALL_CALL_TYPE (vdsop, uint64_t, 0);
+ return get_timebase_freq_fallback ();
}
weak_alias (__get_timebase_freq, __ppc_get_timebase_freq)
@@ -17,11 +17,8 @@
#include <time.h>
#include <sysdep.h>
-
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
#include <sysdep-vdso.h>
+#include <libc-vdso.h>
static int
__gettimeofday_syscall (struct timeval *restrict tv, void *restrict tz)
@@ -29,21 +26,18 @@ __gettimeofday_syscall (struct timeval *restrict tv, void *restrict tz)
if (__glibc_unlikely (tz != 0))
memset (tz, 0, sizeof *tz);
- return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+ int ret = INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+ if (ret != -1)
+ return ret;
+ return INLINE_SYSCALL_CALL (gettimeofday, tv, tz);
}
#ifdef SHARED
-# include <dl-vdso.h>
-# include <libc-vdso.h>
-
-# define INIT_ARCH() \
- void *vdso_gettimeofday = get_vdso_symbol (HAVE_GETTIMEOFDAY_VSYSCALL)
-
+# define INIT_ARCH()
/* If the vDSO is not available we fall back syscall. */
-libc_ifunc (__gettimeofday,
- vdso_gettimeofday
- ? VDSO_IFUNC_RET (vdso_gettimeofday)
- : (void *) __gettimeofday_syscall);
+libc_ifunc (__gettimeofday, GLRO(dl_vdso_gettimeofday)
+ ? VDSO_IFUNC_RET (GLRO(dl_vdso_gettimeofday))
+ : (void *) __gettimeofday_syscall);
#else
int
__gettimeofday (struct timeval *restrict tv, void *restrict tz)
deleted file mode 100644
@@ -1,50 +0,0 @@
-/* Initialization code run first thing by the ELF startup code. Linux/PowerPC.
- Copyright (C) 2007-2019 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
- <https://www.gnu.org/licenses/>. */
-
-#include <dl-vdso.h>
-#include <libc-vdso.h>
-
-unsigned long long (*VDSO_SYMBOL(get_tbfreq)) (void) attribute_hidden;
-#if defined(__PPC64__) || defined(__powerpc64__)
-void *VDSO_SYMBOL(sigtramp_rt64) attribute_hidden;
-#else
-void *VDSO_SYMBOL(sigtramp32) attribute_hidden;
-void *VDSO_SYMBOL(sigtramp_rt32) attribute_hidden;
-#endif
-
-static inline void
-__libc_vdso_platform_setup_arch (void)
-{
- VDSO_SYMBOL (get_tbfreq) = get_vdso_mangle_symbol (HAVE_GET_TBFREQ);
-
- /* PPC64 uses only one signal trampoline symbol, while PPC32 will use
- two depending if SA_SIGINFO is used (__kernel_sigtramp_rt32) or not
- (__kernel_sigtramp32).
- There is no need to pointer mangle these symbol because they will
- used only for pointer comparison. */
-#if defined(__PPC64__) || defined(__powerpc64__)
- VDSO_SYMBOL(sigtramp_rt64) = get_vdso_symbol (HAVE_SIGTRAMP_RT64);
-#else
- VDSO_SYMBOL(sigtramp32) = get_vdso_symbol (HAVE_SIGTRAMP_32);
- VDSO_SYMBOL(sigtramp_rt32) = get_vdso_symbol (HAVE_SIGTRAMP_RT32);
-#endif
-}
-
-#define VDSO_SETUP_ARCH __libc_vdso_platform_setup_arch
-
-#include <sysdeps/unix/sysv/linux/init-first.c>
@@ -54,14 +54,4 @@
# define VDSO_IFUNC_RET(value) ((void *) (value))
#endif
-#include_next <libc-vdso.h>
-
-extern unsigned long long (*VDSO_SYMBOL(get_tbfreq)) (void);
-#if defined(__PPC64__) || defined(__powerpc64__)
-extern void *VDSO_SYMBOL(sigtramp_rt64);
-#else
-extern void *VDSO_SYMBOL(sigtramp32);
-extern void *VDSO_SYMBOL(sigtramp_rt32);
-#endif
-
#endif /* _LIBC_VDSO_H */
@@ -41,7 +41,7 @@
function call, with the exception of LR (which is needed for the
"sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
an error return status). */
-# define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, type, nr, args...) \
+# define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, type, nr, args...) \
({ \
register void *r0 __asm__ ("r0"); \
register long int r3 __asm__ ("r3"); \
@@ -63,13 +63,15 @@
: "+r" (r0), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), \
"+r" (r8), "+r" (r9), "+r" (r10), "+r" (r11), "+r" (r12) \
: : "cr0", "ctr", "lr", "memory"); \
- err = (long int) r0; \
+ long int err = (long int) r0; \
__asm__ __volatile__ ("" : "=r" (rval) : "r" (r3), "r" (r4)); \
+ if (INTERNAL_SYSCALL_ERROR_P (rval, err)) \
+ rval = -rval; \
rval; \
})
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
- INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, long int, nr, args)
+#define INTERNAL_VSYSCALL_CALL(funcptr, nr, args...) \
+ INTERNAL_VSYSCALL_CALL_TYPE(funcptr, long int, nr, args)
# undef INLINE_SYSCALL
# define INLINE_SYSCALL(name, nr, args...) \
@@ -51,7 +51,7 @@
gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
the negation of the return value in the kernel gets reverted. */
-#define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, type, nr, args...) \
+#define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, type, nr, args...) \
({ \
register void *r0 __asm__ ("r0"); \
register long int r3 __asm__ ("r3"); \
@@ -70,13 +70,15 @@
: "+r" (r0), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), \
"+r" (r7), "+r" (r8) \
: : "r9", "r10", "r11", "r12", "cr0", "ctr", "lr", "memory"); \
- err = (long int) r0; \
+ long int err = (long int) r0; \
__asm__ __volatile__ ("" : "=r" (rval) : "r" (r3)); \
+ if (INTERNAL_SYSCALL_ERROR_P (rval, err)) \
+ rval = -rval; \
rval; \
})
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
- INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, long int, nr, args)
+#define INTERNAL_VSYSCALL_CALL(funcptr, nr, args...) \
+ INTERNAL_VSYSCALL_CALL_TYPE(funcptr, long int, nr, args)
/* This version is for kernels that implement system calls that
behave like function calls as far as register saving. */
@@ -18,31 +18,25 @@
#include <time.h>
#include <sysdep.h>
-
-#ifdef HAVE_TIME_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
#include <sysdep-vdso.h>
+#include <libc-vdso.h>
static time_t
time_vsyscall (time_t *t)
{
- return INLINE_VSYSCALL (time, 1, t);
+ time_t ret = INLINE_VSYSCALL (time, 1, t);
+ if (ret != -1)
+ return ret;
+ return INLINE_SYSCALL_CALL (time, t);
}
#ifdef SHARED
-# include <dl-vdso.h>
-# include <libc-vdso.h>
-
-# define INIT_ARCH() \
- void *vdso_time = get_vdso_symbol (HAVE_TIME_VSYSCALL);
-
+#undef INIT_ARCH
+#define INIT_ARCH()
/* If the vDSO is not available we fall back to the syscall. */
-libc_ifunc (time,
- vdso_time
- ? VDSO_IFUNC_RET (vdso_time)
- : (void *) time_vsyscall);
-
+libc_ifunc (time, GLRO(dl_vdso_time)
+ ? VDSO_IFUNC_RET (GLRO(dl_vdso_time))
+ : (void *) time_vsyscall)
#else
time_t
time (time_t *t)
@@ -1,7 +1,3 @@
-ifeq ($(subdir),elf)
-sysdep_routines += dl-vdso
-endif
-
ifeq ($(subdir),misc)
sysdep_headers += sys/cachectl.h
sysdep_routines += flush-icache
@@ -38,7 +38,7 @@ __riscv_flush_icache_syscall (void *start, void *end, unsigned long int flags)
static func_type
__lookup_riscv_flush_icache (void)
{
- func_type func = get_vdso_symbol ("__vdso_flush_icache");
+ func_type func = dl_vdso_vsym ("__vdso_flush_icache");
/* If there is no vDSO entry then call the system call directly. All Linux
versions provide the vDSO entry, but QEMU's user-mode emulation doesn't
@@ -11,10 +11,6 @@ ifeq ($(subdir),stdlib)
gen-as-const-headers += ucontext_i.sym
endif
-ifeq ($(subdir),elf)
-sysdep_routines += dl-vdso
-endif
-
ifeq ($(subdir),nptl)
libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
elision-trylock
@@ -7,10 +7,6 @@ librt-routines += rt-sysdep
librt-shared-only-routines += rt-sysdep
endif
-ifeq ($(subdir),elf)
-sysdep_routines += dl-vdso
-endif
-
ifeq ($(subdir),sysvipc)
sysdep_routines += getshmlba
endif
@@ -34,13 +34,6 @@
#else /* __ASSEMBLER__ */
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
- ({ \
- long _ret = funcptr (args); \
- err = ((unsigned long) (_ret) >= (unsigned long) -4095L); \
- _ret; \
- })
-
# define VDSO_NAME "LINUX_2.6"
# define VDSO_HASH 61765110
@@ -19,71 +19,29 @@
#ifndef SYSDEP_VDSO_LINUX_H
# define SYSDEP_VDSO_LINUX_H
-#include <dl-vdso.h>
+#include <ldsodefs.h>
+/* Return the errno value as a negative value in case of an error or 0 or
+ positive value otherwise. */
#ifndef INTERNAL_VSYSCALL_CALL
-# define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
- funcptr (args)
+# define INTERNAL_VSYSCALL_CALL(funcptr, nr, args...) \
+ funcptr (args)
#endif
-#ifdef HAVE_VSYSCALL
-
-# include <libc-vdso.h>
-
-# define INLINE_VSYSCALL(name, nr, args...) \
- ({ \
- __label__ out; \
- __label__ iserr; \
- INTERNAL_SYSCALL_DECL (sc_err); \
- long int sc_ret; \
- \
- __typeof (__vdso_##name) vdsop = __vdso_##name; \
- PTR_DEMANGLE (vdsop); \
- if (vdsop != NULL) \
- { \
- sc_ret = INTERNAL_VSYSCALL_CALL (vdsop, sc_err, nr, ##args); \
- if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
- goto out; \
- if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS) \
- goto iserr; \
- } \
- \
- sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args); \
- if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
- { \
- iserr: \
- __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \
- sc_ret = -1L; \
- } \
- out: \
- 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; \
+#define INLINE_VSYSCALL(name, nr, args...) \
+ ({ \
+ long int sc_ret = -1; \
+ __typeof (name) *vdsop = GLRO(dl_vdso_##name); \
+ if (vdsop != NULL) \
+ { \
+ sc_ret = INTERNAL_VSYSCALL_CALL (vdsop, nr, ##args); \
+ if ((unsigned long) sc_ret > -4096UL) \
+ { \
+ __set_errno (-sc_ret); \
+ sc_ret = -1L; \
+ } \
+ } \
+ sc_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 */
@@ -20,10 +20,6 @@ CFLAGS-elision-timed.c += -mrtm
CFLAGS-elision-trylock.c += -mrtm
endif
-ifeq ($(subdir),elf)
-sysdep_routines += dl-vdso
-endif
-
ifeq ($(subdir),setjmp)
tests += tst-saved_mask-1
endif
@@ -18,10 +18,6 @@
#include <time.h>
#include <sysdep.h>
-
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
#include <sysdep-vdso.h>
static int
@@ -30,17 +26,17 @@ __gettimeofday_syscall (struct timeval *restrict tv, void *restrict tz)
if (__glibc_unlikely (tz != 0))
memset (tz, 0, sizeof *tz);
- return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+ int ret = INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+ if (ret != -1)
+ return ret;
+ return INLINE_SYSCALL_CALL (gettimeofday, tv, tz);
}
#ifdef SHARED
-# include <dl-vdso.h>
-# include <libc-vdso.h>
-
# define INIT_ARCH()
/* If the vDSO is not available we fall back to syscall. */
libc_ifunc (__gettimeofday,
- (get_vdso_symbol (HAVE_GETTIMEOFDAY_VSYSCALL)
+ (GLRO(dl_vdso_gettimeofday)
?: __gettimeofday_syscall));
#else
@@ -18,26 +18,22 @@
#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)
{
- return INLINE_VSYSCALL (time, 1, t);
+ time_t ret = INLINE_VSYSCALL (time, 1, t);
+ if (ret != -1)
+ return ret;
+ return INLINE_SYSCALL_CALL (time, t);
}
#ifdef SHARED
-# include <dl-vdso.h>
-# include <libc-vdso.h>
-
#undef INIT_ARCH
#define INIT_ARCH()
/* If the vDSO is not available we fall back on the syscall. */
-libc_ifunc (time, (get_vdso_symbol ("__vdso_time") ?: time_vsyscall))
+libc_ifunc (time, (GLRO(dl_vdso_time) ?: time_vsyscall))
#else
time_t
time (time_t *t)