From b6b38fa73b9e0810c68a19dcb3ade2974db20f8c Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Tue, 15 Dec 2015 15:26:29 +0000 Subject: [PATCH] tests/times.test: workaround libc bug on x32 As glibc times wrapper on x32 is known to wrongly truncate and then sign extend the syscall return value, invoke the syscall directly on x32. * tests/times.c (main) [__NR_times && __x86_64__ && __ILP32__]: Invoke times syscall using inline asm. --- tests/times.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/tests/times.c b/tests/times.c index f0e7086b..c34a9a32 100644 --- a/tests/times.c +++ b/tests/times.c @@ -69,9 +69,29 @@ main (void) * prefer direct times syscall over libc's times function because * the latter is more prone to return value truncation. */ -#if !defined __NR_times \ - || defined LINUX_MIPSN32 \ - || defined __x86_64__ && defined __ILP32__ +#undef USE_LIBC_SYSCALL +#if defined __NR_times && \ + !defined(LINUX_MIPSN32) && \ + !(defined __x86_64__ && defined __ILP32__) +# define USE_LIBC_SYSCALL 1 +#endif + +#if defined USE_LIBC_SYSCALL + long res = syscall(__NR_times, &tbuf); + + if (-1L == res) + return 77; + else + llres = (unsigned long) res; +#elif defined __NR_times && defined __x86_64__ && defined __ILP32__ + register long arg asm("rdi") = (long) &tbuf; + asm volatile("syscall\n\t" + : "=a"(llres) + : "0"(__NR_times), "r"(arg) + : "memory", "cc", "r11", "cx"); + if (llres > 0xfffffffffffff000) + return 77; +#else clock_t res = times(&tbuf); if ((clock_t) -1 == res) @@ -80,13 +100,6 @@ main (void) llres = (unsigned long) res; else llres = res; -#else - long res = syscall(__NR_times, &tbuf); - - if (-1L == res) - return 77; - else - llres = (unsigned long) res; #endif printf("times({tms_utime=%llu, tms_stime=%llu, ", -- 2.40.0