2019-05-28 19:57:09 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2014-06-13 04:53:10 +04:00
/*
2020-05-21 23:37:05 +03:00
* vdso_test_gettimeofday . c : Sample code to test parse_vdso . c and
* vDSO gettimeofday ( )
2014-06-13 04:53:10 +04:00
* Copyright ( c ) 2014 Andy Lutomirski
*
* Compile with :
2020-05-21 23:37:05 +03:00
* gcc - std = gnu99 vdso_test_gettimeofday . c parse_vdso_gettimeofday . c
2014-06-13 04:53:10 +04:00
*
* Tested on x86 , 32 - bit and 64 - bit . It may work on other architectures , too .
*/
# include <stdint.h>
# include <elf.h>
# include <stdio.h>
# include <sys/auxv.h>
# include <sys/time.h>
2018-06-22 20:43:23 +03:00
# include "../kselftest.h"
2014-06-13 04:53:10 +04:00
extern void * vdso_sym ( const char * version , const char * name ) ;
extern void vdso_init_from_sysinfo_ehdr ( uintptr_t base ) ;
extern void vdso_init_from_auxv ( void * auxv ) ;
2017-11-02 00:34:26 +03:00
/*
* ARM64 ' s vDSO exports its gettimeofday ( ) implementation with a different
* name and version from other architectures , so we need to handle it as
* a special case .
*/
# if defined(__aarch64__)
const char * version = " LINUX_2.6.39 " ;
const char * name = " __kernel_gettimeofday " ;
# else
const char * version = " LINUX_2.6 " ;
const char * name = " __vdso_gettimeofday " ;
# endif
2014-06-13 04:53:10 +04:00
int main ( int argc , char * * argv )
{
unsigned long sysinfo_ehdr = getauxval ( AT_SYSINFO_EHDR ) ;
if ( ! sysinfo_ehdr ) {
printf ( " AT_SYSINFO_EHDR is not present! \n " ) ;
2018-06-22 20:43:23 +03:00
return KSFT_SKIP ;
2014-06-13 04:53:10 +04:00
}
vdso_init_from_sysinfo_ehdr ( getauxval ( AT_SYSINFO_EHDR ) ) ;
/* Find gettimeofday. */
typedef long ( * gtod_t ) ( struct timeval * tv , struct timezone * tz ) ;
2017-11-02 00:34:26 +03:00
gtod_t gtod = ( gtod_t ) vdso_sym ( version , name ) ;
2014-06-13 04:53:10 +04:00
if ( ! gtod ) {
2017-11-02 00:34:26 +03:00
printf ( " Could not find %s \n " , name ) ;
2018-06-22 20:43:23 +03:00
return KSFT_SKIP ;
2014-06-13 04:53:10 +04:00
}
struct timeval tv ;
long ret = gtod ( & tv , 0 ) ;
if ( ret = = 0 ) {
printf ( " The time is %lld.%06lld \n " ,
( long long ) tv . tv_sec , ( long long ) tv . tv_usec ) ;
} else {
2017-11-02 00:34:26 +03:00
printf ( " %s failed \n " , name ) ;
2018-06-22 20:43:23 +03:00
return KSFT_FAIL ;
2014-06-13 04:53:10 +04:00
}
return 0 ;
}