From 8a4f1e5889edc41f97c861af81d0f0354d0bc75a Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 14 Dec 2015 19:09:13 -0800 Subject: Use INTERNAL_SYSCALL_TIMES for Linux times The Linux times function, which returns clock_t, is implemented with INTERNAL_SYSCALL. Since INTERNAL_SYSCALL returns 32-bit integer and and clock_t is 64-bit on x32, this is a mismatch on x32. times is the only such function. This patch replaces INTERNAL_SYSCALL in Linux times.c with INTERNAL_SYSCALL_TIMES which is default to INTERNAL_SYSCALL and provides x32 times.c with proper INTERNAL_SYSCALL_TIMES. There is no code change on times for i686 nor x86-64. For x32, before this patch, there are 0000000 <__times>: 0: b8 64 00 00 40 mov $0x40000064,%eax 5: 0f 05 syscall 7: 48 63 d0 movslq %eax,%rdx ^^^^^^^^^^ Incorrect signed extension a: 48 83 fa f2 cmp $0xfffffffffffffff2,%rdx e: 75 07 jne 17 <__times+0x17> 10: 3d 00 f0 ff ff cmp $0xfffff000,%eax 15: 77 11 ja 28 <__times+0x28> 17: 48 83 fa ff cmp $0xffffffffffffffff,%rdx 1b: b8 00 00 00 00 mov $0x0,%eax 20: 48 0f 45 c2 cmovne %rdx,%rax 24: c3 retq After this patch, there are 00000000 <__times>: 0: b8 64 00 00 40 mov $0x40000064,%eax 5: 0f 05 syscall 7: 48 83 f8 f2 cmp $0xfffffffffffffff2,%rax b: 75 07 jne 14 <__times+0x14> d: 3d 00 f0 ff ff cmp $0xfffff000,%eax 12: 77 14 ja 28 <__times+0x28> 14: 48 83 f8 ff cmp $0xffffffffffffffff,%rax 18: ba 00 00 00 00 mov $0x0,%edx 1d: 48 0f 44 c2 cmove %rdx,%rax 21: c3 retq The incorrect signed extension is gone. [BZ #19363] * sysdeps/unix/sysv/linux/times.c (INTERNAL_SYSCALL_TIMES): New. (__times): Replace INTERNAL_SYSCALL with INTERNAL_SYSCALL_TIMES. * sysdeps/unix/sysv/linux/x86_64/x32/times.c: New file. xxx --- sysdeps/unix/sysv/linux/times.c | 6 +++++- sysdeps/unix/sysv/linux/x86_64/x32/times.c | 31 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 sysdeps/unix/sysv/linux/x86_64/x32/times.c diff --git a/sysdeps/unix/sysv/linux/times.c b/sysdeps/unix/sysv/linux/times.c index 19b77cf1e0..9d3beed3b8 100644 --- a/sysdeps/unix/sysv/linux/times.c +++ b/sysdeps/unix/sysv/linux/times.c @@ -19,12 +19,16 @@ #include #include +#ifndef INTERNAL_SYSCALL_TIMES +# define INTERNAL_SYSCALL_TIMES(err, buf) \ + INTERNAL_SYSCALL (times, err, 1, buf) +#endif clock_t __times (struct tms *buf) { INTERNAL_SYSCALL_DECL (err); - clock_t ret = INTERNAL_SYSCALL (times, err, 1, buf); + clock_t ret = INTERNAL_SYSCALL_TIMES (err, buf); if (INTERNAL_SYSCALL_ERROR_P (ret, err) && __builtin_expect (INTERNAL_SYSCALL_ERRNO (ret, err) == EFAULT, 0) && buf) diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/times.c b/sysdeps/unix/sysv/linux/x86_64/x32/times.c new file mode 100644 index 0000000000..330315fed2 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86_64/x32/times.c @@ -0,0 +1,31 @@ +/* Linux times. X32 version. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Inline Linux times system call. */ +#define INTERNAL_SYSCALL_TIMES(err, buf) \ + ({ \ + unsigned long long int resultvar; \ + LOAD_ARGS_1 (buf) \ + LOAD_REGS_1 \ + asm volatile ( \ + "syscall\n\t" \ + : "=a" (resultvar) \ + : "0" (__NR_times) ASM_ARGS_1 : "memory", "cc", "r11", "cx"); \ + (long long int) resultvar; }) + +#include -- cgit 1.4.1