diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2019-11-29 10:44:59 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2020-01-03 11:22:07 -0300 |
commit | 1bdda52fe92fd01b424cd6fbb63e3df96a95015c (patch) | |
tree | d25214e63bf5c96ab48c11ec0df28b5d96ca99da | |
parent | 57013650f7e796428ac2c0b7512757e99327bfc9 (diff) | |
download | glibc-1bdda52fe92fd01b424cd6fbb63e3df96a95015c.tar.gz glibc-1bdda52fe92fd01b424cd6fbb63e3df96a95015c.tar.xz glibc-1bdda52fe92fd01b424cd6fbb63e3df96a95015c.zip |
elf: Move vDSO setup to rtld (BZ#24967)
This patch moves the vDSO setup from libc to loader code, just after the vDSO link_map setup. For static case the initialization is moved to _dl_non_dynamic_init instead. Instead of using the mangled pointer, the vDSO data is set as attribute_relro (on _rtld_global_ro for shared or _dl_vdso_* for static). It is read-only even with partial relro. It fixes BZ#24967 now that the vDSO pointer is setup earlier than malloc interposition is called. Also, vDSO calls should not be a problem for static dlopen as indicated by BZ#20802. The vDSO pointer would be zero-initialized and the syscall will be issued instead. Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, arm-linux-gnueabihf, powerpc64le-linux-gnu, powerpc64-linux-gnu, powerpc-linux-gnu, s390x-linux-gnu, sparc64-linux-gnu, and sparcv9-linux-gnu. I also run some tests on mips. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
31 files changed, 257 insertions, 289 deletions
diff --git a/csu/init-first.c b/csu/init-first.c index 669b779b70..1cd8a75098 100644 --- a/csu/init-first.c +++ b/csu/init-first.c @@ -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. */ diff --git a/elf/dl-support.c b/elf/dl-support.c index 508a5c1196..ad791ab6ab 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -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")); diff --git a/elf/rtld.c b/elf/rtld.c index 817fb86eac..553cfbd1b7 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -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 diff --git a/malloc/tst-interpose-aux.c b/malloc/tst-interpose-aux.c index 52696e92d3..a0ab2e5903 100644 --- a/malloc/tst-interpose-aux.c +++ b/malloc/tst-interpose-aux.c @@ -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; } diff --git a/sysdeps/generic/dl-vdso-setup.c b/sysdeps/generic/dl-vdso-setup.c new file mode 100644 index 0000000000..6e25b021ab --- /dev/null +++ b/sysdeps/generic/dl-vdso-setup.c @@ -0,0 +1 @@ +/* Empty. */ diff --git a/sysdeps/generic/dl-vdso-setup.h b/sysdeps/generic/dl-vdso-setup.h new file mode 100644 index 0000000000..5ef7531fac --- /dev/null +++ b/sysdeps/generic/dl-vdso-setup.h @@ -0,0 +1,28 @@ +/* ELF symbol initialization functions for VDSO objects. + Copyright (C) 2020 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 diff --git a/sysdeps/generic/dl-vdso.h b/sysdeps/generic/dl-vdso.h new file mode 100644 index 0000000000..70379a82a1 --- /dev/null +++ b/sysdeps/generic/dl-vdso.h @@ -0,0 +1,30 @@ +/* ELF symbol resolve functions for VDSO objects. + Copyright (C) 2020 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 diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 0a5d3473f5..497938ffa2 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -608,6 +608,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 diff --git a/sysdeps/powerpc/powerpc32/backtrace.c b/sysdeps/powerpc/powerpc32/backtrace.c index 4a35588671..7c2d4726f8 100644 --- a/sysdeps/powerpc/powerpc32/backtrace.c +++ b/sysdeps/powerpc/powerpc32/backtrace.c @@ -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 diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c index ee8ba21f27..65c260ab76 100644 --- a/sysdeps/powerpc/powerpc64/backtrace.c +++ b/sysdeps/powerpc/powerpc64/backtrace.c @@ -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 diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile index 57bbfeaac6..4bcae85bca 100644 --- a/sysdeps/unix/sysv/linux/aarch64/Makefile +++ b/sysdeps/unix/sysv/linux/aarch64/Makefile @@ -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. diff --git a/sysdeps/unix/sysv/linux/arm/Makefile b/sysdeps/unix/sysv/linux/arm/Makefile index d7a2f6a8a7..abdf01f00c 100644 --- a/sysdeps/unix/sysv/linux/arm/Makefile +++ b/sysdeps/unix/sysv/linux/arm/Makefile @@ -1,5 +1,4 @@ ifeq ($(subdir),elf) -sysdep_routines += dl-vdso sysdep-rtld-routines += aeabi_read_tp libc-do-syscall endif diff --git a/sysdeps/unix/sysv/linux/dl-vdso-setup.c b/sysdeps/unix/sysv/linux/dl-vdso-setup.c new file mode 100644 index 0000000000..352fcae529 --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-vdso-setup.c @@ -0,0 +1,81 @@ +/* Data for vDSO support. Linux version. + Copyright (C) 2020 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 int (*_dl_vdso_clock_gettime) (clockid_t, + struct timespec *) RELRO; +#endif +# ifdef HAVE_GETTIMEOFDAY_VSYSCALL +PROCINFO_CLASS int (*_dl_vdso_gettimeofday) (struct timeval *, void *) RELRO; +#endif +# ifdef HAVE_TIME_VSYSCALL +PROCINFO_CLASS time_t (*_dl_vdso_time) (time_t *) RELRO; +# endif +# ifdef HAVE_GETCPU_VSYSCALL +PROCINFO_CLASS int (*_dl_vdso_getcpu) (unsigned *, unsigned *, void *) RELRO; +# endif +# ifdef HAVE_CLOCK_GETRES_VSYSCALL +PROCINFO_CLASS int (*_dl_vdso_clock_getres) (clockid_t, + struct timespec *) RELRO; +# endif + +/* PowerPC specific ones. */ +# ifdef HAVE_GET_TBFREQ +PROCINFO_CLASS uint64_t (*_dl_vdso_get_tbfreq)(void) RELRO; +# endif +/* The sigtramp are used on powerpc backtrace without using + INLINE_VSYSCALL, so there is no need to set their type. */ +# 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 diff --git a/sysdeps/unix/sysv/linux/dl-vdso-setup.h b/sysdeps/unix/sysv/linux/dl-vdso-setup.h new file mode 100644 index 0000000000..9f5e4a3b0b --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-vdso-setup.h @@ -0,0 +1,55 @@ +/* ELF symbol initialization functions for VDSO objects. Linux version. + Copyright (C) 2020 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) = 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 diff --git a/sysdeps/unix/sysv/linux/dl-vdso.c b/sysdeps/unix/sysv/linux/dl-vdso.c deleted file mode 100644 index 08aefde4a4..0000000000 --- a/sysdeps/unix/sysv/linux/dl-vdso.c +++ /dev/null @@ -1,48 +0,0 @@ -/* ELF symbol resolve functions for VDSO objects. - Copyright (C) 2005-2020 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; -} diff --git a/sysdeps/unix/sysv/linux/dl-vdso.h b/sysdeps/unix/sysv/linux/dl-vdso.h index 4fe6fe1d10..12051b98e1 100644 --- a/sysdeps/unix/sysv/linux/dl-vdso.h +++ b/sysdeps/unix/sysv/linux/dl-vdso.h @@ -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 */ diff --git a/sysdeps/unix/sysv/linux/gettimeofday.c b/sysdeps/unix/sysv/linux/gettimeofday.c index 80d6819e5a..d5cdb22495 100644 --- a/sysdeps/unix/sysv/linux/gettimeofday.c +++ b/sysdeps/unix/sysv/linux/gettimeofday.c @@ -25,6 +25,7 @@ # ifdef SHARED # include <dl-vdso.h> +# include <libc-vdso.h> static int __gettimeofday_syscall (struct timeval *restrict tv, void *restrict tz) @@ -36,7 +37,7 @@ __gettimeofday_syscall (struct timeval *restrict tv, void *restrict tz) # undef INIT_ARCH # define INIT_ARCH() \ - void *vdso_gettimeofday = get_vdso_symbol (HAVE_GETTIMEOFDAY_VSYSCALL) + void *vdso_gettimeofday = dl_vdso_vsym (HAVE_GETTIMEOFDAY_VSYSCALL) libc_ifunc (__gettimeofday, vdso_gettimeofday ? VDSO_IFUNC_RET (vdso_gettimeofday) : (void *) __gettimeofday_syscall) diff --git a/sysdeps/unix/sysv/linux/init-first.c b/sysdeps/unix/sysv/linux/init-first.c deleted file mode 100644 index a215a1b376..0000000000 --- a/sysdeps/unix/sysv/linux/init-first.c +++ /dev/null @@ -1,90 +0,0 @@ -/* vDSO internal symbols. Linux generic version. - Copyright (C) 2019-2020 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_gettime64 implementation. */ -#ifdef HAVE_CLOCK_GETTIME64_VSYSCALL -int (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *) - 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_GETTIME64_VSYSCALL - VDSO_SYMBOL(clock_gettime64) - = get_vdso_mangle_symbol (HAVE_CLOCK_GETTIME64_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> diff --git a/sysdeps/unix/sysv/linux/libc-vdso.h b/sysdeps/unix/sysv/linux/libc-vdso.h index 1d7af16be8..31ceafe9d8 100644 --- a/sysdeps/unix/sysv/linux/libc-vdso.h +++ b/sysdeps/unix/sysv/linux/libc-vdso.h @@ -19,37 +19,9 @@ #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 +#define VDSO_IFUNC_RET(__value) (__value) -#ifdef HAVE_CLOCK_GETTIME_VSYSCALL -extern int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *) - attribute_hidden; -#endif -#ifdef HAVE_CLOCK_GETTIME64_VSYSCALL -extern int (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *) - 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 */ diff --git a/sysdeps/unix/sysv/linux/mips/Makefile b/sysdeps/unix/sysv/linux/mips/Makefile index 03044e7365..026ba242cf 100644 --- a/sysdeps/unix/sysv/linux/mips/Makefile +++ b/sysdeps/unix/sysv/linux/mips/Makefile @@ -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. diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile index 1596238afa..cc2f804d86 100644 --- a/sysdeps/unix/sysv/linux/powerpc/Makefile +++ b/sysdeps/unix/sysv/linux/powerpc/Makefile @@ -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 diff --git a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c index ebd0d2f880..81f7c73f38 100644 --- a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c +++ b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c @@ -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,8 +101,7 @@ 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); + uint64_t (*vdsop)(void) = GLRO(dl_vdso_get_tbfreq); if (vdsop == NULL) return get_timebase_freq_fallback (); diff --git a/sysdeps/unix/sysv/linux/powerpc/init-first.c b/sysdeps/unix/sysv/linux/powerpc/init-first.c deleted file mode 100644 index d20938c1da..0000000000 --- a/sysdeps/unix/sysv/linux/powerpc/init-first.c +++ /dev/null @@ -1,50 +0,0 @@ -/* Initialization code run first thing by the ELF startup code. Linux/PowerPC. - Copyright (C) 2007-2020 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> diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h index 2f18a762d8..8dae14057c 100644 --- a/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h +++ b/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h @@ -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 */ diff --git a/sysdeps/unix/sysv/linux/riscv/Makefile b/sysdeps/unix/sysv/linux/riscv/Makefile index b7ad31885c..301b082398 100644 --- a/sysdeps/unix/sysv/linux/riscv/Makefile +++ b/sysdeps/unix/sysv/linux/riscv/Makefile @@ -1,7 +1,3 @@ -ifeq ($(subdir),elf) -sysdep_routines += dl-vdso -endif - ifeq ($(subdir),misc) sysdep_headers += sys/cachectl.h sysdep_routines += flush-icache diff --git a/sysdeps/unix/sysv/linux/riscv/flush-icache.c b/sysdeps/unix/sysv/linux/riscv/flush-icache.c index f1565ab2dd..72caeb190f 100644 --- a/sysdeps/unix/sysv/linux/riscv/flush-icache.c +++ b/sysdeps/unix/sysv/linux/riscv/flush-icache.c @@ -39,7 +39,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 diff --git a/sysdeps/unix/sysv/linux/s390/Makefile b/sysdeps/unix/sysv/linux/s390/Makefile index 77f38523b5..d9db1b5422 100644 --- a/sysdeps/unix/sysv/linux/s390/Makefile +++ b/sysdeps/unix/sysv/linux/s390/Makefile @@ -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 diff --git a/sysdeps/unix/sysv/linux/sparc/Makefile b/sysdeps/unix/sysv/linux/sparc/Makefile index fb3ee5b8a1..b0d182a439 100644 --- a/sysdeps/unix/sysv/linux/sparc/Makefile +++ b/sysdeps/unix/sysv/linux/sparc/Makefile @@ -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 diff --git a/sysdeps/unix/sysv/linux/sysdep-vdso.h b/sysdeps/unix/sysv/linux/sysdep-vdso.h index f0cc384d78..dc6eaddbbf 100644 --- a/sysdeps/unix/sysv/linux/sysdep-vdso.h +++ b/sysdeps/unix/sysv/linux/sysdep-vdso.h @@ -19,8 +19,7 @@ #ifndef SYSDEP_VDSO_LINUX_H # define SYSDEP_VDSO_LINUX_H -#include <dl-vdso.h> -#include <libc-vdso.h> +#include <ldsodefs.h> #ifndef INTERNAL_VSYSCALL_CALL # define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \ @@ -34,8 +33,7 @@ INTERNAL_SYSCALL_DECL (sc_err); \ long int sc_ret; \ \ - __typeof (__vdso_##name) vdsop = __vdso_##name; \ - PTR_DEMANGLE (vdsop); \ + __typeof (GLRO(dl_vdso_##name)) vdsop = GLRO(dl_vdso_##name); \ if (vdsop != NULL) \ { \ sc_ret = INTERNAL_VSYSCALL_CALL (vdsop, sc_err, nr, ##args); \ diff --git a/sysdeps/unix/sysv/linux/time.c b/sysdeps/unix/sysv/linux/time.c index 2dc4cbe786..9d8e573c0a 100644 --- a/sysdeps/unix/sysv/linux/time.c +++ b/sysdeps/unix/sysv/linux/time.c @@ -24,6 +24,7 @@ #ifdef SHARED # include <dl-vdso.h> +# include <libc-vdso.h> static time_t time_syscall (time_t *t) @@ -33,7 +34,7 @@ time_syscall (time_t *t) # undef INIT_ARCH # define INIT_ARCH() \ - void *vdso_time = get_vdso_symbol (HAVE_TIME_VSYSCALL); + void *vdso_time = dl_vdso_vsym (HAVE_TIME_VSYSCALL); libc_ifunc (time, vdso_time ? VDSO_IFUNC_RET (vdso_time) : (void *) time_syscall); diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile index 02ca36c6d2..b23b532590 100644 --- a/sysdeps/unix/sysv/linux/x86/Makefile +++ b/sysdeps/unix/sysv/linux/x86/Makefile @@ -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 |