From 75fb247e69ede25fb49929fed7535a091a4f6934 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 12 Aug 2007 19:03:54 +0000 Subject: * sysdeps/unix/sysv/linux/powerpc/dl-vdso.c: Move to... * sysdeps/unix/sysv/linux/dl-vdso.c: ...here. * sysdeps/unix/sysv/linux/powerpc/dl-vdso.h: Move to... * sysdeps/unix/sysv/linux/dl-vdso.h: ...here. * csu/libc-start.c: Pretty printing. Use VDSO_SETUP if defined. * sysdeps/unix/sysv/linux/powerpc/libc-start.c: Define VDSO_SETUP and let generic code call into _libc_vdso_platform_setup. * sysdeps/unix/sysv/linux/x86_64/libc-start.c: New file. * sysdeps/unix/sysv/linux/x86_64/bits/libc-vdso.h: New file. * sysdeps/unix/sysv/linux/x86_64/sysdep.h: Pretty printing. Define INLINE_VSYSCALL and INTERNAL_VSYSCALL. * sysdeps/unix/sysv/linux/x86_64/Versions: Export __vdso_clock_gettime for GLIBC_PRIVATE. * sysdeps/unix/sysv/linux/x86_64/Makefile [subdir=elf] (sysdep_rountines): Add dl-vdso. * sysdeps/unix/sysv/linux/powerpc/Makefile: Use sysdep_routines instead of routines. * sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h: Add attribute_hidden to __vdso_gettimeofday prototype. --- sysdeps/unix/sysv/linux/dl-vdso.c | 59 +++++++ sysdeps/unix/sysv/linux/dl-vdso.h | 27 +++ sysdeps/unix/sysv/linux/powerpc/Makefile | 2 +- sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h | 2 +- sysdeps/unix/sysv/linux/powerpc/dl-vdso.c | 59 ------- sysdeps/unix/sysv/linux/powerpc/dl-vdso.h | 27 --- sysdeps/unix/sysv/linux/powerpc/libc-start.c | 42 ++--- sysdeps/unix/sysv/linux/x86_64/Makefile | 4 + sysdeps/unix/sysv/linux/x86_64/Versions | 3 + sysdeps/unix/sysv/linux/x86_64/bits/libc-vdso.h | 35 ++++ sysdeps/unix/sysv/linux/x86_64/libc-start.c | 39 +++++ sysdeps/unix/sysv/linux/x86_64/sysdep.h | 206 ++++++++++++++--------- 12 files changed, 320 insertions(+), 185 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/dl-vdso.c create mode 100644 sysdeps/unix/sysv/linux/dl-vdso.h delete mode 100644 sysdeps/unix/sysv/linux/powerpc/dl-vdso.c delete mode 100644 sysdeps/unix/sysv/linux/powerpc/dl-vdso.h create mode 100644 sysdeps/unix/sysv/linux/x86_64/bits/libc-vdso.h create mode 100644 sysdeps/unix/sysv/linux/x86_64/libc-start.c (limited to 'sysdeps') diff --git a/sysdeps/unix/sysv/linux/dl-vdso.c b/sysdeps/unix/sysv/linux/dl-vdso.c new file mode 100644 index 0000000000..e1be097734 --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-vdso.c @@ -0,0 +1,59 @@ +/* ELF symbol resolve functions for VDSO objects. + Copyright (C) 2005 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "config.h" +#include +#include + + +void * +internal_function +_dl_vdso_vsym (const char *name, const char *version) +{ + 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)); + + /* Compute hash value to the version string. */ + struct r_found_version vers; + vers.name = version; + vers.hidden = 1; + vers.hash = _dl_elf_hash (version); + /* We don't have a specific file where the symbol can be found. */ + vers.filename = NULL; + + /* 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 new file mode 100644 index 0000000000..a7dcb2e5ff --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-vdso.h @@ -0,0 +1,27 @@ +/* ELF symbol resolve functions for VDSO objects. + Copyright (C) 2005 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DL_VDSO_H +#define _DL_VDSO_H 1 + +/* Functions for resolving symbols in the VDSO link map. */ +extern void *_dl_vdso_vsym (const char *name, const char *version) + internal_function attribute_hidden; + +#endif /* dl-vdso.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile index ecd8057951..d1281cf469 100644 --- a/sysdeps/unix/sysv/linux/powerpc/Makefile +++ b/sysdeps/unix/sysv/linux/powerpc/Makefile @@ -8,5 +8,5 @@ gen-as-const-headers += ucontext_i.sym endif ifeq ($(subdir),elf) -routines += dl-vdso +sysdep_routines += dl-vdso endif diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h index f20a5a175c..746d9ced4a 100644 --- a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h +++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h @@ -23,7 +23,7 @@ #ifdef SHARED -extern void *__vdso_gettimeofday; +extern void *__vdso_gettimeofday attribute_hidden; extern void *__vdso_clock_gettime; diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-vdso.c b/sysdeps/unix/sysv/linux/powerpc/dl-vdso.c deleted file mode 100644 index e1be097734..0000000000 --- a/sysdeps/unix/sysv/linux/powerpc/dl-vdso.c +++ /dev/null @@ -1,59 +0,0 @@ -/* ELF symbol resolve functions for VDSO objects. - Copyright (C) 2005 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include "config.h" -#include -#include - - -void * -internal_function -_dl_vdso_vsym (const char *name, const char *version) -{ - 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)); - - /* Compute hash value to the version string. */ - struct r_found_version vers; - vers.name = version; - vers.hidden = 1; - vers.hash = _dl_elf_hash (version); - /* We don't have a specific file where the symbol can be found. */ - vers.filename = NULL; - - /* 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/powerpc/dl-vdso.h b/sysdeps/unix/sysv/linux/powerpc/dl-vdso.h deleted file mode 100644 index a7dcb2e5ff..0000000000 --- a/sysdeps/unix/sysv/linux/powerpc/dl-vdso.h +++ /dev/null @@ -1,27 +0,0 @@ -/* ELF symbol resolve functions for VDSO objects. - Copyright (C) 2005 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _DL_VDSO_H -#define _DL_VDSO_H 1 - -/* Functions for resolving symbols in the VDSO link map. */ -extern void *_dl_vdso_vsym (const char *name, const char *version) - internal_function attribute_hidden; - -#endif /* dl-vdso.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-start.c b/sysdeps/unix/sysv/linux/powerpc/libc-start.c index a71cfa5b06..d78876d40d 100644 --- a/sysdeps/unix/sysv/linux/powerpc/libc-start.c +++ b/sysdeps/unix/sysv/linux/powerpc/libc-start.c @@ -24,23 +24,6 @@ #include #include -int __cache_line_size attribute_hidden; -/* The main work is done in the generic function. */ -#define LIBC_START_MAIN generic_start_main -#define LIBC_START_DISABLE_INLINE -#define LIBC_START_MAIN_AUXVEC_ARG -#define MAIN_AUXVEC_ARG -#define INIT_MAIN_ARGS -#include - -struct startup_info - { - void *__unbounded sda_base; - int (*main) (int, char **, char **, void *); - int (*init) (int, char **, char **, void *); - void (*fini) (void); - }; - #ifdef SHARED # include @@ -69,8 +52,28 @@ static inline void _libc_vdso_platform_setup (void) __vdso_get_tbfreq = _dl_vdso_vsym ("__kernel_vdso_get_tbfreq", "LINUX_2.6.15"); } + +# define VDSO_SETUP _libc_vdso_platform_setup #endif + +int __cache_line_size attribute_hidden; +/* The main work is done in the generic function. */ +#define LIBC_START_MAIN generic_start_main +#define LIBC_START_DISABLE_INLINE +#define LIBC_START_MAIN_AUXVEC_ARG +#define MAIN_AUXVEC_ARG +#define INIT_MAIN_ARGS +#include + +struct startup_info + { + void *__unbounded sda_base; + int (*main) (int, char **, char **, void *); + int (*init) (int, char **, char **, void *); + void (*fini) (void); + }; + int /* GKM FIXME: GCC: this should get __BP_ prefix by virtue of the BPs in the arglist of startup_info.main and startup_info.init. */ @@ -117,10 +120,7 @@ int __cache_line_size = av->a_un.a_val; break; } -#ifdef SHARED - /* Resolve and initialize function pointers for VDSO functions. */ - _libc_vdso_platform_setup (); -#endif + return generic_start_main (stinfo->main, argc, ubp_av, auxvec, stinfo->init, stinfo->fini, rtld_fini, stack_on_entry); diff --git a/sysdeps/unix/sysv/linux/x86_64/Makefile b/sysdeps/unix/sysv/linux/x86_64/Makefile index bdad5063df..6e2741a967 100644 --- a/sysdeps/unix/sysv/linux/x86_64/Makefile +++ b/sysdeps/unix/sysv/linux/x86_64/Makefile @@ -13,3 +13,7 @@ endif ifeq ($(subdir),csu) gen-as-const-headers += ucontext_i.sym endif + +ifeq ($(subdir),elf) +sysdep_routines += dl-vdso +endif diff --git a/sysdeps/unix/sysv/linux/x86_64/Versions b/sysdeps/unix/sysv/linux/x86_64/Versions index fd1b3cc296..34c100bfd2 100644 --- a/sysdeps/unix/sysv/linux/x86_64/Versions +++ b/sysdeps/unix/sysv/linux/x86_64/Versions @@ -6,4 +6,7 @@ libc { modify_ldt; } + GLIBC_PRIVATE { + __vdso_clock_gettime; + } } diff --git a/sysdeps/unix/sysv/linux/x86_64/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/x86_64/bits/libc-vdso.h new file mode 100644 index 0000000000..6e08d3b203 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86_64/bits/libc-vdso.h @@ -0,0 +1,35 @@ +/* Resolve function pointers to VDSO functions. + Copyright (C) 2005, 2007 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIBC_VDSO_H +#define _LIBC_VDSO_H + +#include +#include + +#ifdef SHARED + +extern int (*__vdso_gettimeofday) (struct timeval *, void *) + attribute_hidden; + +extern int (*__vdso_clock_gettime) (clockid_t, struct timespec *); + +#endif + +#endif /* _LIBC_VDSO_H */ diff --git a/sysdeps/unix/sysv/linux/x86_64/libc-start.c b/sysdeps/unix/sysv/linux/x86_64/libc-start.c new file mode 100644 index 0000000000..3c95729371 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86_64/libc-start.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2007 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef SHARED +# include +# include + +int (*__vdso_gettimeofday) (struct timeval *, void *) attribute_hidden; + +int (*__vdso_clock_gettime) (clockid_t, struct timespec *); + + +static inline void +_libc_vdso_platform_setup (void) +{ + __vdso_gettimeofday = _dl_vdso_vsym ("gettimeofday", "LINUX_2.6"); + + __vdso_clock_gettime = _dl_vdso_vsym ("clock_gettime", "LINUX_2.6"); +} + +# define VDSO_SETUP _libc_vdso_platform_setup +#endif + +#include diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h index 1d9a68a046..61701a2869 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h @@ -68,14 +68,14 @@ /* We don't want the label for the error handle to be global when we define it here. */ -#ifdef PIC -# define SYSCALL_ERROR_LABEL 0f -#else -# define SYSCALL_ERROR_LABEL syscall_error -#endif +# ifdef PIC +# define SYSCALL_ERROR_LABEL 0f +# else +# define SYSCALL_ERROR_LABEL syscall_error +# endif -#undef PSEUDO -#define PSEUDO(name, syscall_name, args) \ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ .text; \ ENTRY (name) \ DO_CALL (syscall_name, args); \ @@ -83,40 +83,40 @@ jae SYSCALL_ERROR_LABEL; \ L(pseudo_end): -#undef PSEUDO_END -#define PSEUDO_END(name) \ +# undef PSEUDO_END +# define PSEUDO_END(name) \ SYSCALL_ERROR_HANDLER \ END (name) -#undef PSEUDO_NOERRNO -#define PSEUDO_NOERRNO(name, syscall_name, args) \ +# undef PSEUDO_NOERRNO +# define PSEUDO_NOERRNO(name, syscall_name, args) \ .text; \ ENTRY (name) \ DO_CALL (syscall_name, args) -#undef PSEUDO_END_NOERRNO -#define PSEUDO_END_NOERRNO(name) \ +# undef PSEUDO_END_NOERRNO +# define PSEUDO_END_NOERRNO(name) \ END (name) -#define ret_NOERRNO ret +# define ret_NOERRNO ret -#undef PSEUDO_ERRVAL -#define PSEUDO_ERRVAL(name, syscall_name, args) \ +# undef PSEUDO_ERRVAL +# define PSEUDO_ERRVAL(name, syscall_name, args) \ .text; \ ENTRY (name) \ DO_CALL (syscall_name, args); \ negq %rax -#undef PSEUDO_END_ERRVAL -#define PSEUDO_END_ERRVAL(name) \ +# undef PSEUDO_END_ERRVAL +# define PSEUDO_END_ERRVAL(name) \ END (name) -#define ret_ERRVAL ret +# define ret_ERRVAL ret -#ifndef PIC -#define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ -#elif RTLD_PRIVATE_ERRNO -# define SYSCALL_ERROR_HANDLER \ +# ifndef PIC +# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +# elif RTLD_PRIVATE_ERRNO +# define SYSCALL_ERROR_HANDLER \ 0: \ leaq rtld_errno(%rip), %rcx; \ xorl %edx, %edx; \ @@ -124,13 +124,13 @@ movl %edx, (%rcx); \ orq $-1, %rax; \ jmp L(pseudo_end); -#elif USE___THREAD -# ifndef NOT_IN_libc -# define SYSCALL_ERROR_ERRNO __libc_errno -# else -# define SYSCALL_ERROR_ERRNO errno -# endif -# define SYSCALL_ERROR_HANDLER \ +# elif USE___THREAD +# ifndef NOT_IN_libc +# define SYSCALL_ERROR_ERRNO __libc_errno +# else +# define SYSCALL_ERROR_ERRNO errno +# endif +# define SYSCALL_ERROR_HANDLER \ 0: \ movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\ xorl %edx, %edx; \ @@ -138,10 +138,10 @@ movl %edx, %fs:(%rcx); \ orq $-1, %rax; \ jmp L(pseudo_end); -#elif defined _LIBC_REENTRANT +# elif defined _LIBC_REENTRANT /* Store (- %rax) into errno through the GOT. Note that errno occupies only 4 bytes. */ -# define SYSCALL_ERROR_HANDLER \ +# define SYSCALL_ERROR_HANDLER \ 0: \ xorl %edx, %edx; \ subq %rax, %rdx; \ @@ -158,15 +158,15 @@ /* A quick note: it is assumed that the call to `__errno_location' does not modify the stack! */ -#else /* Not _LIBC_REENTRANT. */ -# define SYSCALL_ERROR_HANDLER \ +# else /* Not _LIBC_REENTRANT. */ +# define SYSCALL_ERROR_HANDLER \ 0:movq errno@GOTPCREL(%RIP), %rcx; \ xorl %edx, %edx; \ subq %rax, %rdx; \ movl %edx, (%rcx); \ orq $-1, %rax; \ jmp L(pseudo_end); -#endif /* PIC */ +# endif /* PIC */ /* The Linux/x86-64 kernel expects the system call parameters in registers according to the following table: @@ -204,25 +204,25 @@ Syscalls of more than 6 arguments are not supported. */ -#undef DO_CALL -#define DO_CALL(syscall_name, args) \ +# undef DO_CALL +# define DO_CALL(syscall_name, args) \ DOARGS_##args \ movl $SYS_ify (syscall_name), %eax; \ syscall; -#define DOARGS_0 /* nothing */ -#define DOARGS_1 /* nothing */ -#define DOARGS_2 /* nothing */ -#define DOARGS_3 /* nothing */ -#define DOARGS_4 movq %rcx, %r10; -#define DOARGS_5 DOARGS_4 -#define DOARGS_6 DOARGS_5 +# define DOARGS_0 /* nothing */ +# define DOARGS_1 /* nothing */ +# define DOARGS_2 /* nothing */ +# define DOARGS_3 /* nothing */ +# define DOARGS_4 movq %rcx, %r10; +# define DOARGS_5 DOARGS_4 +# define DOARGS_6 DOARGS_5 #else /* !__ASSEMBLER__ */ /* Define a macro which expands inline into the wrapper code for a system call. */ -#undef INLINE_SYSCALL -#define INLINE_SYSCALL(name, nr, args...) \ +# undef INLINE_SYSCALL +# define INLINE_SYSCALL(name, nr, args...) \ ({ \ unsigned long resultvar = INTERNAL_SYSCALL (name, , nr, args); \ if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0)) \ @@ -232,10 +232,10 @@ } \ (long) resultvar; }) -#undef INTERNAL_SYSCALL_DECL -#define INTERNAL_SYSCALL_DECL(err) do { } while (0) +# undef INTERNAL_SYSCALL_DECL +# define INTERNAL_SYSCALL_DECL(err) do { } while (0) -#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ +# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ({ \ unsigned long resultvar; \ LOAD_ARGS_##nr (args) \ @@ -245,68 +245,122 @@ : "=a" (resultvar) \ : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx"); \ (long) resultvar; }) -#undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ +# undef INTERNAL_SYSCALL +# define INTERNAL_SYSCALL(name, err, nr, args...) \ INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) -#undef INTERNAL_SYSCALL_ERROR_P -#define INTERNAL_SYSCALL_ERROR_P(val, err) \ +# undef INTERNAL_SYSCALL_ERROR_P +# define INTERNAL_SYSCALL_ERROR_P(val, err) \ ((unsigned long) (val) >= -4095L) -#undef INTERNAL_SYSCALL_ERRNO -#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) +# undef INTERNAL_SYSCALL_ERRNO +# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +# ifdef SHARED +# define INLINE_VSYSCALL(name, nr, args...) \ + ({ \ + __label__ out; \ + __label__ iserr; \ + INTERNAL_SYSCALL_DECL (sc_err); \ + long int sc_ret; \ + \ + if (__vdso_##name != NULL) \ + { \ + sc_ret = __vdso_##name (args); \ + if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + goto out; \ + if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS) \ + goto iserr; \ + } \ + \ + sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args); \ + if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + { \ + iserr: \ + __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \ + sc_ret = -1L; \ + } \ + out: \ + sc_ret; \ + }) +# define INTERNAL_VSYSCALL(name, err, nr, args...) \ + ({ \ + __label__ out; \ + long int v_ret; \ + \ + if (__vdso_##name != NULL) \ + { \ + v_ret = __vdso_##name (args); \ + if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err) \ + || INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS) \ + goto out; \ + } \ + v_ret = INTERNAL_SYSCALL (name, err, nr, ##args); \ + out: \ + v_ret; \ + }) + +/* List of system calls which are supported as vsyscalls. */ +# define HAVE_CLOCK_GETTIME_VSYSCALL 1 + +# else +# define INLINE_VSYSCALL(name, nr, args...) \ + INLINE_SYSCALL (name, nr, ##args) +# define INTERNAL_VSYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL (name, err, nr, ##args) +# endif -#define LOAD_ARGS_0() -#define LOAD_REGS_0 -#define ASM_ARGS_0 +# define LOAD_ARGS_0() +# define LOAD_REGS_0 +# define ASM_ARGS_0 -#define LOAD_ARGS_1(a1) \ +# define LOAD_ARGS_1(a1) \ long int __arg1 = (long) (a1); \ LOAD_ARGS_0 () -#define LOAD_REGS_1 \ +# define LOAD_REGS_1 \ register long int _a1 asm ("rdi") = __arg1; \ LOAD_REGS_0 -#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1) +# define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1) -#define LOAD_ARGS_2(a1, a2) \ +# define LOAD_ARGS_2(a1, a2) \ long int __arg2 = (long) (a2); \ LOAD_ARGS_1 (a1) -#define LOAD_REGS_2 \ +# define LOAD_REGS_2 \ register long int _a2 asm ("rsi") = __arg2; \ LOAD_REGS_1 -#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2) +# define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2) -#define LOAD_ARGS_3(a1, a2, a3) \ +# define LOAD_ARGS_3(a1, a2, a3) \ long int __arg3 = (long) (a3); \ LOAD_ARGS_2 (a1, a2) -#define LOAD_REGS_3 \ +# define LOAD_REGS_3 \ register long int _a3 asm ("rdx") = __arg3; \ LOAD_REGS_2 -#define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3) +# define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3) -#define LOAD_ARGS_4(a1, a2, a3, a4) \ +# define LOAD_ARGS_4(a1, a2, a3, a4) \ long int __arg4 = (long) (a4); \ LOAD_ARGS_3 (a1, a2, a3) -#define LOAD_REGS_4 \ +# define LOAD_REGS_4 \ register long int _a4 asm ("r10") = __arg4; \ LOAD_REGS_3 -#define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4) +# define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4) -#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ +# define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ long int __arg5 = (long) (a5); \ LOAD_ARGS_4 (a1, a2, a3, a4) -#define LOAD_REGS_5 \ +# define LOAD_REGS_5 \ register long int _a5 asm ("r8") = __arg5; \ LOAD_REGS_4 -#define ASM_ARGS_5 ASM_ARGS_4, "r" (_a5) +# define ASM_ARGS_5 ASM_ARGS_4, "r" (_a5) -#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ +# define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ long int __arg6 = (long) (a6); \ LOAD_ARGS_5 (a1, a2, a3, a4, a5) -#define LOAD_REGS_6 \ +# define LOAD_REGS_6 \ register long int _a6 asm ("r9") = __arg6; \ LOAD_REGS_5 -#define ASM_ARGS_6 ASM_ARGS_5, "r" (_a6) +# define ASM_ARGS_6 ASM_ARGS_5, "r" (_a6) #endif /* __ASSEMBLER__ */ -- cgit 1.4.1