diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2015-12-14 19:09:13 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-12-16 05:46:20 -0800 |
commit | 4c0dfefbdf950080746e48f6f95f449922bb5d0c (patch) | |
tree | 39de519307330b9de1d58381daaad28d489cf448 /sysdeps/unix/sysv/linux/times.c | |
parent | d29d57eed9a6acb646663a02b7eb2bece2c433dc (diff) | |
download | glibc-4c0dfefbdf950080746e48f6f95f449922bb5d0c.tar.gz glibc-4c0dfefbdf950080746e48f6f95f449922bb5d0c.tar.xz glibc-4c0dfefbdf950080746e48f6f95f449922bb5d0c.zip |
Use INTERNAL_SYSCALL_TIMES* macros for Linux times hjl/pr19363/master
The Linux times function, which returns clock_t, is implemented with INTERNAL_SYSCALL_DECL, INTERNAL_SYSCALL, INTERNAL_SYSCALL_ERROR_P and INTERNAL_SYSCALL_ERRNO. Since INTERNAL_SYSCALL* macros use 32-bit integer and clock_t is 64-bit on x32, this is a mismatch on x32. All system calls returning 64-bit integer, which are lseek, time and times, must be handled specially for x32. lseek is handled by x32 lseek.S and time doesn't check syscall return. times is the only missed one. This patch replaces INTERNAL_SYSCALL* macros in Linux times.c with INTERNAL_SYSCALL_TIMES* macros which are default to INTERNAL_SYSCALL* macros and provides x32 times.c with proper INTERNAL_SYSCALL_TIMES* macros. 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 ^^^^^^^^^^^^^^^^^^^^^ 32-bit compare 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 08 jne 15 <__times+0x15> d: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax 13: 77 13 ja 28 <__times+0x28> 15: 48 83 f8 ff cmp $0xffffffffffffffff,%rax 19: ba 00 00 00 00 mov $0x0,%edx 1e: 48 0f 44 c2 cmove %rdx,%rax 22: c3 retq The incorrect signed extension and 32-bit compare are gone. [BZ #19363] * sysdeps/unix/sysv/linux/times.c (INTERNAL_SYSCALL_TIMES_DECL): New. (INTERNAL_SYSCALL_TIMES): Likewise. (INTERNAL_SYSCALL_TIMES_ERROR_P): Likewise. (INTERNAL_SYSCALL_TIMES_ERRNO): Likewise. (__times): Replace INTERNAL_SYSCALL* macros with INTERNAL_SYSCALL_TIMES* macros. * sysdeps/unix/sysv/linux/x86_64/x32/times.c: New file.
Diffstat (limited to 'sysdeps/unix/sysv/linux/times.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/times.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/sysdeps/unix/sysv/linux/times.c b/sysdeps/unix/sysv/linux/times.c index 19b77cf1e0..d2e9c2326b 100644 --- a/sysdeps/unix/sysv/linux/times.c +++ b/sysdeps/unix/sysv/linux/times.c @@ -19,14 +19,34 @@ #include <sys/times.h> #include <sysdep.h> +#ifndef INTERNAL_SYSCALL_TIMES_DECL +# define INTERNAL_SYSCALL_TIMES_DECL(err) \ + INTERNAL_SYSCALL_DECL (err) +#endif + +#ifndef INTERNAL_SYSCALL_TIMES +# define INTERNAL_SYSCALL_TIMES(err, buf) \ + INTERNAL_SYSCALL (times, err, 1, buf) +#endif + +#ifndef INTERNAL_SYSCALL_TIMES_ERROR_P +# define INTERNAL_SYSCALL_TIMES_ERROR_P(ret, err) \ + INTERNAL_SYSCALL_ERROR_P (ret, err) +#endif + +#ifndef INTERNAL_SYSCALL_TIMES_ERRNO +# define INTERNAL_SYSCALL_TIMES_ERRNO(ret, err) \ + INTERNAL_SYSCALL_ERRNO (ret, err) +#endif clock_t __times (struct tms *buf) { - INTERNAL_SYSCALL_DECL (err); - clock_t ret = INTERNAL_SYSCALL (times, err, 1, buf); - if (INTERNAL_SYSCALL_ERROR_P (ret, err) - && __builtin_expect (INTERNAL_SYSCALL_ERRNO (ret, err) == EFAULT, 0) + INTERNAL_SYSCALL_TIMES_DECL (err); + clock_t ret = INTERNAL_SYSCALL_TIMES (err, buf); + if (INTERNAL_SYSCALL_TIMES_ERROR_P (ret, err) + && (__builtin_expect (INTERNAL_SYSCALL_TIMES_ERRNO (ret, err) + == EFAULT, 0)) && buf) { /* This might be an error or not. For architectures which have |