[1/5] Fix {INLINE,INTERNAL}_SYSCALL macros for x32
Commit Message
From: Adhemerval Zanella <adhemerval.zanella@linaro.com>
The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit
cast the arguments to 'long int', thus passing as 32 bits arguments
that should be passed to 64 bits.
Previous x32 implementation uses the auto-generated syscalls from
assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL
macros are never used with 64 bit argument in x32 (which are
internally broken for this ILP).
To fix it I used a strategy similar to MIPS64n32 (although both
ABI differs for some syscalls on how top pass 64-bits arguments)
where argument types for kernel call are defined using GCC extension
'typeof' with a arithmetic operation. This allows 64-bits arguments
to be defined while 32-bits argument will still passed as 32-bits.
I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining
'inline_syscallX' instead of constructing the argument passing using
macros (it adds some readability) and removed the ununsed
INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to
avoid requiric explicit types passing).
Tested on x86_64 and x32.
* sysdeps/unix/sysv/linux/x86_64/sysdep.h
(INTERNAL_SYSCALL_NCS_TYPES): Remove define.
(LOAD_ARGS_0): Likewise.
(LOAD_ARGS_1): Likewise.
(LOAD_ARGS_2): Likewise.
(LOAD_ARGS_3): Likewise.
(LOAD_ARGS_4): Likewise.
(LOAD_ARGS_5): Likewise.
(LOAD_ARGS_6): Likewise.
(LOAD_REGS_0): Likewise.
(LOAD_REGS_1): Likewise.
(LOAD_REGS_2): Likewise.
(LOAD_REGS_3): Likewise.
(LOAD_REGS_4): Likewise.
(LOAD_REGS_5): Likewise.
(LOAD_REGS_6): Likewise.
(ASM_ARGS_0): Likewise.
(ASM_ARGS_1): Likewise.
(ASM_ARGS_2): Likewise.
(ASM_ARGS_3): Likewise.
(ASM_ARGS_4): Likewise.
(ASM_ARGS_5): Likewise.
(ASM_ARGS_6): Likewise.
(LOAD_ARGS_TYPES_1): Likewise.
(LOAD_ARGS_TYPES_2): Likewise.
(LOAD_ARGS_TYPES_3): Likewise.
(LOAD_ARGS_TYPES_4): Likewise.
(LOAD_ARGS_TYPES_5): Likewise.
(LOAD_ARGS_TYPES_6): Likewise.
(LOAD_REGS_TYPES_1): Likewise.
(LOAD_REGS_TYPES_2): Likewise.
(LOAD_REGS_TYPES_3): Likewise.
(LOAD_REGS_TYPES_4): Likewise.
(LOAD_REGS_TYPES_5): Likewise.
(LOAD_REGS_TYPES_6): Likewise.
(TYPEFY): New define.
(ARGIFY): Likewise.
(internal_syscall0): Likewise.
(internal_syscall1): Likewise.
(internal_syscall2): Likewise.
(internal_syscall3): Likewise.
(internal_syscall4): Likewise.
(internal_syscall5): Likewise.
(internal_syscall6): Likewise.
* sysdeps/unix/sysv/linux/x86_64/x32/times.c
(INTERNAL_SYSCALL_NCS): Remove define.
(internal_syscall1): Add define.
---
ChangeLog | 50 ++++++
sysdeps/unix/sysv/linux/x86_64/sysdep.h | 251 ++++++++++++++++-------------
sysdeps/unix/sysv/linux/x86_64/x32/times.c | 24 +--
3 files changed, 205 insertions(+), 120 deletions(-)
Comments
Ping, x86 is the only target AFAIK preventing the sysdep-cancel asm
macro removal.
On 23/05/2017 15:25, Adhemerval Zanella wrote:
> From: Adhemerval Zanella <adhemerval.zanella@linaro.com>
>
> The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit
> cast the arguments to 'long int', thus passing as 32 bits arguments
> that should be passed to 64 bits.
>
> Previous x32 implementation uses the auto-generated syscalls from
> assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL
> macros are never used with 64 bit argument in x32 (which are
> internally broken for this ILP).
>
> To fix it I used a strategy similar to MIPS64n32 (although both
> ABI differs for some syscalls on how top pass 64-bits arguments)
> where argument types for kernel call are defined using GCC extension
> 'typeof' with a arithmetic operation. This allows 64-bits arguments
> to be defined while 32-bits argument will still passed as 32-bits.
>
> I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining
> 'inline_syscallX' instead of constructing the argument passing using
> macros (it adds some readability) and removed the ununsed
> INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to
> avoid requiric explicit types passing).
>
> Tested on x86_64 and x32.
>
> * sysdeps/unix/sysv/linux/x86_64/sysdep.h
> (INTERNAL_SYSCALL_NCS_TYPES): Remove define.
> (LOAD_ARGS_0): Likewise.
> (LOAD_ARGS_1): Likewise.
> (LOAD_ARGS_2): Likewise.
> (LOAD_ARGS_3): Likewise.
> (LOAD_ARGS_4): Likewise.
> (LOAD_ARGS_5): Likewise.
> (LOAD_ARGS_6): Likewise.
> (LOAD_REGS_0): Likewise.
> (LOAD_REGS_1): Likewise.
> (LOAD_REGS_2): Likewise.
> (LOAD_REGS_3): Likewise.
> (LOAD_REGS_4): Likewise.
> (LOAD_REGS_5): Likewise.
> (LOAD_REGS_6): Likewise.
> (ASM_ARGS_0): Likewise.
> (ASM_ARGS_1): Likewise.
> (ASM_ARGS_2): Likewise.
> (ASM_ARGS_3): Likewise.
> (ASM_ARGS_4): Likewise.
> (ASM_ARGS_5): Likewise.
> (ASM_ARGS_6): Likewise.
> (LOAD_ARGS_TYPES_1): Likewise.
> (LOAD_ARGS_TYPES_2): Likewise.
> (LOAD_ARGS_TYPES_3): Likewise.
> (LOAD_ARGS_TYPES_4): Likewise.
> (LOAD_ARGS_TYPES_5): Likewise.
> (LOAD_ARGS_TYPES_6): Likewise.
> (LOAD_REGS_TYPES_1): Likewise.
> (LOAD_REGS_TYPES_2): Likewise.
> (LOAD_REGS_TYPES_3): Likewise.
> (LOAD_REGS_TYPES_4): Likewise.
> (LOAD_REGS_TYPES_5): Likewise.
> (LOAD_REGS_TYPES_6): Likewise.
> (TYPEFY): New define.
> (ARGIFY): Likewise.
> (internal_syscall0): Likewise.
> (internal_syscall1): Likewise.
> (internal_syscall2): Likewise.
> (internal_syscall3): Likewise.
> (internal_syscall4): Likewise.
> (internal_syscall5): Likewise.
> (internal_syscall6): Likewise.
> * sysdeps/unix/sysv/linux/x86_64/x32/times.c
> (INTERNAL_SYSCALL_NCS): Remove define.
> (internal_syscall1): Add define.
> ---
> ChangeLog | 50 ++++++
> sysdeps/unix/sysv/linux/x86_64/sysdep.h | 251 ++++++++++++++++-------------
> sysdeps/unix/sysv/linux/x86_64/x32/times.c | 24 +--
> 3 files changed, 205 insertions(+), 120 deletions(-)
>
> diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
> index 7b8bd79..6d0a6f4 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
> @@ -221,33 +221,148 @@
> /* Registers clobbered by syscall. */
> # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
>
> -# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
> - ({ \
> - unsigned long int resultvar; \
> - LOAD_ARGS_##nr (args) \
> - LOAD_REGS_##nr \
> - asm volatile ( \
> - "syscall\n\t" \
> - : "=a" (resultvar) \
> - : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> - (long int) resultvar; })
> -# undef INTERNAL_SYSCALL
> -# define INTERNAL_SYSCALL(name, err, nr, args...) \
> - INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
> -
> -# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \
> - ({ \
> - unsigned long int resultvar; \
> - LOAD_ARGS_TYPES_##nr (args) \
> - LOAD_REGS_TYPES_##nr (args) \
> - asm volatile ( \
> - "syscall\n\t" \
> - : "=a" (resultvar) \
> - : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> - (long int) resultvar; })
> -# undef INTERNAL_SYSCALL_TYPES
> -# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \
> - INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)
> +/* Create a variable 'name' based on type 'X' to avoid explicit types.
> + This is mainly used set use 64-bits arguments in x32. */
> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
> +/* Explicit cast the argument to avoid integer from pointer warning on
> + x32. */
> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
> +
> +#undef INTERNAL_SYSCALL
> +#define INTERNAL_SYSCALL(name, err, nr, args...) \
> + internal_syscall##nr (SYS_ify (name), err, args)
> +
> +#undef INTERNAL_SYSCALL_NCS
> +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
> + internal_syscall##nr (number, err, args)
> +
> +#undef internal_syscall0
> +#define internal_syscall0(number, err, dummy...) \
> +({ \
> + unsigned long int resultvar; \
> + asm volatile ( \
> + "syscall\n\t" \
> + : "=a" (resultvar) \
> + : "0" (number) \
> + : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> + (long int) resultvar; \
> +})
> +
> +#undef internal_syscall1
> +#define internal_syscall1(number, err, arg1) \
> +({ \
> + unsigned long int resultvar; \
> + TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
> + register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
> + asm volatile ( \
> + "syscall\n\t" \
> + : "=a" (resultvar) \
> + : "0" (number), "r" (_a1) \
> + : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> + (long int) resultvar; \
> +})
> +
> +#undef internal_syscall2
> +#define internal_syscall2(number, err, arg1, arg2) \
> +({ \
> + unsigned long int resultvar; \
> + TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
> + TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
> + register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
> + register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
> + asm volatile ( \
> + "syscall\n\t" \
> + : "=a" (resultvar) \
> + : "0" (number), "r" (_a1), "r" (_a2) \
> + : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> + (long int) resultvar; \
> +})
> +
> +#undef internal_syscall3
> +#define internal_syscall3(number, err, arg1, arg2, arg3) \
> +({ \
> + unsigned long int resultvar; \
> + TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
> + TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
> + TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
> + register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
> + register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
> + register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
> + asm volatile ( \
> + "syscall\n\t" \
> + : "=a" (resultvar) \
> + : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3) \
> + : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> + (long int) resultvar; \
> +})
> +
> +#undef internal_syscall4
> +#define internal_syscall4(number, err, arg1, arg2, arg3, arg4) \
> +({ \
> + unsigned long int resultvar; \
> + TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
> + TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
> + TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
> + TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
> + register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
> + register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
> + register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
> + register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
> + asm volatile ( \
> + "syscall\n\t" \
> + : "=a" (resultvar) \
> + : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4) \
> + : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> + (long int) resultvar; \
> +})
> +
> +#undef internal_syscall5
> +#define internal_syscall5(number, err, arg1, arg2, arg3, arg4, arg5) \
> +({ \
> + unsigned long int resultvar; \
> + TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
> + TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
> + TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
> + TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
> + TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
> + register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
> + register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
> + register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
> + register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
> + register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
> + asm volatile ( \
> + "syscall\n\t" \
> + : "=a" (resultvar) \
> + : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
> + "r" (_a5) \
> + : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> + (long int) resultvar; \
> +})
> +
> +#undef internal_syscall6
> +#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \
> +({ \
> + unsigned long int resultvar; \
> + TYPEFY (arg6, __arg6) = ARGIFY (arg6); \
> + TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
> + TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
> + TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
> + TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
> + TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
> + register TYPEFY (arg6, _a6) asm ("r9") = __arg6; \
> + register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
> + register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
> + register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
> + register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
> + register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
> + asm volatile ( \
> + "syscall\n\t" \
> + : "=a" (resultvar) \
> + : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
> + "r" (_a5), "r" (_a6) \
> + : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> + (long int) resultvar; \
> +})
>
> # undef INTERNAL_SYSCALL_ERROR_P
> # define INTERNAL_SYSCALL_ERROR_P(val, err) \
> @@ -261,88 +376,6 @@
> # define HAVE_GETTIMEOFDAY_VSYSCALL 1
> # define HAVE_GETCPU_VSYSCALL 1
>
> -# define LOAD_ARGS_0()
> -# define LOAD_REGS_0
> -# define ASM_ARGS_0
> -
> -# define LOAD_ARGS_TYPES_1(t1, a1) \
> - t1 __arg1 = (t1) (a1); \
> - LOAD_ARGS_0 ()
> -# define LOAD_REGS_TYPES_1(t1, a1) \
> - register t1 _a1 asm ("rdi") = __arg1; \
> - LOAD_REGS_0
> -# define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1)
> -# define LOAD_ARGS_1(a1) \
> - LOAD_ARGS_TYPES_1 (long int, a1)
> -# define LOAD_REGS_1 \
> - LOAD_REGS_TYPES_1 (long int, a1)
> -
> -# define LOAD_ARGS_TYPES_2(t1, a1, t2, a2) \
> - t2 __arg2 = (t2) (a2); \
> - LOAD_ARGS_TYPES_1 (t1, a1)
> -# define LOAD_REGS_TYPES_2(t1, a1, t2, a2) \
> - register t2 _a2 asm ("rsi") = __arg2; \
> - LOAD_REGS_TYPES_1(t1, a1)
> -# define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2)
> -# define LOAD_ARGS_2(a1, a2) \
> - LOAD_ARGS_TYPES_2 (long int, a1, long int, a2)
> -# define LOAD_REGS_2 \
> - LOAD_REGS_TYPES_2 (long int, a1, long int, a2)
> -
> -# define LOAD_ARGS_TYPES_3(t1, a1, t2, a2, t3, a3) \
> - t3 __arg3 = (t3) (a3); \
> - LOAD_ARGS_TYPES_2 (t1, a1, t2, a2)
> -# define LOAD_REGS_TYPES_3(t1, a1, t2, a2, t3, a3) \
> - register t3 _a3 asm ("rdx") = __arg3; \
> - LOAD_REGS_TYPES_2(t1, a1, t2, a2)
> -# define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3)
> -# define LOAD_ARGS_3(a1, a2, a3) \
> - LOAD_ARGS_TYPES_3 (long int, a1, long int, a2, long int, a3)
> -# define LOAD_REGS_3 \
> - LOAD_REGS_TYPES_3 (long int, a1, long int, a2, long int, a3)
> -
> -# define LOAD_ARGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4) \
> - t4 __arg4 = (t4) (a4); \
> - LOAD_ARGS_TYPES_3 (t1, a1, t2, a2, t3, a3)
> -# define LOAD_REGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4) \
> - register t4 _a4 asm ("r10") = __arg4; \
> - LOAD_REGS_TYPES_3(t1, a2, t2, a2, t3, a3)
> -# define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4)
> -# define LOAD_ARGS_4(a1, a2, a3, a4) \
> - LOAD_ARGS_TYPES_4 (long int, a1, long int, a2, long int, a3, \
> - long int, a4)
> -# define LOAD_REGS_4 \
> - LOAD_REGS_TYPES_4 (long int, a1, long int, a2, long int, a3, \
> - long int, a4)
> -
> -# define LOAD_ARGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
> - t5 __arg5 = (t5) (a5); \
> - LOAD_ARGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4)
> -# define LOAD_REGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
> - register t5 _a5 asm ("r8") = __arg5; \
> - LOAD_REGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4)
> -# define ASM_ARGS_5 ASM_ARGS_4, "r" (_a5)
> -# define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
> - LOAD_ARGS_TYPES_5 (long int, a1, long int, a2, long int, a3, \
> - long int, a4, long int, a5)
> -# define LOAD_REGS_5 \
> - LOAD_REGS_TYPES_5 (long int, a1, long int, a2, long int, a3, \
> - long int, a4, long int, a5)
> -
> -# define LOAD_ARGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
> - t6 __arg6 = (t6) (a6); \
> - LOAD_ARGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)
> -# define LOAD_REGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
> - register t6 _a6 asm ("r9") = __arg6; \
> - LOAD_REGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)
> -# define ASM_ARGS_6 ASM_ARGS_5, "r" (_a6)
> -# define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \
> - LOAD_ARGS_TYPES_6 (long int, a1, long int, a2, long int, a3, \
> - long int, a4, long int, a5, long int, a6)
> -# define LOAD_REGS_6 \
> - LOAD_REGS_TYPES_6 (long int, a1, long int, a2, long int, a3, \
> - long int, a4, long int, a5, long int, a6)
> -
> #endif /* __ASSEMBLER__ */
>
>
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/times.c b/sysdeps/unix/sysv/linux/x86_64/x32/times.c
> index d56106e..8763047 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/times.c
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/times.c
> @@ -19,17 +19,19 @@
> #include <sysdep.h>
>
> /* Linux times system call returns 64-bit integer. */
> -#undef INTERNAL_SYSCALL_NCS
> -#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
> - ({ \
> - unsigned long long int resultvar; \
> - LOAD_ARGS_##nr (args) \
> - LOAD_REGS_##nr \
> - asm volatile ( \
> - "syscall\n\t" \
> - : "=a" (resultvar) \
> - : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> - (long long int) resultvar; })
> +#undef internal_syscall1
> +#define internal_syscall1(number, err, arg1) \
> +({ \
> + unsigned long long int resultvar; \
> + TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
> + register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
> + asm volatile ( \
> + "syscall\n\t" \
> + : "=a" (resultvar) \
> + : "0" (number), "r" (_a1) \
> + : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> + (long long int) resultvar; \
> +})
>
> #undef INTERNAL_SYSCALL_ERROR_P
> #define INTERNAL_SYSCALL_ERROR_P(val, err) \
>
On 06/29/2017 04:15 PM, Adhemerval Zanella wrote:
> +/* Create a variable 'name' based on type 'X' to avoid explicit types.
> + This is mainly used set use 64-bits arguments in x32. */
> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
> +/* Explicit cast the argument to avoid integer from pointer warning on
> + x32. */
> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
I think cast_to_integer was added for this purpose.
Thanks,
Florian
On 29/06/2017 15:50, Florian Weimer wrote:
> On 06/29/2017 04:15 PM, Adhemerval Zanella wrote:
>> +/* Create a variable 'name' based on type 'X' to avoid explicit types.
>> + This is mainly used set use 64-bits arguments in x32. */
>> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
>> +/* Explicit cast the argument to avoid integer from pointer warning on
>> + x32. */
>> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
>
> I think cast_to_integer was added for this purpose.
The 'cast_to_integer' macro was added after my initial (I based the ARGIFY
macro on the mips64n32 one) and checking it by replacing ARGIGY with
'cast_to_integer' I see:
---
gconv_cache.c: In function ‘__gconv_load_cache’:
../include/libc-pointer-arith.h:34:45: error: cast specifies array type
__integer_if_pointer_type_sub(__typeof__ ((__typeof__ (expr)) 0), \
^
../include/libc-pointer-arith.h:29:39: note: in definition of macro ‘__integer_if_pointer_type_sub’
__typeof__ (*(0 ? (__typeof__ (0 ? (T *) 0 : (void *) (P))) 0 \
^
../include/libc-pointer-arith.h:38:33: note: in expansion of macro ‘__integer_if_pointer_type’
# define cast_to_integer(val) ((__integer_if_pointer_type (val)) (val))
^~~~~~~~~~~~~~~~~~~~~~~~~
../sysdeps/unix/sysv/linux/x86_64/sysdep.h:284:29: note: in expansion of macro ‘cast_to_integer’
TYPEFY (arg1, __arg1) = cast_to_integer (arg1); \
^~~~~~~~~~~~~~~
../sysdeps/unix/sysv/linux/x86_64/sysdep.h:230:2: note: in expansion of macro ‘internal_syscall3’
internal_syscall##nr (SYS_ify (name), err, args)
^~~~~~~~~~~~~~~~
../sysdeps/unix/sysv/linux/x86_64/sysdep.h:196:35: note: in expansion of macro ‘INTERNAL_SYSCALL’
unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args); \
^~~~~~~~~~~~~~~~
../sysdeps/unix/sysv/linux/not-cancel.h:31:4: note: in expansion of macro ‘INLINE_SYSCALL’
INLINE_SYSCALL (open, 3, name, flags, mode)
---
And I recall this was one the issue I had when creating this patch. Using compound
literal on __typeof__ cast did not help due we build with -Wwrite-strings it and
in turn it enables -Wdiscarded-array-qualifiers. This triggers a 'pointer to
array loses qualifier', because constness type is propagate.
So to actually use cast_to_integer workable on char array (and on other arrays
as well) one solution is to incorporate the arithmetic promotion used on
mips64n32 sysdep and also on this patch:
---
/* Type cast using arithmetic promotion. It also remove l-value-constness
when using char arrays on cast_to_interger (for instance
cast_to_interger ("...") will not trigger a 'pointer to array loses
qualifier' warning due -Wdiscarded-array-qualifiers from -Wwrite-strings.
*/
# define __typeof_arith_promote(T) __typeof__((T) - (T))
/* 1 if 'type' is a pointer type, 0 otherwise. */
# define __pointer_type(type) (__builtin_classify_type ((type) 0) == 5)
/* intptr_t if P is true, or T if P is false. */
# define __integer_if_pointer_type_sub(T, P) \
__typeof__ (*(0 ? (__typeof__ (0 ? (T *) 0: (void *) (P))) 0 \
: (__typeof__ (0 ? (intptr_t *) 0: (void *) (!(P)))) 0))
/* intptr_t if EXPR has a pointer type, or the type of EXPR otherwise. */
# define __integer_if_pointer_type(expr) \
__integer_if_pointer_type_sub(__typeof__ ((__typeof_arith_promote (expr)) 0), \
__pointer_type (__typeof_arith_promote (expr)))
/* Cast an integer or a pointer VAL to integer with proper type. */
# define cast_to_integer(val) ((__integer_if_pointer_type (val)) (val))
---
I am not sure how safe is the arithmetic promotion in the all the possible
cases where one could use cast_to_integer, however current cases on atomic
and syscall usage should be safe (make check shows no regression on
x86_64{-x32} with the pread auto-generate removal applied, so they use the
default Linux implementation. If you think it is worth I can resend with the
libc-pointer-arith.h modification.
On Tue, May 23, 2017 at 11:25 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> From: Adhemerval Zanella <adhemerval.zanella@linaro.com>
>
> The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit
> cast the arguments to 'long int', thus passing as 32 bits arguments
> that should be passed to 64 bits.
>
> Previous x32 implementation uses the auto-generated syscalls from
> assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL
> macros are never used with 64 bit argument in x32 (which are
> internally broken for this ILP).
>
> To fix it I used a strategy similar to MIPS64n32 (although both
> ABI differs for some syscalls on how top pass 64-bits arguments)
> where argument types for kernel call are defined using GCC extension
> 'typeof' with a arithmetic operation. This allows 64-bits arguments
> to be defined while 32-bits argument will still passed as 32-bits.
>
> I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining
> 'inline_syscallX' instead of constructing the argument passing using
> macros (it adds some readability) and removed the ununsed
> INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to
> avoid requiric explicit types passing).
>
> Tested on x86_64 and x32.
>
> * sysdeps/unix/sysv/linux/x86_64/sysdep.h
> (INTERNAL_SYSCALL_NCS_TYPES): Remove define.
> (LOAD_ARGS_0): Likewise.
> (LOAD_ARGS_1): Likewise.
> (LOAD_ARGS_2): Likewise.
> (LOAD_ARGS_3): Likewise.
> (LOAD_ARGS_4): Likewise.
> (LOAD_ARGS_5): Likewise.
> (LOAD_ARGS_6): Likewise.
> (LOAD_REGS_0): Likewise.
> (LOAD_REGS_1): Likewise.
> (LOAD_REGS_2): Likewise.
> (LOAD_REGS_3): Likewise.
> (LOAD_REGS_4): Likewise.
> (LOAD_REGS_5): Likewise.
> (LOAD_REGS_6): Likewise.
> (ASM_ARGS_0): Likewise.
> (ASM_ARGS_1): Likewise.
> (ASM_ARGS_2): Likewise.
> (ASM_ARGS_3): Likewise.
> (ASM_ARGS_4): Likewise.
> (ASM_ARGS_5): Likewise.
> (ASM_ARGS_6): Likewise.
> (LOAD_ARGS_TYPES_1): Likewise.
> (LOAD_ARGS_TYPES_2): Likewise.
> (LOAD_ARGS_TYPES_3): Likewise.
> (LOAD_ARGS_TYPES_4): Likewise.
> (LOAD_ARGS_TYPES_5): Likewise.
> (LOAD_ARGS_TYPES_6): Likewise.
> (LOAD_REGS_TYPES_1): Likewise.
> (LOAD_REGS_TYPES_2): Likewise.
> (LOAD_REGS_TYPES_3): Likewise.
> (LOAD_REGS_TYPES_4): Likewise.
> (LOAD_REGS_TYPES_5): Likewise.
> (LOAD_REGS_TYPES_6): Likewise.
> (TYPEFY): New define.
> (ARGIFY): Likewise.
> (internal_syscall0): Likewise.
> (internal_syscall1): Likewise.
> (internal_syscall2): Likewise.
> (internal_syscall3): Likewise.
> (internal_syscall4): Likewise.
> (internal_syscall5): Likewise.
> (internal_syscall6): Likewise.
> * sysdeps/unix/sysv/linux/x86_64/x32/times.c
> (INTERNAL_SYSCALL_NCS): Remove define.
> (internal_syscall1): Add define.
> ---
> ChangeLog | 50 ++++++
> sysdeps/unix/sysv/linux/x86_64/sysdep.h | 251 ++++++++++++++++-------------
> sysdeps/unix/sysv/linux/x86_64/x32/times.c | 24 +--
> 3 files changed, 205 insertions(+), 120 deletions(-)
>
> diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
> index 7b8bd79..6d0a6f4 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
> @@ -221,33 +221,148 @@
> /* Registers clobbered by syscall. */
> # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
>
> -# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
> - ({ \
> - unsigned long int resultvar; \
> - LOAD_ARGS_##nr (args) \
> - LOAD_REGS_##nr \
> - asm volatile ( \
> - "syscall\n\t" \
> - : "=a" (resultvar) \
> - : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> - (long int) resultvar; })
> -# undef INTERNAL_SYSCALL
> -# define INTERNAL_SYSCALL(name, err, nr, args...) \
> - INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
> -
> -# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \
> - ({ \
> - unsigned long int resultvar; \
> - LOAD_ARGS_TYPES_##nr (args) \
> - LOAD_REGS_TYPES_##nr (args) \
> - asm volatile ( \
> - "syscall\n\t" \
> - : "=a" (resultvar) \
> - : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
> - (long int) resultvar; })
> -# undef INTERNAL_SYSCALL_TYPES
> -# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \
> - INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)
> +/* Create a variable 'name' based on type 'X' to avoid explicit types.
> + This is mainly used set use 64-bits arguments in x32. */
> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
> +/* Explicit cast the argument to avoid integer from pointer warning on
> + x32. */
> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
> +
I am a little bit concerned about this. The current macros cast to long int
by default on purpose. 64-bit return and arguments are treated as
special cases. With your change, this code in loadlocale.c:
if (filedata != NULL)
{
off_t to_read = st.st_size;
ssize_t nread;
char *p = (char *) filedata;
while (to_read > 0)
{
nread = read_not_cancel (fd, p, to_read);
if (__builtin_expect (nread, 1) <= 0)
{
free (filedata);
if (nread == 0)
__set_errno (EINVAL); /* Bizarreness going on. */
goto puntfd;
}
p += nread;
is generated differently. On x32, ssize_t is 32 bits and offset is 64 bits.
Before your patch, to_read is passed as 32 bit value. With your change,
__typeof__ ((X) - (X)) turns to_read into 64 bits. It may be OK for this
particular case. But I am not certain that your change is 100% safe in
all cases.
H.J.
On 01/07/2017 13:53, H.J. Lu wrote:
> On Tue, May 23, 2017 at 11:25 AM, Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>> From: Adhemerval Zanella <adhemerval.zanella@linaro.com>
>>
>> The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit
>> cast the arguments to 'long int', thus passing as 32 bits arguments
>> that should be passed to 64 bits.
>>
>> Previous x32 implementation uses the auto-generated syscalls from
>> assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL
>> macros are never used with 64 bit argument in x32 (which are
>> internally broken for this ILP).
>>
>> To fix it I used a strategy similar to MIPS64n32 (although both
>> ABI differs for some syscalls on how top pass 64-bits arguments)
>> where argument types for kernel call are defined using GCC extension
>> 'typeof' with a arithmetic operation. This allows 64-bits arguments
>> to be defined while 32-bits argument will still passed as 32-bits.
>>
>> I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining
>> 'inline_syscallX' instead of constructing the argument passing using
>> macros (it adds some readability) and removed the ununsed
>> INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to
>> avoid requiric explicit types passing).
>>
>> Tested on x86_64 and x32.
>>
>> * sysdeps/unix/sysv/linux/x86_64/sysdep.h
>> (INTERNAL_SYSCALL_NCS_TYPES): Remove define.
>> (LOAD_ARGS_0): Likewise.
>> (LOAD_ARGS_1): Likewise.
>> (LOAD_ARGS_2): Likewise.
>> (LOAD_ARGS_3): Likewise.
>> (LOAD_ARGS_4): Likewise.
>> (LOAD_ARGS_5): Likewise.
>> (LOAD_ARGS_6): Likewise.
>> (LOAD_REGS_0): Likewise.
>> (LOAD_REGS_1): Likewise.
>> (LOAD_REGS_2): Likewise.
>> (LOAD_REGS_3): Likewise.
>> (LOAD_REGS_4): Likewise.
>> (LOAD_REGS_5): Likewise.
>> (LOAD_REGS_6): Likewise.
>> (ASM_ARGS_0): Likewise.
>> (ASM_ARGS_1): Likewise.
>> (ASM_ARGS_2): Likewise.
>> (ASM_ARGS_3): Likewise.
>> (ASM_ARGS_4): Likewise.
>> (ASM_ARGS_5): Likewise.
>> (ASM_ARGS_6): Likewise.
>> (LOAD_ARGS_TYPES_1): Likewise.
>> (LOAD_ARGS_TYPES_2): Likewise.
>> (LOAD_ARGS_TYPES_3): Likewise.
>> (LOAD_ARGS_TYPES_4): Likewise.
>> (LOAD_ARGS_TYPES_5): Likewise.
>> (LOAD_ARGS_TYPES_6): Likewise.
>> (LOAD_REGS_TYPES_1): Likewise.
>> (LOAD_REGS_TYPES_2): Likewise.
>> (LOAD_REGS_TYPES_3): Likewise.
>> (LOAD_REGS_TYPES_4): Likewise.
>> (LOAD_REGS_TYPES_5): Likewise.
>> (LOAD_REGS_TYPES_6): Likewise.
>> (TYPEFY): New define.
>> (ARGIFY): Likewise.
>> (internal_syscall0): Likewise.
>> (internal_syscall1): Likewise.
>> (internal_syscall2): Likewise.
>> (internal_syscall3): Likewise.
>> (internal_syscall4): Likewise.
>> (internal_syscall5): Likewise.
>> (internal_syscall6): Likewise.
>> * sysdeps/unix/sysv/linux/x86_64/x32/times.c
>> (INTERNAL_SYSCALL_NCS): Remove define.
>> (internal_syscall1): Add define.
>> ---
>> ChangeLog | 50 ++++++
>> sysdeps/unix/sysv/linux/x86_64/sysdep.h | 251 ++++++++++++++++-------------
>> sysdeps/unix/sysv/linux/x86_64/x32/times.c | 24 +--
>> 3 files changed, 205 insertions(+), 120 deletions(-)
>>
>> diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
>> index 7b8bd79..6d0a6f4 100644
>> --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
>> +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
>> @@ -221,33 +221,148 @@
>> /* Registers clobbered by syscall. */
>> # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
>>
>> -# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
>> - ({ \
>> - unsigned long int resultvar; \
>> - LOAD_ARGS_##nr (args) \
>> - LOAD_REGS_##nr \
>> - asm volatile ( \
>> - "syscall\n\t" \
>> - : "=a" (resultvar) \
>> - : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
>> - (long int) resultvar; })
>> -# undef INTERNAL_SYSCALL
>> -# define INTERNAL_SYSCALL(name, err, nr, args...) \
>> - INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
>> -
>> -# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \
>> - ({ \
>> - unsigned long int resultvar; \
>> - LOAD_ARGS_TYPES_##nr (args) \
>> - LOAD_REGS_TYPES_##nr (args) \
>> - asm volatile ( \
>> - "syscall\n\t" \
>> - : "=a" (resultvar) \
>> - : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
>> - (long int) resultvar; })
>> -# undef INTERNAL_SYSCALL_TYPES
>> -# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \
>> - INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)
>> +/* Create a variable 'name' based on type 'X' to avoid explicit types.
>> + This is mainly used set use 64-bits arguments in x32. */
>> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
>> +/* Explicit cast the argument to avoid integer from pointer warning on
>> + x32. */
>> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
>> +
>
> I am a little bit concerned about this. The current macros cast to long int
> by default on purpose. 64-bit return and arguments are treated as
> special cases. With your change, this code in loadlocale.c:
>
> if (filedata != NULL)
> {
> off_t to_read = st.st_size;
> ssize_t nread;
> char *p = (char *) filedata;
> while (to_read > 0)
> {
> nread = read_not_cancel (fd, p, to_read);
> if (__builtin_expect (nread, 1) <= 0)
> {
> free (filedata);
> if (nread == 0)
> __set_errno (EINVAL); /* Bizarreness going on. */
> goto puntfd;
> }
> p += nread;
>
> is generated differently. On x32, ssize_t is 32 bits and offset is 64 bits.
> Before your patch, to_read is passed as 32 bit value. With your change,
> __typeof__ ((X) - (X)) turns to_read into 64 bits. It may be OK for this
> particular case. But I am not certain that your change is 100% safe in
> all cases.
I think the problem is we define 'read_not_cancel' as a macro rather than
an static inline with expected arguments types. For a QoI I think creating
wrappers around it would be better.
I would like to make the syscall internal macros to work seamlessly across
all architectures and avoid to create specialized assembly macros for
specific syscalls (such as lseek{64} for x32 witch I think it is not
avoidable). Also x32 is the only architecture afaik preventing the
syscall-cancel.h cleanup currently.
On Mon, Jul 3, 2017 at 4:52 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>
>
> On 01/07/2017 13:53, H.J. Lu wrote:
>> On Tue, May 23, 2017 at 11:25 AM, Adhemerval Zanella
>> <adhemerval.zanella@linaro.org> wrote:
>>> From: Adhemerval Zanella <adhemerval.zanella@linaro.com>
>>>
>>> The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit
>>> cast the arguments to 'long int', thus passing as 32 bits arguments
>>> that should be passed to 64 bits.
>>>
>>> Previous x32 implementation uses the auto-generated syscalls from
>>> assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL
>>> macros are never used with 64 bit argument in x32 (which are
>>> internally broken for this ILP).
>>>
>>> To fix it I used a strategy similar to MIPS64n32 (although both
>>> ABI differs for some syscalls on how top pass 64-bits arguments)
>>> where argument types for kernel call are defined using GCC extension
>>> 'typeof' with a arithmetic operation. This allows 64-bits arguments
>>> to be defined while 32-bits argument will still passed as 32-bits.
>>>
>>> I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining
>>> 'inline_syscallX' instead of constructing the argument passing using
>>> macros (it adds some readability) and removed the ununsed
>>> INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to
>>> avoid requiric explicit types passing).
>>>
>>> Tested on x86_64 and x32.
>>>
>>> * sysdeps/unix/sysv/linux/x86_64/sysdep.h
>>> (INTERNAL_SYSCALL_NCS_TYPES): Remove define.
>>> (LOAD_ARGS_0): Likewise.
>>> (LOAD_ARGS_1): Likewise.
>>> (LOAD_ARGS_2): Likewise.
>>> (LOAD_ARGS_3): Likewise.
>>> (LOAD_ARGS_4): Likewise.
>>> (LOAD_ARGS_5): Likewise.
>>> (LOAD_ARGS_6): Likewise.
>>> (LOAD_REGS_0): Likewise.
>>> (LOAD_REGS_1): Likewise.
>>> (LOAD_REGS_2): Likewise.
>>> (LOAD_REGS_3): Likewise.
>>> (LOAD_REGS_4): Likewise.
>>> (LOAD_REGS_5): Likewise.
>>> (LOAD_REGS_6): Likewise.
>>> (ASM_ARGS_0): Likewise.
>>> (ASM_ARGS_1): Likewise.
>>> (ASM_ARGS_2): Likewise.
>>> (ASM_ARGS_3): Likewise.
>>> (ASM_ARGS_4): Likewise.
>>> (ASM_ARGS_5): Likewise.
>>> (ASM_ARGS_6): Likewise.
>>> (LOAD_ARGS_TYPES_1): Likewise.
>>> (LOAD_ARGS_TYPES_2): Likewise.
>>> (LOAD_ARGS_TYPES_3): Likewise.
>>> (LOAD_ARGS_TYPES_4): Likewise.
>>> (LOAD_ARGS_TYPES_5): Likewise.
>>> (LOAD_ARGS_TYPES_6): Likewise.
>>> (LOAD_REGS_TYPES_1): Likewise.
>>> (LOAD_REGS_TYPES_2): Likewise.
>>> (LOAD_REGS_TYPES_3): Likewise.
>>> (LOAD_REGS_TYPES_4): Likewise.
>>> (LOAD_REGS_TYPES_5): Likewise.
>>> (LOAD_REGS_TYPES_6): Likewise.
>>> (TYPEFY): New define.
>>> (ARGIFY): Likewise.
>>> (internal_syscall0): Likewise.
>>> (internal_syscall1): Likewise.
>>> (internal_syscall2): Likewise.
>>> (internal_syscall3): Likewise.
>>> (internal_syscall4): Likewise.
>>> (internal_syscall5): Likewise.
>>> (internal_syscall6): Likewise.
>>> * sysdeps/unix/sysv/linux/x86_64/x32/times.c
>>> (INTERNAL_SYSCALL_NCS): Remove define.
>>> (internal_syscall1): Add define.
>>> ---
>>> ChangeLog | 50 ++++++
>>> sysdeps/unix/sysv/linux/x86_64/sysdep.h | 251 ++++++++++++++++-------------
>>> sysdeps/unix/sysv/linux/x86_64/x32/times.c | 24 +--
>>> 3 files changed, 205 insertions(+), 120 deletions(-)
>>>
>>> diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
>>> index 7b8bd79..6d0a6f4 100644
>>> --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
>>> +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
>>> @@ -221,33 +221,148 @@
>>> /* Registers clobbered by syscall. */
>>> # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
>>>
>>> -# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
>>> - ({ \
>>> - unsigned long int resultvar; \
>>> - LOAD_ARGS_##nr (args) \
>>> - LOAD_REGS_##nr \
>>> - asm volatile ( \
>>> - "syscall\n\t" \
>>> - : "=a" (resultvar) \
>>> - : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
>>> - (long int) resultvar; })
>>> -# undef INTERNAL_SYSCALL
>>> -# define INTERNAL_SYSCALL(name, err, nr, args...) \
>>> - INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
>>> -
>>> -# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \
>>> - ({ \
>>> - unsigned long int resultvar; \
>>> - LOAD_ARGS_TYPES_##nr (args) \
>>> - LOAD_REGS_TYPES_##nr (args) \
>>> - asm volatile ( \
>>> - "syscall\n\t" \
>>> - : "=a" (resultvar) \
>>> - : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
>>> - (long int) resultvar; })
>>> -# undef INTERNAL_SYSCALL_TYPES
>>> -# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \
>>> - INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)
>>> +/* Create a variable 'name' based on type 'X' to avoid explicit types.
>>> + This is mainly used set use 64-bits arguments in x32. */
>>> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
>>> +/* Explicit cast the argument to avoid integer from pointer warning on
>>> + x32. */
>>> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
>>> +
>>
>> I am a little bit concerned about this. The current macros cast to long int
>> by default on purpose. 64-bit return and arguments are treated as
>> special cases. With your change, this code in loadlocale.c:
>>
>> if (filedata != NULL)
>> {
>> off_t to_read = st.st_size;
>> ssize_t nread;
>> char *p = (char *) filedata;
>> while (to_read > 0)
>> {
>> nread = read_not_cancel (fd, p, to_read);
>> if (__builtin_expect (nread, 1) <= 0)
>> {
>> free (filedata);
>> if (nread == 0)
>> __set_errno (EINVAL); /* Bizarreness going on. */
>> goto puntfd;
>> }
>> p += nread;
>>
>> is generated differently. On x32, ssize_t is 32 bits and offset is 64 bits.
>> Before your patch, to_read is passed as 32 bit value. With your change,
>> __typeof__ ((X) - (X)) turns to_read into 64 bits. It may be OK for this
>> particular case. But I am not certain that your change is 100% safe in
>> all cases.
>
> I think the problem is we define 'read_not_cancel' as a macro rather than
> an static inline with expected arguments types. For a QoI I think creating
> wrappers around it would be better.
That is fine with me.
> I would like to make the syscall internal macros to work seamlessly across
> all architectures and avoid to create specialized assembly macros for
> specific syscalls (such as lseek{64} for x32 witch I think it is not
> avoidable). Also x32 is the only architecture afaik preventing the
> syscall-cancel.h cleanup currently.
There is fine with me as long as the implementation is correct for
x32. But the current one isn't correct for x32.
Thanks.
@@ -221,33 +221,148 @@
/* Registers clobbered by syscall. */
# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
-# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
- ({ \
- unsigned long int resultvar; \
- LOAD_ARGS_##nr (args) \
- LOAD_REGS_##nr \
- asm volatile ( \
- "syscall\n\t" \
- : "=a" (resultvar) \
- : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
- (long int) resultvar; })
-# undef INTERNAL_SYSCALL
-# define INTERNAL_SYSCALL(name, err, nr, args...) \
- INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
-
-# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \
- ({ \
- unsigned long int resultvar; \
- LOAD_ARGS_TYPES_##nr (args) \
- LOAD_REGS_TYPES_##nr (args) \
- asm volatile ( \
- "syscall\n\t" \
- : "=a" (resultvar) \
- : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
- (long int) resultvar; })
-# undef INTERNAL_SYSCALL_TYPES
-# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \
- INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)
+/* Create a variable 'name' based on type 'X' to avoid explicit types.
+ This is mainly used set use 64-bits arguments in x32. */
+#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
+/* Explicit cast the argument to avoid integer from pointer warning on
+ x32. */
+#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
+
+#undef INTERNAL_SYSCALL
+#define INTERNAL_SYSCALL(name, err, nr, args...) \
+ internal_syscall##nr (SYS_ify (name), err, args)
+
+#undef INTERNAL_SYSCALL_NCS
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
+ internal_syscall##nr (number, err, args)
+
+#undef internal_syscall0
+#define internal_syscall0(number, err, dummy...) \
+({ \
+ unsigned long int resultvar; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall1
+#define internal_syscall1(number, err, arg1) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall2
+#define internal_syscall2(number, err, arg1, arg2) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall3
+#define internal_syscall3(number, err, arg1, arg2, arg3) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall4
+#define internal_syscall4(number, err, arg1, arg2, arg3, arg4) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall5
+#define internal_syscall5(number, err, arg1, arg2, arg3, arg4, arg5) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
+ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
+ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
+ "r" (_a5) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall6
+#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg6, __arg6) = ARGIFY (arg6); \
+ TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
+ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg6, _a6) asm ("r9") = __arg6; \
+ register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
+ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
+ "r" (_a5), "r" (_a6) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
# undef INTERNAL_SYSCALL_ERROR_P
# define INTERNAL_SYSCALL_ERROR_P(val, err) \
@@ -261,88 +376,6 @@
# define HAVE_GETTIMEOFDAY_VSYSCALL 1
# define HAVE_GETCPU_VSYSCALL 1
-# define LOAD_ARGS_0()
-# define LOAD_REGS_0
-# define ASM_ARGS_0
-
-# define LOAD_ARGS_TYPES_1(t1, a1) \
- t1 __arg1 = (t1) (a1); \
- LOAD_ARGS_0 ()
-# define LOAD_REGS_TYPES_1(t1, a1) \
- register t1 _a1 asm ("rdi") = __arg1; \
- LOAD_REGS_0
-# define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1)
-# define LOAD_ARGS_1(a1) \
- LOAD_ARGS_TYPES_1 (long int, a1)
-# define LOAD_REGS_1 \
- LOAD_REGS_TYPES_1 (long int, a1)
-
-# define LOAD_ARGS_TYPES_2(t1, a1, t2, a2) \
- t2 __arg2 = (t2) (a2); \
- LOAD_ARGS_TYPES_1 (t1, a1)
-# define LOAD_REGS_TYPES_2(t1, a1, t2, a2) \
- register t2 _a2 asm ("rsi") = __arg2; \
- LOAD_REGS_TYPES_1(t1, a1)
-# define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2)
-# define LOAD_ARGS_2(a1, a2) \
- LOAD_ARGS_TYPES_2 (long int, a1, long int, a2)
-# define LOAD_REGS_2 \
- LOAD_REGS_TYPES_2 (long int, a1, long int, a2)
-
-# define LOAD_ARGS_TYPES_3(t1, a1, t2, a2, t3, a3) \
- t3 __arg3 = (t3) (a3); \
- LOAD_ARGS_TYPES_2 (t1, a1, t2, a2)
-# define LOAD_REGS_TYPES_3(t1, a1, t2, a2, t3, a3) \
- register t3 _a3 asm ("rdx") = __arg3; \
- LOAD_REGS_TYPES_2(t1, a1, t2, a2)
-# define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3)
-# define LOAD_ARGS_3(a1, a2, a3) \
- LOAD_ARGS_TYPES_3 (long int, a1, long int, a2, long int, a3)
-# define LOAD_REGS_3 \
- LOAD_REGS_TYPES_3 (long int, a1, long int, a2, long int, a3)
-
-# define LOAD_ARGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4) \
- t4 __arg4 = (t4) (a4); \
- LOAD_ARGS_TYPES_3 (t1, a1, t2, a2, t3, a3)
-# define LOAD_REGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4) \
- register t4 _a4 asm ("r10") = __arg4; \
- LOAD_REGS_TYPES_3(t1, a2, t2, a2, t3, a3)
-# define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4)
-# define LOAD_ARGS_4(a1, a2, a3, a4) \
- LOAD_ARGS_TYPES_4 (long int, a1, long int, a2, long int, a3, \
- long int, a4)
-# define LOAD_REGS_4 \
- LOAD_REGS_TYPES_4 (long int, a1, long int, a2, long int, a3, \
- long int, a4)
-
-# define LOAD_ARGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
- t5 __arg5 = (t5) (a5); \
- LOAD_ARGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4)
-# define LOAD_REGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
- register t5 _a5 asm ("r8") = __arg5; \
- LOAD_REGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4)
-# define ASM_ARGS_5 ASM_ARGS_4, "r" (_a5)
-# define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
- LOAD_ARGS_TYPES_5 (long int, a1, long int, a2, long int, a3, \
- long int, a4, long int, a5)
-# define LOAD_REGS_5 \
- LOAD_REGS_TYPES_5 (long int, a1, long int, a2, long int, a3, \
- long int, a4, long int, a5)
-
-# define LOAD_ARGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
- t6 __arg6 = (t6) (a6); \
- LOAD_ARGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)
-# define LOAD_REGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
- register t6 _a6 asm ("r9") = __arg6; \
- LOAD_REGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)
-# define ASM_ARGS_6 ASM_ARGS_5, "r" (_a6)
-# define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \
- LOAD_ARGS_TYPES_6 (long int, a1, long int, a2, long int, a3, \
- long int, a4, long int, a5, long int, a6)
-# define LOAD_REGS_6 \
- LOAD_REGS_TYPES_6 (long int, a1, long int, a2, long int, a3, \
- long int, a4, long int, a5, long int, a6)
-
#endif /* __ASSEMBLER__ */
@@ -19,17 +19,19 @@
#include <sysdep.h>
/* Linux times system call returns 64-bit integer. */
-#undef INTERNAL_SYSCALL_NCS
-#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
- ({ \
- unsigned long long int resultvar; \
- LOAD_ARGS_##nr (args) \
- LOAD_REGS_##nr \
- asm volatile ( \
- "syscall\n\t" \
- : "=a" (resultvar) \
- : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
- (long long int) resultvar; })
+#undef internal_syscall1
+#define internal_syscall1(number, err, arg1) \
+({ \
+ unsigned long long int resultvar; \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long long int) resultvar; \
+})
#undef INTERNAL_SYSCALL_ERROR_P
#define INTERNAL_SYSCALL_ERROR_P(val, err) \