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>
This commit is contained in:
Adhemerval Zanella 2019-11-29 10:44:59 -03:00
parent 57013650f7
commit 1bdda52fe9
31 changed files with 258 additions and 290 deletions

View file

@ -74,10 +74,6 @@ _init (int argc, char **argv, char **envp)
_dl_non_dynamic_init (); _dl_non_dynamic_init ();
#endif #endif
#ifdef VDSO_SETUP
VDSO_SETUP ();
#endif
__init_misc (argc, argv, envp); __init_misc (argc, argv, envp);
/* Initialize ctype data. */ /* Initialize ctype data. */

View file

@ -34,6 +34,8 @@
#include <unsecvars.h> #include <unsecvars.h>
#include <hp-timing.h> #include <hp-timing.h>
#include <stackinfo.h> #include <stackinfo.h>
#include <dl-vdso.h>
#include <dl-vdso-setup.h>
extern char *__progname; extern char *__progname;
char **_dl_argv = &__progname; /* This is checked for some error messages. */ 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" # include "get-dynamic-info.h"
#endif #endif
#include "setup-vdso.h" #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 /* During the program run we must not modify the global data of
loaded shared object simultanously in two threads. Therefore we 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. */ so they can influence _dl_init_paths. */
setup_vdso (NULL, NULL); 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 /* Initialize the data structures for the search paths for shared
objects. */ objects. */
_dl_init_paths (getenv ("LD_LIBRARY_PATH")); _dl_init_paths (getenv ("LD_LIBRARY_PATH"));

View file

@ -39,6 +39,8 @@
#include <dl-osinfo.h> #include <dl-osinfo.h>
#include <dl-procinfo.h> #include <dl-procinfo.h>
#include <dl-prop.h> #include <dl-prop.h>
#include <dl-vdso.h>
#include <dl-vdso-setup.h>
#include <tls.h> #include <tls.h>
#include <stap-probe.h> #include <stap-probe.h>
#include <stackinfo.h> #include <stackinfo.h>
@ -833,7 +835,7 @@ security_init (void)
_dl_random = NULL; _dl_random = NULL;
} }
#include "setup-vdso.h" #include <setup-vdso.h>
/* The library search path. */ /* The library search path. */
static const char *library_path attribute_relro; 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. */ so they can influence _dl_init_paths. */
setup_vdso (main_map, &first_preload); setup_vdso (main_map, &first_preload);
/* With vDSO setup we can initialize the function pointers. */
setup_vdso_pointers ();
#ifdef DL_SYSDEP_OSCHECK #ifdef DL_SYSDEP_OSCHECK
DL_SYSDEP_OSCHECK (_dl_fatal_printf); DL_SYSDEP_OSCHECK (_dl_fatal_printf);
#endif #endif

View file

@ -28,6 +28,7 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
#include <time.h>
#if INTERPOSE_THREADS #if INTERPOSE_THREADS
#include <pthread.h> #include <pthread.h>
@ -96,6 +97,7 @@ struct __attribute__ ((aligned (__alignof__ (max_align_t)))) allocation_header
{ {
size_t allocation_index; size_t allocation_index;
size_t allocation_size; size_t allocation_size;
struct timespec ts;
}; };
/* Array of known allocations, to track invalid frees. */ /* Array of known allocations, to track invalid frees. */
@ -166,6 +168,9 @@ malloc_internal (size_t size)
.allocation_index = index, .allocation_index = index,
.allocation_size = allocation_size .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; return allocations[index] + 1;
} }

View file

@ -0,0 +1 @@
/* Empty. */

View file

@ -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

30
sysdeps/generic/dl-vdso.h Normal file
View file

@ -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

View file

