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.
This commit is contained in:
Дмитрий Левин 2015-12-15 15:26:29 +00:00
parent c4afd6dc7a
commit b6b38fa73b

View File

@ -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, ",