Skip to content

Commit ca747e4

Browse files
committed
[sanitizer] Restrict clock_gettime workaround to glibc
The hackery is due to glibc clock_gettime crashing from preinit_array (D40679). 32-bit musl architectures do not define `__NR_clock_gettime` so the code causes a compile error. Tested on Alpine Linux x86-64 (musl) and FreeBSD x86-64. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D96925
1 parent d163e75 commit ca747e4

File tree

4 files changed

+11
-12
lines changed

4 files changed

+11
-12
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,6 +2178,7 @@ INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
21782178
}
21792179
return res;
21802180
}
2181+
#if SANITIZER_GLIBC
21812182
namespace __sanitizer {
21822183
extern "C" {
21832184
int real_clock_gettime(u32 clk_id, void *tp) {
@@ -2187,6 +2188,7 @@ int real_clock_gettime(u32 clk_id, void *tp) {
21872188
}
21882189
} // extern "C"
21892190
} // namespace __sanitizer
2191+
#endif
21902192
INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
21912193
void *ctx;
21922194
COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);

compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,11 +500,13 @@ u64 NanoTime() {
500500
internal_syscall(SYSCALL(gettimeofday), &tv, 0);
501501
return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
502502
}
503+
#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD
503504

505+
#if SANITIZER_GLIBC
504506
uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
505507
return internal_syscall(SYSCALL(clock_gettime), clk_id, tp);
506508
}
507-
#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD
509+
#endif // SANITIZER_GLIBC
508510

509511
// Like getenv, but reads env directly from /proc (on Linux) or parses the
510512
// 'environ' array (on some others) and does not use libc. This function

compiler-rt/lib/sanitizer_common/sanitizer_linux.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
4949
uptr internal_sigaltstack(const void* ss, void* oss);
5050
uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
5151
__sanitizer_sigset_t *oldset);
52+
#if SANITIZER_GLIBC
5253
uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp);
54+
#endif
5355

5456
// Linux-only syscalls.
5557
#if SANITIZER_LINUX

compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -803,20 +803,13 @@ void LogMessageOnPrintf(const char *str) {
803803

804804
#endif // SANITIZER_LINUX
805805

806-
#if SANITIZER_LINUX && !SANITIZER_GO
806+
#if SANITIZER_GLIBC && !SANITIZER_GO
807807
// glibc crashes when using clock_gettime from a preinit_array function as the
808808
// vDSO function pointers haven't been initialized yet. __progname is
809809
// initialized after the vDSO function pointers, so if it exists, is not null
810810
// and is not empty, we can use clock_gettime.
811811
extern "C" SANITIZER_WEAK_ATTRIBUTE char *__progname;
812-
inline bool CanUseVDSO() {
813-
// Bionic is safe, it checks for the vDSO function pointers to be initialized.
814-
if (SANITIZER_ANDROID)
815-
return true;
816-
if (&__progname && __progname && *__progname)
817-
return true;
818-
return false;
819-
}
812+
inline bool CanUseVDSO() { return &__progname && __progname && *__progname; }
820813

821814
// MonotonicNanoTime is a timing function that can leverage the vDSO by calling
822815
// clock_gettime. real_clock_gettime only exists if clock_gettime is
@@ -836,10 +829,10 @@ u64 MonotonicNanoTime() {
836829
return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec;
837830
}
838831
#else
839-
// Non-Linux & Go always use the syscall.
832+
// Non-Linux & Go always use the regular function.
840833
u64 MonotonicNanoTime() {
841834
timespec ts;
842-
internal_clock_gettime(CLOCK_MONOTONIC, &ts);
835+
clock_gettime(CLOCK_MONOTONIC, &ts);
843836
return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec;
844837
}
845838
#endif // SANITIZER_LINUX && !SANITIZER_GO

0 commit comments

Comments
 (0)