13002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes/* 23002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * Copyright (C) 2014 The Android Open Source Project 33002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * 43002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 53002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * you may not use this file except in compliance with the License. 63002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * You may obtain a copy of the License at 73002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * 83002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 93002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * 103002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * Unless required by applicable law or agreed to in writing, software 113002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 123002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * See the License for the specific language governing permissions and 143002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes * limitations under the License. 153002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes */ 163002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 173002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#include <link.h> 183002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#include <sys/auxv.h> 193002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#include <unistd.h> 203002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 213002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes// x86 has a vdso, but there's nothing useful to us in it. 223002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#if defined(__aarch64__) || defined(__x86_64__) 233002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 243002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#if defined(__aarch64__) 253002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime" 263002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#define VDSO_GETTIMEOFDAY_SYMBOL "__kernel_gettimeofday" 273002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#elif defined(__x86_64__) 283002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime" 293002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#define VDSO_GETTIMEOFDAY_SYMBOL "__vdso_gettimeofday" 303002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#endif 313002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 323002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#include <time.h> 333002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 343002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughesextern "C" int __clock_gettime(int, timespec*); 353002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughesextern "C" int __gettimeofday(timeval*, struct timezone*); 363002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 373002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughesstruct vdso_entry { 383002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes const char* name; 393002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes void* fn; 403002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes}; 413002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 423002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughesenum { 433002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes VDSO_CLOCK_GETTIME = 0, 443002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes VDSO_GETTIMEOFDAY, 453002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes VDSO_END 463002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes}; 473002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 483002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughesstatic vdso_entry vdso_entries[] = { 493002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes [VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, reinterpret_cast<void*>(__clock_gettime) }, 503002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes [VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) }, 513002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes}; 523002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 533002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughesint clock_gettime(int clock_id, timespec* tp) { 543002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes static int (*vdso_clock_gettime)(int, timespec*) = 553002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes (int (*)(int, timespec*)) vdso_entries[VDSO_CLOCK_GETTIME].fn; 563002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes return vdso_clock_gettime(clock_id, tp); 573002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes} 583002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 593002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughesint gettimeofday(timeval* tv, struct timezone* tz) { 603002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes static int (*vdso_gettimeofday)(timeval*, struct timezone*) = 613002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes (int (*)(timeval*, struct timezone*)) vdso_entries[VDSO_GETTIMEOFDAY].fn; 623002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes return vdso_gettimeofday(tv, tz); 633002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes} 643002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 653002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughesvoid __libc_init_vdso() { 663002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes // Do we have a vdso? 673002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR); 683002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr); 693002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes if (vdso_ehdr == NULL) { 703002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes return; 713002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 723002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 733002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes // How many symbols does it have? 743002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes size_t symbol_count = 0; 753002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes ElfW(Shdr)* vdso_shdr = reinterpret_cast<ElfW(Shdr)*>(vdso_ehdr_addr + vdso_ehdr->e_shoff); 763002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes for (size_t i = 0; i < vdso_ehdr->e_shnum; ++i) { 773002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes if (vdso_shdr[i].sh_type == SHT_DYNSYM) { 783002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes symbol_count = vdso_shdr[i].sh_size / sizeof(ElfW(Sym)); 793002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 803002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 813002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes if (symbol_count == 0) { 823002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes return; 833002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 843002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 853002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes // Where's the dynamic table? 863002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes ElfW(Addr) vdso_addr = 0; 873002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes ElfW(Dyn)* vdso_dyn = NULL; 883002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes ElfW(Phdr)* vdso_phdr = reinterpret_cast<ElfW(Phdr)*>(vdso_ehdr_addr + vdso_ehdr->e_phoff); 893002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) { 903002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes if (vdso_phdr[i].p_type == PT_DYNAMIC) { 913002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes vdso_dyn = reinterpret_cast<ElfW(Dyn)*>(vdso_ehdr_addr + vdso_phdr[i].p_offset); 923002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } else if (vdso_phdr[i].p_type == PT_LOAD) { 933002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes vdso_addr = vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr; 943002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 953002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 963002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes if (vdso_addr == 0 || vdso_dyn == NULL) { 973002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes return; 983002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 993002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 1003002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes // Where are the string and symbol tables? 1013002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes const char* strtab = NULL; 1023002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes ElfW(Sym)* symtab = NULL; 1033002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) { 1043002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes if (d->d_tag == DT_STRTAB) { 1053002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes strtab = reinterpret_cast<const char*>(vdso_addr + d->d_un.d_ptr); 1063002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } else if (d->d_tag == DT_SYMTAB) { 1073002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes symtab = reinterpret_cast<ElfW(Sym)*>(vdso_addr + d->d_un.d_ptr); 1083002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 1093002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 1103002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes if (strtab == NULL || symtab == NULL) { 1113002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes return; 1123002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 1133002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 1143002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes // Are there any symbols we want? 1153002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes for (size_t i = 0; i < symbol_count; ++i) { 1163002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes for (size_t j = 0; j < VDSO_END; ++j) { 1173002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes if (strcmp(vdso_entries[j].name, strtab + symtab[i].st_name) == 0) { 1183002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes vdso_entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value); 1193002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 1203002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 1213002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 1223002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes} 1233002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 1243002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#else 1253002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 1263002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughesvoid __libc_init_vdso() { 1273002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes} 1283002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes 1293002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#endif 130