Skip to content

Commit

Permalink
Fix linking to 64-bit time_t versions of functions on musl (#14895)
Browse files Browse the repository at this point in the history
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
ca0b670, 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.

Fixes issue 23608.
  • Loading branch information
CyberShadow committed Feb 20, 2023
1 parent a9eedfe commit bacf62c
Show file tree
Hide file tree
Showing 14 changed files with 93 additions and 1 deletion.
25 changes: 25 additions & 0 deletions druntime/src/core/stdc/config.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
6 changes: 6 additions & 0 deletions druntime/src/core/stdc/time.d
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions druntime/src/core/sys/posix/aio.d
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/
module core.sys.posix.aio;

import core.stdc.config;
import core.sys.posix.signal;
import core.sys.posix.sys.types;

Expand Down Expand Up @@ -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);
Expand Down
32 changes: 32 additions & 0 deletions druntime/src/core/sys/posix/dlfcn.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions druntime/src/core/sys/posix/mqueue.d
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
6 changes: 5 additions & 1 deletion druntime/src/core/sys/posix/sched.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions druntime/src/core/sys/posix/semaphore.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions druntime/src/core/sys/posix/signal.d
Original file line number Diff line number Diff line change
Expand Up @@ -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*);
}
Expand Down
1 change: 1 addition & 0 deletions druntime/src/core/sys/posix/sys/resource.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions druntime/src/core/sys/posix/sys/select.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions druntime/src/core/sys/posix/sys/stat.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions druntime/src/core/sys/posix/sys/time.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions druntime/src/core/sys/posix/time.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions druntime/src/core/sys/posix/utime.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit bacf62c

Please sign in to comment.