V2 [PATCH 2/3] x32: Properly pass long to syscall [BZ #25810]
Florian Weimer
fw@deneb.enyo.de
Mon Apr 13 21:13:02 GMT 2020
* H. J. Lu via Libc-alpha:
>> > diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
>> > index 2b5cf0c0ea..67335c2a7f 100644
>> > --- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
>> > +++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
>> > @@ -44,6 +44,20 @@
>> > # define ZERO_EXTEND_5 movl %r8d, %r8d;
>> > # undef ZERO_EXTEND_6
>> > # define ZERO_EXTEND_6 movl %r9d, %r9d;
>> > +#else /*! __ASSEMBLER__ */
>> > +# undef ARGIFY
>> > +/* Enforce zero-extension for pointers and array system call arguments.
>> > + For integer types, extend to int64_t (the full register) using a
>> > + regular cast, resulting in zero or sign extension based on the
>> > + signedness of the original type. */
>> > +# define ARGIFY(X) \
>> > + ({ \
>> > + _Pragma ("GCC diagnostic push"); \
>> > + _Pragma ("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \
>> > + (__builtin_classify_type (X) == 5 \
>> > + ? (uintptr_t) (X) : (int64_t) (X)); \
>> > + _Pragma ("GCC diagnostic pop"); \
>> > + })
>> > #endif /* __ASSEMBLER__ */
>> >
>> > #endif /* linux/x86_64/x32/sysdep.h */
>>
>> I face a similar issue when fixing BZ#12683 for x32, and one possible
>> solution I found was:
>>
>> #define __SSC(__x) \
>> ({ \
>> __syscall_arg_t __arg = sizeof (1 ? (__x) : 0ULL) < 8 \
>> ? (unsigned long int) (uintptr_t)(__x) \
>> : (__syscall_arg_t) (__typeof__ ((__x) - (__x))) (__x); \
>> __arg; \
>> })
>
> This is similar to what I have checked in.
I think Adhemerval specifically meant the additional cast using
__typeof__ to suppress the warning (which I did not think of).
The _Pragma construct as written is a Clang porting hazard because it
causes the statement expression to return void (which is a Clang/GCC
discrepancy). Rather than introducing a temporary, using the
__typeof__ hack is probably the better way of fixing it.
More information about the Libc-alpha
mailing list