[v3,09/16] elf: Move vDSO setup to rtld (BZ#24967)

Message ID 20191217214728.2886-9-adhemerval.zanella@linaro.org
State New
Headers show
Series
  • [v2,01/16] linux: Fix vDSO macros build with time64 interfaces
Related show

Commit Message

Adhemerval Zanella Dec. 17, 2019, 9:47 p.m.
Changes from previous version:

  - Do not GLRO access on ifunc resolver, ut rather call the vDSO
    resolve function instead (dl_vdso_vsym).

--

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.
---
 csu/init-first.c                              |  4 -
 elf/dl-support.c                              |  7 ++
 elf/rtld.c                                    |  7 +-
 malloc/tst-interpose-aux.c                    |  5 ++
 sysdeps/generic/dl-vdso-setup.c               |  1 +
 sysdeps/generic/dl-vdso-setup.h               | 28 ++++++
 sysdeps/generic/dl-vdso.h                     | 30 +++++++
 sysdeps/generic/ldsodefs.h                    |  6 ++
 sysdeps/powerpc/powerpc32/backtrace.c         | 16 ++--
 sysdeps/powerpc/powerpc64/backtrace.c         |  8 +-
 sysdeps/unix/sysv/linux/aarch64/Makefile      |  1 -
 sysdeps/unix/sysv/linux/arm/Makefile          |  1 -
 sysdeps/unix/sysv/linux/dl-vdso-setup.c       | 81 +++++++++++++++++
 sysdeps/unix/sysv/linux/dl-vdso-setup.h       | 55 ++++++++++++
 sysdeps/unix/sysv/linux/dl-vdso.c             | 48 ----------
 sysdeps/unix/sysv/linux/dl-vdso.h             | 30 ++++---
 sysdeps/unix/sysv/linux/gettimeofday.c        |  3 +-
 sysdeps/unix/sysv/linux/init-first.c          | 90 -------------------
 sysdeps/unix/sysv/linux/libc-vdso.h           | 30 +------
 sysdeps/unix/sysv/linux/mips/Makefile         |  2 -
 sysdeps/unix/sysv/linux/powerpc/Makefile      |  1 -
 .../sysv/linux/powerpc/get_timebase_freq.c    |  5 +-
 sysdeps/unix/sysv/linux/powerpc/init-first.c  | 50 -----------
 sysdeps/unix/sysv/linux/powerpc/libc-vdso.h   | 10 ---
 sysdeps/unix/sysv/linux/riscv/Makefile        |  4 -
 sysdeps/unix/sysv/linux/riscv/flush-icache.c  |  2 +-
 sysdeps/unix/sysv/linux/s390/Makefile         |  4 -
 sysdeps/unix/sysv/linux/sparc/Makefile        |  4 -
 sysdeps/unix/sysv/linux/sysdep-vdso.h         |  6 +-
 sysdeps/unix/sysv/linux/time.c                |  3 +-
 sysdeps/unix/sysv/linux/x86/Makefile          |  4 -
 31 files changed, 257 insertions(+), 289 deletions(-)
 create mode 100644 sysdeps/generic/dl-vdso-setup.c
 create mode 100644 sysdeps/generic/dl-vdso-setup.h
 create mode 100644 sysdeps/generic/dl-vdso.h
 create mode 100644 sysdeps/unix/sysv/linux/dl-vdso-setup.c
 create mode 100644 sysdeps/unix/sysv/linux/dl-vdso-setup.h
 delete mode 100644 sysdeps/unix/sysv/linux/dl-vdso.c
 delete mode 100644 sysdeps/unix/sysv/linux/init-first.c
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/init-first.c

-- 
2.17.1

Comments

Siddhesh Poyarekar Jan. 2, 2020, 12:55 p.m. | #1
On 18/12/19 3:17 am, Adhemerval Zanella wrote:
> Changes from previous version:

> 

>   - Do not GLRO access on ifunc resolver, ut rather call the vDSO

>     resolve function instead (dl_vdso_vsym).

> 

> --

> 

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

> ---

>  csu/init-first.c                              |  4 -

>  elf/dl-support.c                              |  7 ++

>  elf/rtld.c                                    |  7 +-

>  malloc/tst-interpose-aux.c                    |  5 ++

>  sysdeps/generic/dl-vdso-setup.c               |  1 +

>  sysdeps/generic/dl-vdso-setup.h               | 28 ++++++

>  sysdeps/generic/dl-vdso.h                     | 30 +++++++

>  sysdeps/generic/ldsodefs.h                    |  6 ++

>  sysdeps/powerpc/powerpc32/backtrace.c         | 16 ++--

>  sysdeps/powerpc/powerpc64/backtrace.c         |  8 +-

>  sysdeps/unix/sysv/linux/aarch64/Makefile      |  1 -

>  sysdeps/unix/sysv/linux/arm/Makefile          |  1 -

>  sysdeps/unix/sysv/linux/dl-vdso-setup.c       | 81 +++++++++++++++++

>  sysdeps/unix/sysv/linux/dl-vdso-setup.h       | 55 ++++++++++++

>  sysdeps/unix/sysv/linux/dl-vdso.c             | 48 ----------

>  sysdeps/unix/sysv/linux/dl-vdso.h             | 30 ++++---

>  sysdeps/unix/sysv/linux/gettimeofday.c        |  3 +-

>  sysdeps/unix/sysv/linux/init-first.c          | 90 -------------------

>  sysdeps/unix/sysv/linux/libc-vdso.h           | 30 +------

>  sysdeps/unix/sysv/linux/mips/Makefile         |  2 -

>  sysdeps/unix/sysv/linux/powerpc/Makefile      |  1 -

>  .../sysv/linux/powerpc/get_timebase_freq.c    |  5 +-

>  sysdeps/unix/sysv/linux/powerpc/init-first.c  | 50 -----------

>  sysdeps/unix/sysv/linux/powerpc/libc-vdso.h   | 10 ---

>  sysdeps/unix/sysv/linux/riscv/Makefile        |  4 -

>  sysdeps/unix/sysv/linux/riscv/flush-icache.c  |  2 +-

>  sysdeps/unix/sysv/linux/s390/Makefile         |  4 -

>  sysdeps/unix/sysv/linux/sparc/Makefile        |  4 -

>  sysdeps/unix/sysv/linux/sysdep-vdso.h         |  6 +-

>  sysdeps/unix/sysv/linux/time.c                |  3 +-

>  sysdeps/unix/sysv/linux/x86/Makefile          |  4 -

>  31 files changed, 257 insertions(+), 289 deletions(-)

>  create mode 100644 sysdeps/generic/dl-vdso-setup.c

>  create mode 100644 sysdeps/generic/dl-vdso-setup.h

>  create mode 100644 sysdeps/generic/dl-vdso.h

>  create mode 100644 sysdeps/unix/sysv/linux/dl-vdso-setup.c

>  create mode 100644 sysdeps/unix/sysv/linux/dl-vdso-setup.h

>  delete mode 100644 sysdeps/unix/sysv/linux/dl-vdso.c

>  delete mode 100644 sysdeps/unix/sysv/linux/init-first.c

>  delete mode 100644 sysdeps/unix/sysv/linux/powerpc/init-first.c

> 


OK with some minor nits fixed, see below.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>



> diff --git a/csu/init-first.c b/csu/init-first.c

> index e0f489ee6d..891719a839 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 b2b1b12f6f..81d44b0343 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 dd8fc5e6c6..a06e13c657 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 bbe321e843..8cbc3e6fea 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..3d79bae317

> --- /dev/null

> +++ b/sysdeps/generic/dl-vdso-setup.h

> @@ -0,0 +1,28 @@

> +/* ELF symbol initialization functions for VDSO objects.

> +   Copyright (C) 2019 Free Software Foundation, Inc.


Update copyright year.

> +   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..5651f49a1a

> --- /dev/null

> +++ b/sysdeps/generic/dl-vdso.h

> @@ -0,0 +1,30 @@

> +/* ELF symbol resolve functions for VDSO objects.

> +   Copyright (C) 2019 Free Software Foundation, Inc.


Update copyright year.

> +   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 fc25a81e1c..8cbd0e87cc 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 2e6a859d9f..f2a57480a5 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 234d9c00dc..8ed5bc1585 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..1069879f1a

> --- /dev/null

> +++ b/sysdeps/unix/sysv/linux/dl-vdso-setup.c

> @@ -0,0 +1,81 @@

> +/* Data for vDSO support.  Linux version.

> +   Copyright (C) 2019 Free Software Foundation, Inc.


Update copyright year.

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


Fix indentation.

> +# ifdef HAVE_GETTIMEOFDAY_VSYSCALL

> +PROCINFO_CLASS int (*_dl_vdso_gettimeofday) (struct timeval *, void *) RELRO;

> +#endif


Fix indentation.

> +# 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..f4e76202fc

> --- /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) 2019 Free Software Foundation, Inc.


Update copyright year.

> +   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 5577f2103c..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-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;

> -}

> diff --git a/sysdeps/unix/sysv/linux/dl-vdso.h b/sysdeps/unix/sysv/linux/dl-vdso.h

> index 19ffd30c7e..d1e782b81f 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 600da6b468..6945be269c 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 d005d13322..0000000000

> --- a/sysdeps/unix/sysv/linux/init-first.c

> +++ /dev/null

> @@ -1,90 +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_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 c6d505bab3..004faf0a97 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 29b6624b9a..11eb2b126d 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 92a4af83af..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-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>

> diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h

> index cb7da3b289..adc06d48b0 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 c5bd60d9c2..e967e40deb 100644

> --- a/sysdeps/unix/sysv/linux/riscv/flush-icache.c

> +++ b/sysdeps/unix/sysv/linux/riscv/flush-icache.c

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

> 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 76a211e39b..772313f97e 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 0598958c9c..a7e4cbeb96 100644

> --- a/sysdeps/unix/sysv/linux/time.c

> +++ b/sysdeps/unix/sysv/linux/time.c

> @@ -25,6 +25,7 @@

>  

>  #ifdef SHARED

>  # include <dl-vdso.h>

> +# include <libc-vdso.h>

>  

>  static time_t

>  time_syscall (time_t *t)

> @@ -34,7 +35,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

>
Adhemerval Zanella Jan. 2, 2020, 1 p.m. | #2
On 02/01/2020 09:55, Siddhesh Poyarekar wrote:
> On 18/12/19 3:17 am, Adhemerval Zanella wrote:

>> Changes from previous version:

>>

>>   - Do not GLRO access on ifunc resolver, ut rather call the vDSO

>>     resolve function instead (dl_vdso_vsym).

>>

>> --

>>

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

>> ---

>>  csu/init-first.c                              |  4 -

>>  elf/dl-support.c                              |  7 ++

>>  elf/rtld.c                                    |  7 +-

>>  malloc/tst-interpose-aux.c                    |  5 ++

>>  sysdeps/generic/dl-vdso-setup.c               |  1 +

>>  sysdeps/generic/dl-vdso-setup.h               | 28 ++++++

>>  sysdeps/generic/dl-vdso.h                     | 30 +++++++

>>  sysdeps/generic/ldsodefs.h                    |  6 ++

>>  sysdeps/powerpc/powerpc32/backtrace.c         | 16 ++--

>>  sysdeps/powerpc/powerpc64/backtrace.c         |  8 +-

>>  sysdeps/unix/sysv/linux/aarch64/Makefile      |  1 -

>>  sysdeps/unix/sysv/linux/arm/Makefile          |  1 -

>>  sysdeps/unix/sysv/linux/dl-vdso-setup.c       | 81 +++++++++++++++++

>>  sysdeps/unix/sysv/linux/dl-vdso-setup.h       | 55 ++++++++++++

>>  sysdeps/unix/sysv/linux/dl-vdso.c             | 48 ----------

>>  sysdeps/unix/sysv/linux/dl-vdso.h             | 30 ++++---

>>  sysdeps/unix/sysv/linux/gettimeofday.c        |  3 +-

>>  sysdeps/unix/sysv/linux/init-first.c          | 90 -------------------

>>  sysdeps/unix/sysv/linux/libc-vdso.h           | 30 +------

>>  sysdeps/unix/sysv/linux/mips/Makefile         |  2 -

>>  sysdeps/unix/sysv/linux/powerpc/Makefile      |  1 -

>>  .../sysv/linux/powerpc/get_timebase_freq.c    |  5 +-

>>  sysdeps/unix/sysv/linux/powerpc/init-first.c  | 50 -----------

>>  sysdeps/unix/sysv/linux/powerpc/libc-vdso.h   | 10 ---

>>  sysdeps/unix/sysv/linux/riscv/Makefile        |  4 -

>>  sysdeps/unix/sysv/linux/riscv/flush-icache.c  |  2 +-

>>  sysdeps/unix/sysv/linux/s390/Makefile         |  4 -

>>  sysdeps/unix/sysv/linux/sparc/Makefile        |  4 -

>>  sysdeps/unix/sysv/linux/sysdep-vdso.h         |  6 +-

>>  sysdeps/unix/sysv/linux/time.c                |  3 +-

>>  sysdeps/unix/sysv/linux/x86/Makefile          |  4 -

>>  31 files changed, 257 insertions(+), 289 deletions(-)

>>  create mode 100644 sysdeps/generic/dl-vdso-setup.c

>>  create mode 100644 sysdeps/generic/dl-vdso-setup.h

>>  create mode 100644 sysdeps/generic/dl-vdso.h

>>  create mode 100644 sysdeps/unix/sysv/linux/dl-vdso-setup.c

>>  create mode 100644 sysdeps/unix/sysv/linux/dl-vdso-setup.h

>>  delete mode 100644 sysdeps/unix/sysv/linux/dl-vdso.c

>>  delete mode 100644 sysdeps/unix/sysv/linux/init-first.c

>>  delete mode 100644 sysdeps/unix/sysv/linux/powerpc/init-first.c

>>

> 

> OK with some minor nits fixed, see below.

> 

> Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>


>> diff --git a/sysdeps/generic/dl-vdso-setup.h b/sysdeps/generic/dl-vdso-setup.h

>> new file mode 100644

>> index 0000000000..3d79bae317

>> --- /dev/null

>> +++ b/sysdeps/generic/dl-vdso-setup.h

>> @@ -0,0 +1,28 @@

>> +/* ELF symbol initialization functions for VDSO objects.

>> +   Copyright (C) 2019 Free Software Foundation, Inc.

> 

> Update copyright year.


Ack.

> 

>> +   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..5651f49a1a

>> --- /dev/null

>> +++ b/sysdeps/generic/dl-vdso.h

>> @@ -0,0 +1,30 @@

>> +/* ELF symbol resolve functions for VDSO objects.

>> +   Copyright (C) 2019 Free Software Foundation, Inc.

> 

> Update copyright year.


Ack.

>> 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..1069879f1a

>> --- /dev/null

>> +++ b/sysdeps/unix/sysv/linux/dl-vdso-setup.c

>> @@ -0,0 +1,81 @@

>> +/* Data for vDSO support.  Linux version.

>> +   Copyright (C) 2019 Free Software Foundation, Inc.

> 

> Update copyright year.


Ack.

> 

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

> 

> Fix indentation.


Ack.

> 

>> +# ifdef HAVE_GETTIMEOFDAY_VSYSCALL

>> +PROCINFO_CLASS int (*_dl_vdso_gettimeofday) (struct timeval *, void *) RELRO;

>> +#endif

> 

> Fix indentation.


Ack.
Lukasz Majewski Jan. 7, 2020, 4:13 p.m. | #3
Hi Adhemerval, Siddhesh

> On 02/01/2020 09:55, Siddhesh Poyarekar wrote:

> > On 18/12/19 3:17 am, Adhemerval Zanella wrote:  

> >> Changes from previous version:

> >>

> >>   - Do not GLRO access on ifunc resolver, ut rather call the vDSO

> >>     resolve function instead (dl_vdso_vsym).

> >>

> >> --

> >>

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

> >> ---

> >>  csu/init-first.c                              |  4 -

> >>  elf/dl-support.c                              |  7 ++

> >>  elf/rtld.c                                    |  7 +-

> >>  malloc/tst-interpose-aux.c                    |  5 ++

> >>  sysdeps/generic/dl-vdso-setup.c               |  1 +

> >>  sysdeps/generic/dl-vdso-setup.h               | 28 ++++++

> >>  sysdeps/generic/dl-vdso.h                     | 30 +++++++

> >>  sysdeps/generic/ldsodefs.h                    |  6 ++

> >>  sysdeps/powerpc/powerpc32/backtrace.c         | 16 ++--

> >>  sysdeps/powerpc/powerpc64/backtrace.c         |  8 +-

> >>  sysdeps/unix/sysv/linux/aarch64/Makefile      |  1 -

> >>  sysdeps/unix/sysv/linux/arm/Makefile          |  1 -

> >>  sysdeps/unix/sysv/linux/dl-vdso-setup.c       | 81

> >> +++++++++++++++++ sysdeps/unix/sysv/linux/dl-vdso-setup.h       |

> >> 55 ++++++++++++ sysdeps/unix/sysv/linux/dl-vdso.c             | 48

> >> ---------- sysdeps/unix/sysv/linux/dl-vdso.h             | 30

> >> ++++--- sysdeps/unix/sysv/linux/gettimeofday.c        |  3 +-

> >>  sysdeps/unix/sysv/linux/init-first.c          | 90

> >> ------------------- sysdeps/unix/sysv/linux/libc-vdso.h

> >> | 30 +------ sysdeps/unix/sysv/linux/mips/Makefile         |  2 -

> >>  sysdeps/unix/sysv/linux/powerpc/Makefile      |  1 -

> >>  .../sysv/linux/powerpc/get_timebase_freq.c    |  5 +-

> >>  sysdeps/unix/sysv/linux/powerpc/init-first.c  | 50 -----------

> >>  sysdeps/unix/sysv/linux/powerpc/libc-vdso.h   | 10 ---

> >>  sysdeps/unix/sysv/linux/riscv/Makefile        |  4 -

> >>  sysdeps/unix/sysv/linux/riscv/flush-icache.c  |  2 +-

> >>  sysdeps/unix/sysv/linux/s390/Makefile         |  4 -

> >>  sysdeps/unix/sysv/linux/sparc/Makefile        |  4 -

> >>  sysdeps/unix/sysv/linux/sysdep-vdso.h         |  6 +-

> >>  sysdeps/unix/sysv/linux/time.c                |  3 +-

> >>  sysdeps/unix/sysv/linux/x86/Makefile          |  4 -

> >>  31 files changed, 257 insertions(+), 289 deletions(-)

> >>  create mode 100644 sysdeps/generic/dl-vdso-setup.c

> >>  create mode 100644 sysdeps/generic/dl-vdso-setup.h

> >>  create mode 100644 sysdeps/generic/dl-vdso.h

> >>  create mode 100644 sysdeps/unix/sysv/linux/dl-vdso-setup.c

> >>  create mode 100644 sysdeps/unix/sysv/linux/dl-vdso-setup.h

> >>  delete mode 100644 sysdeps/unix/sysv/linux/dl-vdso.c

> >>  delete mode 100644 sysdeps/unix/sysv/linux/init-first.c

> >>  delete mode 100644 sysdeps/unix/sysv/linux/powerpc/init-first.c

> >>  

> > 

> > OK with some minor nits fixed, see below.

> > 

> > Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>  

> 

> >> diff --git a/sysdeps/generic/dl-vdso-setup.h

> >> b/sysdeps/generic/dl-vdso-setup.h new file mode 100644

> >> index 0000000000..3d79bae317

> >> --- /dev/null

> >> +++ b/sysdeps/generic/dl-vdso-setup.h

> >> @@ -0,0 +1,28 @@

> >> +/* ELF symbol initialization functions for VDSO objects.

> >> +   Copyright (C) 2019 Free Software Foundation, Inc.  

> > 

> > Update copyright year.  

> 

> Ack.

> 

> >   

> >> +   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..5651f49a1a

> >> --- /dev/null

> >> +++ b/sysdeps/generic/dl-vdso.h

> >> @@ -0,0 +1,30 @@

> >> +/* ELF symbol resolve functions for VDSO objects.

> >> +   Copyright (C) 2019 Free Software Foundation, Inc.  

> > 

> > Update copyright year.  

> 

> Ack.

> 

> >> 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..1069879f1a

> >> --- /dev/null

> >> +++ b/sysdeps/unix/sysv/linux/dl-vdso-setup.c

> >> @@ -0,0 +1,81 @@

> >> +/* Data for vDSO support.  Linux version.

> >> +   Copyright (C) 2019 Free Software Foundation, Inc.  

> > 

> > Update copyright year.  

> 

> Ack.

> 

> >   

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

> > 

> > Fix indentation.  

> 

> Ack.

> 

> >   

> >> +# ifdef HAVE_GETTIMEOFDAY_VSYSCALL

> >> +PROCINFO_CLASS int (*_dl_vdso_gettimeofday) (struct timeval *,

> >> void *) RELRO; +#endif  

> > 

> > Fix indentation.  

> 

> Ack.


Unfortunately this patch caused regression on my ARMv7 32 bit setup.
Please find filled in bugzilla entry:

https://sourceware.org/bugzilla/show_bug.cgi?id=25352


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
Adhemerval Zanella Jan. 7, 2020, 7:40 p.m. | #4
On 07/01/2020 13:13, Lukasz Majewski wrote:
> 

> Unfortunately this patch caused regression on my ARMv7 32 bit setup.

> Please find filled in bugzilla entry:

> 

> https://sourceware.org/bugzilla/show_bug.cgi?id=25352


Are you sure you are testing it properly? As indicated by Andreas, it
seems a mismatch between ld.so and libc.so.  I just setup a debian 9 
VM with both a 4.9 and 5.4 kernel and a simple test:

--
#include <time.h>

int main ()
{
  clock_gettime (CLOCK_REALTIME, &(struct timespec) {});
  clock_gettime (CLOCK_MONOTONIC, &(struct timespec) {});
  clock_gettime (CLOCK_BOOTTIME, &(struct timespec) {});

  return 0;
}
--

does show the expected results.  On 4.9 kernel I am seeing:

15:36:06 syscall_0x193(0, 0xbed9a3d8, 0xc8, 0, 0xbed9a3d8, 0) = -1 ENOSYS (Function not implemented)
15:36:06 clock_gettime(CLOCK_BOOTTIME, {tv_sec=1303, tv_nsec=570795799}) = 0
15:36:06 exit_group(0)                  = ?
15:36:06 +++ exited with 0 +++

While on a 5.4 kernel:

syscall_0x193(0, 0xbedfb3e8, 0xc8, 0, 0xbedfb3e8, 0) = 0
syscall_0x193(0x1, 0xbedfb3e8, 0xc8, 0, 0xbedfb3e8, 0x1) = 0
syscall_0x193(0x7, 0xbedfb3e8, 0xc8, 0, 0xbedfb3e8, 0x7) = 0

(arm clock_gettime64 vDSO was added on 5.5).

Patch

diff --git a/csu/init-first.c b/csu/init-first.c
index e0f489ee6d..891719a839 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 b2b1b12f6f..81d44b0343 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 dd8fc5e6c6..a06e13c657 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 bbe321e843..8cbc3e6fea 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..3d79bae317
--- /dev/null
+++ b/sysdeps/generic/dl-vdso-setup.h
@@ -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
diff --git a/sysdeps/generic/dl-vdso.h b/sysdeps/generic/dl-vdso.h
new file mode 100644
index 0000000000..5651f49a1a
--- /dev/null
+++ b/sysdeps/generic/dl-vdso.h
@@ -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
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index fc25a81e1c..8cbd0e87cc 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 2e6a859d9f..f2a57480a5 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 234d9c00dc..8ed5bc1585 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..1069879f1a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/dl-vdso-setup.c
@@ -0,0 +1,81 @@ 
+/* 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 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..f4e76202fc
--- /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) 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) = 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 5577f2103c..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-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;
-}
diff --git a/sysdeps/unix/sysv/linux/dl-vdso.h b/sysdeps/unix/sysv/linux/dl-vdso.h
index 19ffd30c7e..d1e782b81f 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 600da6b468..6945be269c 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 d005d13322..0000000000
--- a/sysdeps/unix/sysv/linux/init-first.c
+++ /dev/null
@@ -1,90 +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_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 c6d505bab3..004faf0a97 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 29b6624b9a..11eb2b126d 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 92a4af83af..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-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>
diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h
index cb7da3b289..adc06d48b0 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 c5bd60d9c2..e967e40deb 100644
--- a/sysdeps/unix/sysv/linux/riscv/flush-icache.c
+++ b/sysdeps/unix/sysv/linux/riscv/flush-icache.c
@@ -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
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 76a211e39b..772313f97e 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 0598958c9c..a7e4cbeb96 100644
--- a/sysdeps/unix/sysv/linux/time.c
+++ b/sysdeps/unix/sysv/linux/time.c
@@ -25,6 +25,7 @@ 
 
 #ifdef SHARED
 # include <dl-vdso.h>
+# include <libc-vdso.h>
 
 static time_t
 time_syscall (time_t *t)
@@ -34,7 +35,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