@ -608,6 +608,12 @@ struct rtld_global_ro
/* At startup time we set up the normal DSO data structure for it, /* At startup time we set up the normal DSO data structure for it,
and this points to it. */ and this points to it. */
EXTERN struct link_map *_dl_sysinfo_map; EXTERN struct link_map *_dl_sysinfo_map;
# define PROCINFO_DECL
# ifndef PROCINFO_CLASS
# define PROCINFO_CLASS EXTERN
# endif
# include <dl-vdso-setup.c>
#endif #endif
/* Mask for more hardware capabilities that are available on some /* Mask for more hardware capabilities that are available on some

View file

@ -51,14 +51,14 @@ struct signal_frame_32 {
/* We don't care about the rest, since IP value is at 'mctx' field. */ /* 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) is_sigtramp_address (void *nip)
{ {
#ifdef HAVE_SIGTRAMP_RT32 #ifdef HAVE_SIGTRAMP_RT32
if (nip == VDSO_SYMBOL (sigtramp32)) if (nip == GLRO (dl_vdso_sigtramp_32))
return 1; return true;
#endif #endif
return 0; return false;
} }
struct rt_signal_frame_32 { 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. */ /* 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) is_sigtramp_address_rt (void * nip)
{ {
#ifdef HAVE_SIGTRAMP_32 #ifdef HAVE_SIGTRAMP_32
if (nip == VDSO_SYMBOL (sigtramp_rt32)) if (nip == GLRO (dl_vdso_sigtramp_rt32))
return 1; return true;
#endif #endif
return 0; return false;
} }
int int

View file

@ -54,14 +54,14 @@ struct signal_frame_64 {
/* We don't care about the rest, since the IP value is at 'uc' field. */ /* 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) is_sigtramp_address (void *nip)
{ {
#ifdef HAVE_SIGTRAMP_RT64 #ifdef HAVE_SIGTRAMP_RT64
if (nip == VDSO_SYMBOL (sigtramp_rt64)) if (nip == GLRO (dl_vdso_sigtramp_rt64))
return 1; return true;
#endif #endif
return 0; return false;
} }
int int

View file

@ -5,7 +5,6 @@ shared-only-routines += libc-__read_tp
endif endif
ifeq ($(subdir),elf) ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
sysdep-rtld-routines += __read_tp sysdep-rtld-routines += __read_tp
ifeq ($(build-shared),yes) ifeq ($(build-shared),yes)
# This is needed for DSO loading from static binaries. # This is needed for DSO loading from static binaries.

View file

@ -1,5 +1,4 @@
ifeq ($(subdir),elf) ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
sysdep-rtld-routines += aeabi_read_tp libc-do-syscall sysdep-rtld-routines += aeabi_read_tp libc-do-syscall
endif endif

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -22,11 +22,6 @@
#include <ldsodefs.h> #include <ldsodefs.h>
#include <dl-hash.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 /* If the architecture support vDSO it should define which is the expected
kernel version and hash value through both VDSO_NAME and VDSO_HASH kernel version and hash value through both VDSO_NAME and VDSO_HASH
(usually defined at architecture sysdep.h). */ (usually defined at architecture sysdep.h). */
@ -38,19 +33,26 @@ extern void *_dl_vdso_vsym (const char *name,
# define VDSO_HASH 0 # define VDSO_HASH 0
#endif #endif
/* Functions for resolving symbols in the VDSO link map. */
static inline void * static inline void *
get_vdso_symbol (const char *symbol) dl_vdso_vsym (const char *name)
{ {
struct r_found_version rfv = { VDSO_NAME, VDSO_HASH, 1, NULL }; struct link_map *map = GLRO (dl_sysinfo_map);
return _dl_vdso_vsym (symbol, &rfv); if (map == NULL)
} return NULL;
static inline void * /* Use a WEAK REF so we don't error out if the symbol is not found. */
get_vdso_mangle_symbol (const char *symbol) ElfW (Sym) wsym = { 0 };
{ wsym.st_info = (unsigned char) ELFW (ST_INFO (STB_WEAK, STT_NOTYPE));
void *vdsop = get_vdso_symbol (symbol);
PTR_MANGLE (vdsop); struct r_found_version rfv = { VDSO_NAME, VDSO_HASH, 1, NULL };
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 */ #endif /* dl-vdso.h */

View file

@ -25,6 +25,7 @@
# ifdef SHARED # ifdef SHARED
# include <dl-vdso.h> # include <dl-vdso.h>
# include <libc-vdso.h>
static int static int
__gettimeofday_syscall (struct timeval *restrict tv, void *restrict tz) __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 # undef INIT_ARCH
# define 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, libc_ifunc (__gettimeofday,
vdso_gettimeofday ? VDSO_IFUNC_RET (vdso_gettimeofday) vdso_gettimeofday ? VDSO_IFUNC_RET (vdso_gettimeofday)
: (void *) __gettimeofday_syscall) : (void *) __gettimeofday_syscall)

View file

@ -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>

View file

@ -19,37 +19,9 @@
#ifndef _LIBC_VDSO_H #ifndef _LIBC_VDSO_H
#define _LIBC_VDSO_H #define _LIBC_VDSO_H
#define VDSO_SYMBOL(__name) __vdso_##__name
/* Adjust the return IFUNC value from a vDSO symbol accordingly required /* 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 by the ELFv1 ABI. It is used by the architecture to create an ODP
entry since the kernel vDSO does not provide it. */ entry since the kernel vDSO does not provide it. */
#ifndef VDSO_IFUNC_RET #define VDSO_IFUNC_RET(__value) (__value)
# 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 #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 */

View file

@ -60,8 +60,6 @@ ifeq ($(subdir),elf)
ifeq ($(build-shared),yes) ifeq ($(build-shared),yes)
# This is needed for DSO loading from static binaries. # This is needed for DSO loading from static binaries.
sysdep-dl-routines += dl-static sysdep-dl-routines += dl-static
sysdep_routines += dl-vdso
endif endif
# If the compiler doesn't use GNU.stack note, # If the compiler doesn't use GNU.stack note,
# this test is expected to fail. # this test is expected to fail.

View file

@ -13,7 +13,6 @@ gen-as-const-headers += ucontext_i.sym
endif endif
ifeq ($(subdir),elf) ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
ifeq ($(build-shared),yes) ifeq ($(build-shared),yes)
# This is needed for DSO loading from static binaries. # This is needed for DSO loading from static binaries.
sysdep-dl-routines += dl-static sysdep-dl-routines += dl-static

View file

@ -21,7 +21,7 @@
#include <libc-internal.h> #include <libc-internal.h>
#include <not-cancel.h> #include <not-cancel.h>
#include <libc-vdso.h> #include <sysdep-vdso.h>
static uint64_t static uint64_t
get_timebase_freq_fallback (void) get_timebase_freq_fallback (void)
@ -101,8 +101,7 @@ uint64_t
__get_timebase_freq (void) __get_timebase_freq (void)
{ {
/* The vDSO does not have a fallback mechanism (such calling a syscall). */ /* The vDSO does not have a fallback mechanism (such calling a syscall). */
__typeof (VDSO_SYMBOL (get_tbfreq)) vdsop = VDSO_SYMBOL (get_tbfreq); uint64_t (*vdsop)(void) = GLRO(dl_vdso_get_tbfreq);
PTR_DEMANGLE (vdsop);
if (vdsop == NULL) if (vdsop == NULL)
return get_timebase_freq_fallback (); return get_timebase_freq_fallback ();

View file

@ -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>

View file

@ -54,14 +54,4 @@
# define VDSO_IFUNC_RET(value) ((void *) (value)) # define VDSO_IFUNC_RET(value) ((void *) (value))
#endif #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 */ #endif /* _LIBC_VDSO_H */

View file

@ -1,7 +1,3 @@
ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
endif
ifeq ($(subdir),misc) ifeq ($(subdir),misc)
sysdep_headers += sys/cachectl.h sysdep_headers += sys/cachectl.h
sysdep_routines += flush-icache sysdep_routines += flush-icache

View file

@ -39,7 +39,7 @@ __riscv_flush_icache_syscall (void *start, void *end, unsigned long int flags)
static func_type static func_type
__lookup_riscv_flush_icache (void) __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 /* 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 versions provide the vDSO entry, but QEMU's user-mode emulation doesn't

View file

@ -11,10 +11,6 @@ ifeq ($(subdir),stdlib)
gen-as-const-headers += ucontext_i.sym gen-as-const-headers += ucontext_i.sym
endif endif
ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
endif
ifeq ($(subdir),nptl) ifeq ($(subdir),nptl)
libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \ libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
elision-trylock elision-trylock

View file

@ -7,10 +7,6 @@ librt-routines += rt-sysdep
librt-shared-only-routines += rt-sysdep librt-shared-only-routines += rt-sysdep
endif endif
ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
endif
ifeq ($(subdir),sysvipc) ifeq ($(subdir),sysvipc)
sysdep_routines += getshmlba sysdep_routines += getshmlba
endif endif

View file

@ -19,8 +19,7 @@
#ifndef SYSDEP_VDSO_LINUX_H #ifndef SYSDEP_VDSO_LINUX_H
# define SYSDEP_VDSO_LINUX_H # define SYSDEP_VDSO_LINUX_H
#include <dl-vdso.h> #include <ldsodefs.h>
#include <libc-vdso.h>
#ifndef INTERNAL_VSYSCALL_CALL #ifndef INTERNAL_VSYSCALL_CALL
# define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \ # define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
@ -34,8 +33,7 @@
INTERNAL_SYSCALL_DECL (sc_err); \ INTERNAL_SYSCALL_DECL (sc_err); \
long int sc_ret; \ long int sc_ret; \
\ \
__typeof (__vdso_##name) vdsop = __vdso_##name; \ __typeof (GLRO(dl_vdso_##name)) vdsop = GLRO(dl_vdso_##name); \
PTR_DEMANGLE (vdsop); \
if (vdsop != NULL) \ if (vdsop != NULL) \
{ \ { \
sc_ret = INTERNAL_VSYSCALL_CALL (vdsop, sc_err, nr, ##args); \ sc_ret = INTERNAL_VSYSCALL_CALL (vdsop, sc_err, nr, ##args); \

View file

@ -24,6 +24,7 @@
#ifdef SHARED #ifdef SHARED
# include <dl-vdso.h> # include <dl-vdso.h>
# include <libc-vdso.h>
static time_t static time_t
time_syscall (time_t *t) time_syscall (time_t *t)
@ -33,7 +34,7 @@ time_syscall (time_t *t)
# undef INIT_ARCH # undef INIT_ARCH
# define 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, libc_ifunc (time,
vdso_time ? VDSO_IFUNC_RET (vdso_time) vdso_time ? VDSO_IFUNC_RET (vdso_time)
: (void *) time_syscall); : (void *) time_syscall);

View file

@ -20,10 +20,6 @@ CFLAGS-elision-timed.c += -mrtm
CFLAGS-elision-trylock.c += -mrtm CFLAGS-elision-trylock.c += -mrtm
endif endif
ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
endif
ifeq ($(subdir),setjmp) ifeq ($(subdir),setjmp)
tests += tst-saved_mask-1 tests += tst-saved_mask-1
endif endif