From 57a8308c7d671d3de47e290ebda458f50604d46e Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Sun, 8 Jan 2023 17:56:46 +0000 Subject: [PATCH] Fix linking to 64-bit time_t versions of functions on musl musl switched to 64-bit time_t across all architectures in version 1.2.0: https://musl.libc.org/time64.html This change was done in a way which attempted to preserve ABI compatibility. To achieve this, the 32-bit versions of functions were left at their original names in the compiled library, and new 64-bit versions of functions were introduced. The header files then redirected calls to the standard function names to use the new 64-bit versions using the __asm__("name") construct, which is similar to D's pragma(mangle, "name"). This change is a fix-up for commit ca0b670b87284afa341f1bef57f5614d88aecb4b, which tried addressing this change in musl by changing time_t to 64-bit when targeting new musl versions (the default). However, that change was incomplete, as it did not implement the function redirection part of the change, which is required to actually call the implementations using 64-bit time_t. As a result, it caused programs to link but return incorrect results at runtime on 32-bit architectures when targeting new musl versions. Fix this by adjusting the mangled name of the D declarations of affected functions when targeting musl on 32-bit platforms. Affected functions in musl can be found by grepping for _REDIR_TIME64 and uses of the __REDIR macro. --- druntime/src/core/stdc/config.d | 25 +++++++++++++++++ druntime/src/core/stdc/time.d | 6 ++++ druntime/src/core/sys/posix/aio.d | 2 ++ druntime/src/core/sys/posix/dlfcn.d | 32 ++++++++++++++++++++++ druntime/src/core/sys/posix/mqueue.d | 2 ++ druntime/src/core/sys/posix/sched.d | 6 +++- druntime/src/core/sys/posix/semaphore.d | 1 + druntime/src/core/sys/posix/signal.d | 1 + druntime/src/core/sys/posix/sys/resource.d | 1 + druntime/src/core/sys/posix/sys/select.d | 2 ++ druntime/src/core/sys/posix/sys/stat.d | 3 ++ druntime/src/core/sys/posix/sys/time.d | 2 ++ druntime/src/core/sys/posix/time.d | 10 +++++++ druntime/src/core/sys/posix/utime.d | 1 + 14 files changed, 93 insertions(+), 1 deletion(-) diff --git a/druntime/src/core/stdc/config.d b/druntime/src/core/stdc/config.d index 9a9c29b19f7f..8033018bf66e 100644 --- a/druntime/src/core/stdc/config.d +++ b/druntime/src/core/stdc/config.d @@ -290,3 +290,28 @@ alias c_complex_float = __c_complex_float; alias c_complex_double = __c_complex_double; alias c_complex_real = __c_complex_real; } + + +// Returns the mangled name for the 64-bit time_t versions of +// functions affected by musl's transition to 64-bit time_t. +// https://musl.libc.org/time64.html +version (CRuntime_Musl) +{ + version (CRuntime_Musl_Pre_Time64) + enum muslRedirTime64 = false; + else + { + // time_t was defined as a C long in older Musl versions. + enum muslRedirTime64 = (c_long.sizeof == 4); + } +} +else + enum muslRedirTime64 = false; + +package(core) template muslRedirTime64Mangle(string name, string redirectedName) +{ + static if (muslRedirTime64) + enum muslRedirTime64Mangle = redirectedName; + else + enum muslRedirTime64Mangle = name; +} diff --git a/druntime/src/core/stdc/time.d b/druntime/src/core/stdc/time.d index b19c3c7a899f..d7a57655fabe 100644 --- a/druntime/src/core/stdc/time.d +++ b/druntime/src/core/stdc/time.d @@ -30,19 +30,25 @@ nothrow: @nogc: /// +pragma(mangle, muslRedirTime64Mangle!("difftime", "__difftime64")) pure double difftime(time_t time1, time_t time0); // MT-Safe /// +pragma(mangle, muslRedirTime64Mangle!("mktime", "__mktime64")) @system time_t mktime(scope tm* timeptr); // @system: MT-Safe env locale /// +pragma(mangle, muslRedirTime64Mangle!("time", "__time64")) time_t time(scope time_t* timer); /// @system char* asctime(const scope tm* timeptr); // @system: MT-Unsafe race:asctime locale /// +pragma(mangle, muslRedirTime64Mangle!("ctime", "__ctime64")) @system char* ctime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf race:asctime env locale /// +pragma(mangle, muslRedirTime64Mangle!("gmtime", "__gmtime64")) @system tm* gmtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale /// +pragma(mangle, muslRedirTime64Mangle!("localtime", "__localtime64")) @system tm* localtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale /// @system size_t strftime(scope char* s, size_t maxsize, const scope char* format, const scope tm* timeptr); // @system: MT-Safe env locale diff --git a/druntime/src/core/sys/posix/aio.d b/druntime/src/core/sys/posix/aio.d index 3ea7f6a19adf..3a537a4a575b 100644 --- a/druntime/src/core/sys/posix/aio.d +++ b/druntime/src/core/sys/posix/aio.d @@ -8,6 +8,7 @@ */ module core.sys.posix.aio; +import core.stdc.config; import core.sys.posix.signal; import core.sys.posix.sys.types; @@ -392,6 +393,7 @@ else int aio_fsync(int op, aiocb* aiocbp); int aio_error(const(aiocb)* aiocbp); ssize_t aio_return(aiocb* aiocbp); + pragma(mangle, muslRedirTime64Mangle!("aio_suspend", "__aio_suspend_time64")) int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout); int aio_cancel(int fd, aiocb* aiocbp); int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp); diff --git a/druntime/src/core/sys/posix/dlfcn.d b/druntime/src/core/sys/posix/dlfcn.d index 5797b8fd35d8..f4bd2d8ba92f 100644 --- a/druntime/src/core/sys/posix/dlfcn.d +++ b/druntime/src/core/sys/posix/dlfcn.d @@ -177,6 +177,38 @@ version (CRuntime_Glibc) void* dli_saddr; } } +else +version (CRuntime_Musl) +{ + enum RTLD_LAZY = 1; + enum RTLD_NOW = 2; + enum RTLD_NOLOAD = 4; + enum RTLD_NODELETE = 4096; + enum RTLD_GLOBAL = 256; + enum RTLD_LOCAL = 0; + + enum RTLD_NEXT = cast(void *)-1; + enum RTLD_DEFAULT = cast(void *)0; + + enum RTLD_DI_LINKMAP = 2; + + int dlclose(void *); + char *dlerror(); + void *dlopen(const(char) *, int); + + pragma(mangle, muslRedirTime64Mangle!("dlsym", "__dlsym_time64")) + void *dlsym(void *__restrict, const(char) *__restrict); + + struct Dl_info + { + const(char)* dli_fname; + void* dli_fbase; + const(char)* dli_sname; + void* dli_saddr; + } + int dladdr(const(void) *, Dl_info *); + int dlinfo(void *, int, void *); +} else version (Darwin) { enum RTLD_LAZY = 0x00001; diff --git a/druntime/src/core/sys/posix/mqueue.d b/druntime/src/core/sys/posix/mqueue.d index ac697bf8b9be..eae50d27d835 100644 --- a/druntime/src/core/sys/posix/mqueue.d +++ b/druntime/src/core/sys/posix/mqueue.d @@ -178,6 +178,7 @@ ssize_t mq_receive (mqd_t mqdes, char* msg_ptr, size_t msg_len, uint* msg_prio); * On success, mq_receive() returns the number of bytes in the received * message; on error, -1 is returned, with errno set to indicate the error */ +pragma(mangle, muslRedirTime64Mangle!("mq_timedreceive", "__mq_timedreceive_time64")) ssize_t mq_timedreceive (mqd_t mqdes, char* msg_ptr, size_t msg_len, uint* msg_prio, const(timespec)* abs_timeout); @@ -216,5 +217,6 @@ int mq_send (mqd_t mqdes, const(char)* msg_ptr, size_t msg_len, uint msg_prio); * with errno set to indicate the error. * */ +pragma(mangle, muslRedirTime64Mangle!("mq_timedsend", "__mq_timedsend_time64")) int mq_timedsend (mqd_t mqdes, const(char)* msg_ptr, size_t msg_len, uint msg_prio, const(timespec)* abs_timeout); diff --git a/druntime/src/core/sys/posix/sched.d b/druntime/src/core/sys/posix/sched.d index f6f0a58e3592..ba7ab8984a9c 100644 --- a/druntime/src/core/sys/posix/sched.d +++ b/druntime/src/core/sys/posix/sched.d @@ -65,7 +65,10 @@ version (linux) { int sched_priority; int __reserved1; - timespec[2] __reserved2; + static if (muslRedirTime64) + c_long[2] __reserved2; + else + timespec[2] __reserved2; int __reserved3; } } @@ -282,6 +285,7 @@ else version (CRuntime_Musl) { int sched_get_priority_max(int); int sched_get_priority_min(int); + pragma(mangle, muslRedirTime64Mangle!("sched_rr_get_interval", "__sched_rr_get_interval_time64")) int sched_rr_get_interval(pid_t, timespec*); } else version (CRuntime_UClibc) diff --git a/druntime/src/core/sys/posix/semaphore.d b/druntime/src/core/sys/posix/semaphore.d index d755f86c9cc8..4f3b6e951c33 100644 --- a/druntime/src/core/sys/posix/semaphore.d +++ b/druntime/src/core/sys/posix/semaphore.d @@ -216,6 +216,7 @@ else version (CRuntime_Bionic) } else version (CRuntime_Musl) { + pragma(mangle, muslRedirTime64Mangle!("sem_timedwait", "__sem_timedwait_time64")) int sem_timedwait(sem_t*, const scope timespec*); } else version (CRuntime_UClibc) diff --git a/druntime/src/core/sys/posix/signal.d b/druntime/src/core/sys/posix/signal.d index 542e83a1679d..f722bc4df628 100644 --- a/druntime/src/core/sys/posix/signal.d +++ b/druntime/src/core/sys/posix/signal.d @@ -2990,6 +2990,7 @@ else version (CRuntime_Bionic) else version (CRuntime_Musl) { int sigqueue(pid_t, int, const sigval); + pragma(mangle, muslRedirTime64Mangle!("sigtimedwait", "__sigtimedwait_time64")) int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*); int sigwaitinfo(const scope sigset_t*, siginfo_t*); } diff --git a/druntime/src/core/sys/posix/sys/resource.d b/druntime/src/core/sys/posix/sys/resource.d index 1f46f03e14d9..b997f112e4d0 100644 --- a/druntime/src/core/sys/posix/sys/resource.d +++ b/druntime/src/core/sys/posix/sys/resource.d @@ -547,6 +547,7 @@ else version (CRuntime_Musl) int setrlimit(int, const scope rlimit*); alias getrlimit getrlimit64; alias setrlimit setrlimit64; + pragma(mangle, muslRedirTime64Mangle!("getrusage", "__getrusage_time64")) int getrusage(int, rusage*); } else version (Solaris) diff --git a/druntime/src/core/sys/posix/sys/select.d b/druntime/src/core/sys/posix/sys/select.d index 06b094093ed5..dd05d08dde6b 100644 --- a/druntime/src/core/sys/posix/sys/select.d +++ b/druntime/src/core/sys/posix/sys/select.d @@ -501,7 +501,9 @@ else version (CRuntime_Musl) { fdset.fds_bits[0 .. $] = 0; } + pragma(mangle, muslRedirTime64Mangle!("pselect", "__pselect_time64")) int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); + pragma(mangle, muslRedirTime64Mangle!("select", "__select_time64")) int select(int, fd_set*, fd_set*, fd_set*, timeval*); } else version (CRuntime_UClibc) diff --git a/druntime/src/core/sys/posix/sys/stat.d b/druntime/src/core/sys/posix/sys/stat.d index ecc98ccf0ed8..4bcba2a6116c 100644 --- a/druntime/src/core/sys/posix/sys/stat.d +++ b/druntime/src/core/sys/posix/sys/stat.d @@ -1890,8 +1890,11 @@ else version (CRuntime_Bionic) } else version (CRuntime_Musl) { + pragma(mangle, muslRedirTime64Mangle!("stat", "__stat_time64")) int stat(const scope char*, stat_t*); + pragma(mangle, muslRedirTime64Mangle!("fstat", "__fstat_time64")) int fstat(int, stat_t*); + pragma(mangle, muslRedirTime64Mangle!("lstat", "__lstat_time64")) int lstat(const scope char*, stat_t*); alias fstat fstat64; diff --git a/druntime/src/core/sys/posix/sys/time.d b/druntime/src/core/sys/posix/sys/time.d index b536eedc14fe..dda4caf0bf36 100644 --- a/druntime/src/core/sys/posix/sys/time.d +++ b/druntime/src/core/sys/posix/sys/time.d @@ -89,7 +89,9 @@ else version (CRuntime_Musl) time_t tv_sec; suseconds_t tv_usec; } + pragma(mangle, muslRedirTime64Mangle!("gettimeofday", "__gettimeofday_time64")) int gettimeofday(timeval*, void*); + pragma(mangle, muslRedirTime64Mangle!("utimes", "__utimes_time64")) int utimes(const scope char*, ref const(timeval)[2]); } else version (Darwin) diff --git a/druntime/src/core/sys/posix/time.d b/druntime/src/core/sys/posix/time.d index af52002b1aaf..f49764d1964a 100644 --- a/druntime/src/core/sys/posix/time.d +++ b/druntime/src/core/sys/posix/time.d @@ -83,6 +83,7 @@ else version (CRuntime_Bionic) } else version (CRuntime_Musl) { + pragma(mangle, muslRedirTime64Mangle!("timegm", "__timegm_time64")) time_t timegm(tm*); } else version (CRuntime_UClibc) @@ -483,15 +484,21 @@ else version (CRuntime_Musl) int nanosleep(const scope timespec*, timespec*); + pragma(mangle, muslRedirTime64Mangle!("clock_getres", "__clock_getres_time64")) int clock_getres(clockid_t, timespec*); + pragma(mangle, muslRedirTime64Mangle!("clock_gettime", "__clock_gettime64")) int clock_gettime(clockid_t, timespec*); + pragma(mangle, muslRedirTime64Mangle!("clock_settime", "__clock_settime64")) int clock_settime(clockid_t, const scope timespec*); + pragma(mangle, muslRedirTime64Mangle!("clock_nanosleep", "__clock_nanosleep_time64")) int clock_nanosleep(clockid_t, int, const scope timespec*, timespec*); int clock_getcpuclockid(pid_t, clockid_t *); int timer_create(clockid_t, sigevent*, timer_t*); int timer_delete(timer_t); + pragma(mangle, muslRedirTime64Mangle!("timer_gettime", "__timer_gettime64")) int timer_gettime(timer_t, itimerspec*); + pragma(mangle, muslRedirTime64Mangle!("timer_settime", "__timer_settime64")) int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*); int timer_getoverrun(timer_t); } @@ -596,8 +603,11 @@ else version (CRuntime_Bionic) else version (CRuntime_Musl) { char* asctime_r(const scope tm*, char*); + pragma(mangle, muslRedirTime64Mangle!("ctime_r", "__ctime64_r")) char* ctime_r(const scope time_t*, char*); + pragma(mangle, muslRedirTime64Mangle!("gmtime_r", "__gmtime64_r")) tm* gmtime_r(const scope time_t*, tm*); + pragma(mangle, muslRedirTime64Mangle!("localtime_r", "__localtime64_r")) tm* localtime_r(const scope time_t*, tm*); } else version (CRuntime_UClibc) diff --git a/druntime/src/core/sys/posix/utime.d b/druntime/src/core/sys/posix/utime.d index fcec7af3fde0..e7059d712838 100644 --- a/druntime/src/core/sys/posix/utime.d +++ b/druntime/src/core/sys/posix/utime.d @@ -62,6 +62,7 @@ else version (CRuntime_Musl) time_t modtime; } + pragma(mangle, muslRedirTime64Mangle!("utime", "__utime64")) int utime(const scope char*, const scope utimbuf*); } else version (Darwin)