Message ID | 1495563960-669-2-git-send-email-adhemerval.zanella@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | Remove sysdep-cancel assembly macro | expand |
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. -- H.J.
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) \
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(-) -- 2.7.4