github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/vdso/vdso.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // This is the VDSO for sandboxed binaries. This file just contains the entry 16 // points to the VDSO. All of the real work is done in vdso_time.cc 17 18 #define _DEFAULT_SOURCE // ensure glibc provides struct timezone. 19 #include <sys/time.h> 20 #include <time.h> 21 22 #include "vdso/syscalls.h" 23 #include "vdso/vdso_time.h" 24 25 namespace vdso { 26 namespace { 27 28 int __common_clock_gettime(clockid_t clock, struct timespec* ts) { 29 int ret; 30 31 switch (clock) { 32 case CLOCK_REALTIME: 33 ret = ClockRealtime(ts); 34 break; 35 36 case CLOCK_BOOTTIME: 37 // Fallthrough, CLOCK_BOOTTIME is an alias for CLOCK_MONOTONIC 38 case CLOCK_MONOTONIC: 39 ret = ClockMonotonic(ts); 40 break; 41 42 default: 43 ret = sys_clock_gettime(clock, ts); 44 break; 45 } 46 47 return ret; 48 } 49 50 int __common_gettimeofday(struct timeval* tv, struct timezone* tz) { 51 if (tv) { 52 struct timespec ts; 53 int ret = ClockRealtime(&ts); 54 if (ret) { 55 return ret; 56 } 57 tv->tv_sec = ts.tv_sec; 58 tv->tv_usec = ts.tv_nsec / 1000; 59 } 60 61 // Nobody should be calling gettimeofday() with a non-NULL 62 // timezone pointer. If they do then they will get zeros. 63 if (tz) { 64 tz->tz_minuteswest = 0; 65 tz->tz_dsttime = 0; 66 } 67 68 return 0; 69 } 70 } // namespace 71 72 // __kernel_rt_sigreturn() implements rt_sigreturn() 73 extern "C" void __kernel_rt_sigreturn(unsigned long unused) { 74 // No optimizations yet, just make the real system call. 75 sys_rt_sigreturn(); 76 } 77 78 #if __x86_64__ 79 80 // __vdso_clock_gettime() implements clock_gettime() 81 extern "C" int __vdso_clock_gettime(clockid_t clock, struct timespec* ts) { 82 return __common_clock_gettime(clock, ts); 83 } 84 extern "C" int clock_gettime(clockid_t clock, struct timespec* ts) 85 __attribute__((weak, alias("__vdso_clock_gettime"))); 86 87 // __vdso_gettimeofday() implements gettimeofday() 88 extern "C" int __vdso_gettimeofday(struct timeval* tv, struct timezone* tz) { 89 return __common_gettimeofday(tv, tz); 90 } 91 extern "C" int gettimeofday(struct timeval* tv, struct timezone* tz) 92 __attribute__((weak, alias("__vdso_gettimeofday"))); 93 94 // __vdso_time() implements time() 95 extern "C" time_t __vdso_time(time_t* t) { 96 struct timespec ts; 97 ClockRealtime(&ts); 98 if (t) { 99 *t = ts.tv_sec; 100 } 101 return ts.tv_sec; 102 } 103 extern "C" time_t time(time_t* t) __attribute__((weak, alias("__vdso_time"))); 104 105 // __vdso_getcpu() implements getcpu() 106 extern "C" long __vdso_getcpu(unsigned* cpu, unsigned* node, 107 struct getcpu_cache* cache) { 108 // No optimizations yet, just make the real system call. 109 return sys_getcpu(cpu, node, cache); 110 } 111 extern "C" long getcpu(unsigned* cpu, unsigned* node, 112 struct getcpu_cache* cache) 113 __attribute__((weak, alias("__vdso_getcpu"))); 114 115 #elif __aarch64__ 116 117 // __kernel_clock_gettime() implements clock_gettime() 118 extern "C" int __kernel_clock_gettime(clockid_t clock, struct timespec* ts) { 119 return __common_clock_gettime(clock, ts); 120 } 121 122 // __kernel_gettimeofday() implements gettimeofday() 123 extern "C" int __kernel_gettimeofday(struct timeval* tv, struct timezone* tz) { 124 return __common_gettimeofday(tv, tz); 125 } 126 127 // __kernel_clock_getres() implements clock_getres() 128 extern "C" int __kernel_clock_getres(clockid_t clock, struct timespec* res) { 129 int ret = 0; 130 131 switch (clock) { 132 case CLOCK_REALTIME: 133 case CLOCK_MONOTONIC: 134 case CLOCK_BOOTTIME: { 135 if (res == nullptr) { 136 return 0; 137 } 138 139 res->tv_sec = 0; 140 res->tv_nsec = 1; 141 break; 142 } 143 144 default: 145 ret = sys_clock_getres(clock, res); 146 break; 147 } 148 149 return ret; 150 } 151 152 #else 153 #error "unsupported architecture" 154 #endif 155 } // namespace vdso