18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * vdso_test_gettimeofday.c: Sample code to test parse_vdso.c and 48c2ecf20Sopenharmony_ci * vDSO gettimeofday() 58c2ecf20Sopenharmony_ci * Copyright (c) 2014 Andy Lutomirski 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Compile with: 88c2ecf20Sopenharmony_ci * gcc -std=gnu99 vdso_test_gettimeofday.c parse_vdso_gettimeofday.c 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Tested on x86, 32-bit and 64-bit. It may work on other architectures, too. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <stdint.h> 148c2ecf20Sopenharmony_ci#include <elf.h> 158c2ecf20Sopenharmony_ci#include <stdio.h> 168c2ecf20Sopenharmony_ci#include <sys/auxv.h> 178c2ecf20Sopenharmony_ci#include <sys/time.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "../kselftest.h" 208c2ecf20Sopenharmony_ci#include "parse_vdso.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* 238c2ecf20Sopenharmony_ci * ARM64's vDSO exports its gettimeofday() implementation with a different 248c2ecf20Sopenharmony_ci * name and version from other architectures, so we need to handle it as 258c2ecf20Sopenharmony_ci * a special case. 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci#if defined(__aarch64__) 288c2ecf20Sopenharmony_ciconst char *version = "LINUX_2.6.39"; 298c2ecf20Sopenharmony_ciconst char *name = "__kernel_gettimeofday"; 308c2ecf20Sopenharmony_ci#else 318c2ecf20Sopenharmony_ciconst char *version = "LINUX_2.6"; 328c2ecf20Sopenharmony_ciconst char *name = "__vdso_gettimeofday"; 338c2ecf20Sopenharmony_ci#endif 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ciint main(int argc, char **argv) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR); 388c2ecf20Sopenharmony_ci if (!sysinfo_ehdr) { 398c2ecf20Sopenharmony_ci printf("AT_SYSINFO_EHDR is not present!\n"); 408c2ecf20Sopenharmony_ci return KSFT_SKIP; 418c2ecf20Sopenharmony_ci } 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR)); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* Find gettimeofday. */ 468c2ecf20Sopenharmony_ci typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz); 478c2ecf20Sopenharmony_ci gtod_t gtod = (gtod_t)vdso_sym(version, name); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci if (!gtod) { 508c2ecf20Sopenharmony_ci printf("Could not find %s\n", name); 518c2ecf20Sopenharmony_ci return KSFT_SKIP; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci struct timeval tv; 558c2ecf20Sopenharmony_ci long ret = gtod(&tv, 0); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci if (ret == 0) { 588c2ecf20Sopenharmony_ci printf("The time is %lld.%06lld\n", 598c2ecf20Sopenharmony_ci (long long)tv.tv_sec, (long long)tv.tv_usec); 608c2ecf20Sopenharmony_ci } else { 618c2ecf20Sopenharmony_ci printf("%s failed\n", name); 628c2ecf20Sopenharmony_ci return KSFT_FAIL; 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return 0; 668c2ecf20Sopenharmony_ci} 67