V2 [PATCH 1/2] Add SYSCALL_ULONG_ARG_[12] to pass long to syscall [BZ #25810]
Commit Message
X32 has 32-bit long and pointer with 64-bit off_t. Since x32 psABI
requires that pointers passed in registers must be zero-extended to
64bit, x32 can share many syscall interfaces with LP64. When a LP64
syscall with long and unsigned long arguments is used for x32, these
arguments must be properly extended to 64-bit. Otherwise if the upper
32 bits of the register have undefined value, such a syscall will be
rejected by kernel.
For syscalls implemented in assembly codes, 'U' is added to syscall
signature key letters for unsigned long. SYSCALL_ULONG_ARG_1 and
SYSCALL_ULONG_ARG_2 are passed to syscall-template.S for the first
and the second unsigned long arguments if PSEUDOS_HAVE_4_ARGS is
defined. They are used by x32 to zero-extend 32-bit arguments to
64 bits.
Tested on i386, x86-64 and x32 as well as with build-many-glibcs.py.
---
sysdeps/unix/make-syscalls.sh | 88 +++++++++++++++++++++
sysdeps/unix/syscall-template.S | 43 +++++++++-
sysdeps/unix/syscalls.list | 6 +-
sysdeps/unix/sysv/linux/syscalls.list | 14 ++--
sysdeps/unix/sysv/linux/x86_64/sysdep.h | 70 ++++++++++++----
sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h | 20 ++++-
6 files changed, 213 insertions(+), 28 deletions(-)
Comments
* H. J. Lu via Libc-alpha:
> diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh
> index c07626677f..4a28badea6 100644
> --- a/sysdeps/unix/make-syscalls.sh
> +++ b/sysdeps/unix/make-syscalls.sh
> @@ -30,6 +30,7 @@
> # P: optionally-NULL pointer to typed object (e.g., 3rd argument to sigaction)
> # s: non-NULL string (e.g., 1st arg to open)
> # S: optionally-NULL string (e.g., 1st arg to acct)
> +# U: unsigned long
Maybe this?
# U: unsigned long int (32-bit types are zero-extended to 64-bit types)
> # v: vararg scalar (e.g., optional 3rd arg to open)
> # V: byte-per-page vector (3rd arg to mincore)
> # W: wait status, optionally-NULL pointer to int (e.g., 2nd arg of wait4)
> @@ -184,6 +185,91 @@ while read file srcfile caller syscall args strong weak; do
> ?:?????????) nargs=9;;
> esac
>
> + # Derive the unsigned long arguments from the argument signature
“unsigned long int”
> + ulong_arg_1=0
> + ulong_arg_2=0
> + case $args in
> + ?:U*)
> + ulong_arg_1=1
> + case $args in
> + ?:UU*) ulong_arg_2=2;;
> + ?:U?U*) ulong_arg_2=3;;
> + ?:U??U*) ulong_arg_2=4;;
> + ?:U???U*) ulong_arg_2=5;;
> + ?:U????U*) ulong_arg_2=6;;
> + ?:U?????U*) ulong_arg_2=7;;
> + ?:U??????U*) ulong_arg_2=8;;
> + ?:U???????U) ulong_arg_2=9;;
> + esac
> + ;;
> + ?:????????U)
> + ulong_arg_1=9
> + ;;
> + esac
> +
I must say that I find this really, really ugly. We should rewrite
this in Python as soon as possible (in a separate patch).
You could try this instead:
$ echo U1U | grep -ob U
0:U
2:U
And maybe guard it with a case match, so that performance does not
suffer too much.
In any case, there should be an error check that covers the more
than-two-Us case.
> # Make sure only the first syscall rule is used, if multiple dirs
> # define the same syscall.
> echo ''
> @@ -245,6 +331,8 @@ while read file srcfile caller syscall args strong weak; do
> \$(make-target-directory)
> (echo '#define SYSCALL_NAME $syscall'; \\
> echo '#define SYSCALL_NARGS $nargs'; \\
> + echo '#define SYSCALL_ULONG_ARG_1 $ulong_arg_1'; \\
> + echo '#define SYSCALL_ULONG_ARG_2 $ulong_arg_2'; \\
Should this be conditional on whether $ulong_arg_1 and $ulong_arg_2
are empty? I think that might be less confusing.
Otherwise, the comment at the beginning should mention the special
value zero.
> echo '#define SYSCALL_SYMBOL $strong'; \\
> echo '#define SYSCALL_NOERRNO $noerrno'; \\
> echo '#define SYSCALL_ERRVAL $errval'; \\
> diff --git a/sysdeps/unix/syscall-template.S b/sysdeps/unix/syscall-template.S
> index cf6c7a58fb..0824a3c61e 100644
> --- a/sysdeps/unix/syscall-template.S
> +++ b/sysdeps/unix/syscall-template.S
> @@ -25,6 +25,10 @@
> defining a few macros:
> SYSCALL_NAME syscall name
> SYSCALL_NARGS number of arguments this call takes
> + SYSCALL_ULONG_ARG_1 the first unsigned long argument this
> + call takes
> + SYSCALL_ULONG_ARG_2 the second unsigned long argument this
> + call takes
“unsigned long int”
> SYSCALL_SYMBOL primary symbol name
> SYSCALL_NOERRNO 1 to define a no-errno version (see below)
> SYSCALL_ERRVAL 1 to define an error-value version (see below)
> @@ -44,9 +48,27 @@
> /* This indirection is needed so that SYMBOL gets macro-expanded. */
> #define syscall_hidden_def(SYMBOL) hidden_def (SYMBOL)
>
> -#define T_PSEUDO(SYMBOL, NAME, N) PSEUDO (SYMBOL, NAME, N)
> -#define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) PSEUDO_NOERRNO (SYMBOL, NAME, N)
> -#define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) PSEUDO_ERRVAL (SYMBOL, NAME, N)
> +/* If PSEUDOS_HAVE_4_ARGS is defined, PSEUDO macros have 4 arguments. */
> +#ifndef PSEUDOS_HAVE_4_ARGS
> +# undef SYSCALL_ULONG_ARG_1
> +# define SYSCALL_ULONG_ARG_1 0
> +#endif
PSEUDOS_HAVE_4_ARGS should be PSEUDOS_HAVE_ULONG_INDICES or something
like that. And a comment that briefly explains all the macro
arguments. (Not sure if T_PSEUDO is documented somewhere else
already.)
> diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
> index 01c4a0e6b1..e63a8b9d23 100644
> --- a/sysdeps/unix/syscalls.list
> +++ b/sysdeps/unix/syscalls.list
> @@ -37,11 +37,11 @@ kill - kill i:ii __kill kill
> link - link i:ss __link link
> listen - listen i:ii __listen listen
> lseek - lseek i:iii __libc_lseek __lseek lseek
> -madvise - madvise i:pii __madvise madvise
> +madvise - madvise i:pUi __madvise madvise
> mkdir - mkdir i:si __mkdir mkdir
> mmap - mmap b:aniiii __mmap mmap
> -mprotect - mprotect i:aii __mprotect mprotect
> -munmap - munmap i:ai __munmap munmap
> +mprotect - mprotect i:aUi __mprotect mprotect
> +munmap - munmap i:aU __munmap munmap
> open - open Ci:siv __libc_open __open open
> profil - profil i:piii __profil profil
> ptrace - ptrace i:iiii ptrace
What about read, readlink, write, etc.?
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
> index a37d520f86..b8a74ad2c2 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
> @@ -26,7 +26,25 @@
> #undef LO_HI_LONG
> #define LO_HI_LONG(val) (val)
>
> -#ifndef __ASSEMBLER__
> +#ifdef __ASSEMBLER__
> +# undef ZERO_EXTEND_1
> +# define ZERO_EXTEND_1 movl %edi, %edi;
> +# undef ZERO_EXTEND_2
> +# define ZERO_EXTEND_2 movl %esi, %esi;
> +# undef ZERO_EXTEND_3
> +# define ZERO_EXTEND_3 movl %edx, %edx;
> +# if SYSCALL_ULONG_ARG_1 == 4 || SYSCALL_ULONG_ARG_2 == 4
> +# undef DOARGS_4
> +# define DOARGS_4 movl %ecx, %r10d;
> +# else
> +# undef ZERO_EXTEND_4
> +# define ZERO_EXTEND_4 movl %r10d, %r10d;
> +# endif
> +# undef ZERO_EXTEND_5
> +# 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
The comment should come before the newly added changes, I think.
On 22/04/2020 07:42, Florian Weimer wrote:
> * H. J. Lu via Libc-alpha:
>
>> diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh
>> index c07626677f..4a28badea6 100644
>> --- a/sysdeps/unix/make-syscalls.sh
>> +++ b/sysdeps/unix/make-syscalls.sh
>> @@ -30,6 +30,7 @@
>> # P: optionally-NULL pointer to typed object (e.g., 3rd argument to sigaction)
>> # s: non-NULL string (e.g., 1st arg to open)
>> # S: optionally-NULL string (e.g., 1st arg to acct)
>> +# U: unsigned long
>
> Maybe this?
>
> # U: unsigned long int (32-bit types are zero-extended to 64-bit types)
>
>> # v: vararg scalar (e.g., optional 3rd arg to open)
>> # V: byte-per-page vector (3rd arg to mincore)
>> # W: wait status, optionally-NULL pointer to int (e.g., 2nd arg of wait4)
>> @@ -184,6 +185,91 @@ while read file srcfile caller syscall args strong weak; do
>> ?:?????????) nargs=9;;
>> esac
>>
>> + # Derive the unsigned long arguments from the argument signature
>
> “unsigned long int”
>
>> + ulong_arg_1=0
>> + ulong_arg_2=0
>> + case $args in
>> + ?:U*)
>> + ulong_arg_1=1
>> + case $args in
>> + ?:UU*) ulong_arg_2=2;;
>> + ?:U?U*) ulong_arg_2=3;;
>> + ?:U??U*) ulong_arg_2=4;;
>> + ?:U???U*) ulong_arg_2=5;;
>> + ?:U????U*) ulong_arg_2=6;;
>> + ?:U?????U*) ulong_arg_2=7;;
>> + ?:U??????U*) ulong_arg_2=8;;
>> + ?:U???????U) ulong_arg_2=9;;
>> + esac
>> + ;;
>
>> + ?:????????U)
>> + ulong_arg_1=9
>> + ;;
>> + esac
>> +
>
> I must say that I find this really, really ugly. We should rewrite
> this in Python as soon as possible (in a separate patch).
And I think we should make long term gold to just get rid of this
assembly macro and focus on automatic generation to a C code file
as well.
>
> You could try this instead:
>
> $ echo U1U | grep -ob U
> 0:U
> 2:U
>
> And maybe guard it with a case match, so that performance does not
> suffer too much.
>
> In any case, there should be an error check that covers the more
> than-two-Us case.
>
>
>> # Make sure only the first syscall rule is used, if multiple dirs
>> # define the same syscall.
>> echo ''
>> @@ -245,6 +331,8 @@ while read file srcfile caller syscall args strong weak; do
>> \$(make-target-directory)
>> (echo '#define SYSCALL_NAME $syscall'; \\
>> echo '#define SYSCALL_NARGS $nargs'; \\
>> + echo '#define SYSCALL_ULONG_ARG_1 $ulong_arg_1'; \\
>> + echo '#define SYSCALL_ULONG_ARG_2 $ulong_arg_2'; \\
>
> Should this be conditional on whether $ulong_arg_1 and $ulong_arg_2
> are empty? I think that might be less confusing.
>
> Otherwise, the comment at the beginning should mention the special
> value zero.
>
>> echo '#define SYSCALL_SYMBOL $strong'; \\
>> echo '#define SYSCALL_NOERRNO $noerrno'; \\
>> echo '#define SYSCALL_ERRVAL $errval'; \\
>> diff --git a/sysdeps/unix/syscall-template.S b/sysdeps/unix/syscall-template.S
>> index cf6c7a58fb..0824a3c61e 100644
>> --- a/sysdeps/unix/syscall-template.S
>> +++ b/sysdeps/unix/syscall-template.S
>> @@ -25,6 +25,10 @@
>> defining a few macros:
>> SYSCALL_NAME syscall name
>> SYSCALL_NARGS number of arguments this call takes
>> + SYSCALL_ULONG_ARG_1 the first unsigned long argument this
>> + call takes
>> + SYSCALL_ULONG_ARG_2 the second unsigned long argument this
>> + call takes
>
> “unsigned long int”
>
>> SYSCALL_SYMBOL primary symbol name
>> SYSCALL_NOERRNO 1 to define a no-errno version (see below)
>> SYSCALL_ERRVAL 1 to define an error-value version (see below)
>> @@ -44,9 +48,27 @@
>> /* This indirection is needed so that SYMBOL gets macro-expanded. */
>> #define syscall_hidden_def(SYMBOL) hidden_def (SYMBOL)
>>
>> -#define T_PSEUDO(SYMBOL, NAME, N) PSEUDO (SYMBOL, NAME, N)
>> -#define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) PSEUDO_NOERRNO (SYMBOL, NAME, N)
>> -#define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) PSEUDO_ERRVAL (SYMBOL, NAME, N)
>> +/* If PSEUDOS_HAVE_4_ARGS is defined, PSEUDO macros have 4 arguments. */
>> +#ifndef PSEUDOS_HAVE_4_ARGS
>> +# undef SYSCALL_ULONG_ARG_1
>> +# define SYSCALL_ULONG_ARG_1 0
>> +#endif
>
> PSEUDOS_HAVE_4_ARGS should be PSEUDOS_HAVE_ULONG_INDICES or something
> like that. And a comment that briefly explains all the macro
> arguments. (Not sure if T_PSEUDO is documented somewhere else
> already.)
>
>> diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
>> index 01c4a0e6b1..e63a8b9d23 100644
>> --- a/sysdeps/unix/syscalls.list
>> +++ b/sysdeps/unix/syscalls.list
>> @@ -37,11 +37,11 @@ kill - kill i:ii __kill kill
>> link - link i:ss __link link
>> listen - listen i:ii __listen listen
>> lseek - lseek i:iii __libc_lseek __lseek lseek
>> -madvise - madvise i:pii __madvise madvise
>> +madvise - madvise i:pUi __madvise madvise
>> mkdir - mkdir i:si __mkdir mkdir
>> mmap - mmap b:aniiii __mmap mmap
>> -mprotect - mprotect i:aii __mprotect mprotect
>> -munmap - munmap i:ai __munmap munmap
>> +mprotect - mprotect i:aUi __mprotect mprotect
>> +munmap - munmap i:aU __munmap munmap
>> open - open Ci:siv __libc_open __open open
>> profil - profil i:piii __profil profil
>> ptrace - ptrace i:iiii ptrace
>
> What about read, readlink, write, etc.?
>
>> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
>> index a37d520f86..b8a74ad2c2 100644
>> --- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
>> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
>> @@ -26,7 +26,25 @@
>> #undef LO_HI_LONG
>> #define LO_HI_LONG(val) (val)
>>
>> -#ifndef __ASSEMBLER__
>> +#ifdef __ASSEMBLER__
>> +# undef ZERO_EXTEND_1
>> +# define ZERO_EXTEND_1 movl %edi, %edi;
>> +# undef ZERO_EXTEND_2
>> +# define ZERO_EXTEND_2 movl %esi, %esi;
>> +# undef ZERO_EXTEND_3
>> +# define ZERO_EXTEND_3 movl %edx, %edx;
>> +# if SYSCALL_ULONG_ARG_1 == 4 || SYSCALL_ULONG_ARG_2 == 4
>> +# undef DOARGS_4
>> +# define DOARGS_4 movl %ecx, %r10d;
>> +# else
>> +# undef ZERO_EXTEND_4
>> +# define ZERO_EXTEND_4 movl %r10d, %r10d;
>> +# endif
>> +# undef ZERO_EXTEND_5
>> +# 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
>
> The comment should come before the newly added changes, I think.
>
On Wed, 22 Apr 2020, Adhemerval Zanella via Libc-alpha wrote:
> > I must say that I find this really, really ugly. We should rewrite
> > this in Python as soon as possible (in a separate patch).
>
> And I think we should make long term gold to just get rid of this
> assembly macro and focus on automatic generation to a C code file
> as well.
There are a couple of possible improvements in this area that might be in
tension here:
* Simplifying how the syscall arguments are specified. The reason there
are so many different letters is not because of anything relevant to
assembly code generation now, it's because of the old support for bounded
pointers (removed from GCC in 2002, actual substantive uses in the glibc
syscall generation code removed in
<https://sourceware.org/legacy-ml/libc-alpha/2013-01/msg00919.html>).
* Generating debug info for the automatically generated syscall
implementations. For that, the C code should have actual meaningful
argument types, not just a sequence of integers that has the right ABI
(but may not even have the right number of arguments, in cases where a
64-bit argument uses two letters for syscall arguments in the 32-bit
syscalls.list files).
What this suggests to me is that automatically-generated C code should get
actual argument types from the header files in some way, and in the cases
where header file information isn't sufficient (including syscalls not
declared in header files or with different arguments to the public C
function, etc.), using some sort of internal header to give the types
might be better than having complicated encodings in syscalls.list. Maybe
syscalls.list doesn't need much more information than the conventions for
return value / error handling and the *number* of arguments, if types can
be extracted from C headers.
On 22/04/2020 19:01, Joseph Myers wrote:
> On Wed, 22 Apr 2020, Adhemerval Zanella via Libc-alpha wrote:
>
>>> I must say that I find this really, really ugly. We should rewrite
>>> this in Python as soon as possible (in a separate patch).
>>
>> And I think we should make long term gold to just get rid of this
>> assembly macro and focus on automatic generation to a C code file
>> as well.
>
> There are a couple of possible improvements in this area that might be in
> tension here:
>
> * Simplifying how the syscall arguments are specified. The reason there
> are so many different letters is not because of anything relevant to
> assembly code generation now, it's because of the old support for bounded
> pointers (removed from GCC in 2002, actual substantive uses in the glibc
> syscall generation code removed in
> <https://sourceware.org/legacy-ml/libc-alpha/2013-01/msg00919.html>).
>
> * Generating debug info for the automatically generated syscall
> implementations. For that, the C code should have actual meaningful
> argument types, not just a sequence of integers that has the right ABI
> (but may not even have the right number of arguments, in cases where a
> 64-bit argument uses two letters for syscall arguments in the 32-bit
> syscalls.list files).
>
> What this suggests to me is that automatically-generated C code should get
> actual argument types from the header files in some way, and in the cases
> where header file information isn't sufficient (including syscalls not
> declared in header files or with different arguments to the public C
> function, etc.), using some sort of internal header to give the types
> might be better than having complicated encodings in syscalls.list. Maybe
> syscalls.list doesn't need much more information than the conventions for
> return value / error handling and the *number* of arguments, if types can
> be extracted from C headers.
My initial approach would be to extend the syscall argument definition
on syscall file description (syscalls.list) with all the required
information to synthesize the C implementation. It increases the
verbose required in the argument description, but I think it would
simpler than try infer from the header itself (which would require to
parse the it and the this information).
Something like, using wordsize-64 fstatfs syscalls.list entry:
fstatfs fstatfs [sys/statfs.h] [const char *, struct statfs64 *] [fstatfs64:w, __fstatfs64:w]
which would translate to:
#define fstatfs64 __redirect_fstatfs64
#define __fstatfs64 __redirect___fstatfs64
#include <sys/statfs.h>
#undef fstatfs64
#undef __fstatfs64
int
__fstatfs (int arg1, struct statfs *arg2)
{
return INLINE_SYSCALL_CALL (fstatfs, arg1, arg2);
}
weak_alias (__fstatfs, fstatfs)
weak_alias (__fstatfs, __fstatfs64)
weak_alias (__fstatfs, fstatfs64)
The alias would require some pre-defined logic to handle the LFS
alias for __OFF_T_MATCHES_OFF64_T (and I am not sure if this
example would be better handled in a C implementation in fact),
to handle internal hidden alias, and version.
@@ -30,6 +30,7 @@
# P: optionally-NULL pointer to typed object (e.g., 3rd argument to sigaction)
# s: non-NULL string (e.g., 1st arg to open)
# S: optionally-NULL string (e.g., 1st arg to acct)
+# U: unsigned long
# v: vararg scalar (e.g., optional 3rd arg to open)
# V: byte-per-page vector (3rd arg to mincore)
# W: wait status, optionally-NULL pointer to int (e.g., 2nd arg of wait4)
@@ -184,6 +185,91 @@ while read file srcfile caller syscall args strong weak; do
?:?????????) nargs=9;;
esac
+ # Derive the unsigned long arguments from the argument signature
+ ulong_arg_1=0
+ ulong_arg_2=0
+ case $args in
+ ?:U*)
+ ulong_arg_1=1
+ case $args in
+ ?:UU*) ulong_arg_2=2;;
+ ?:U?U*) ulong_arg_2=3;;
+ ?:U??U*) ulong_arg_2=4;;
+ ?:U???U*) ulong_arg_2=5;;
+ ?:U????U*) ulong_arg_2=6;;
+ ?:U?????U*) ulong_arg_2=7;;
+ ?:U??????U*) ulong_arg_2=8;;
+ ?:U???????U) ulong_arg_2=9;;
+ esac
+ ;;
+ ?:?U*)
+ ulong_arg_1=2
+ case $args in
+ ?:?UU*) ulong_arg_2=3;;
+ ?:?U?U*) ulong_arg_2=4;;
+ ?:?U??U*) ulong_arg_2=5;;
+ ?:?U???U*) ulong_arg_2=6;;
+ ?:?U????U*) ulong_arg_2=7;;
+ ?:?U?????U*) ulong_arg_2=8;;
+ ?:?U??????U) ulong_arg_2=9;;
+ esac
+ ;;
+ ?:??U*)
+ ulong_arg_1=3
+ case $args in
+ ?:??UU*) ulong_arg_2=4;;
+ ?:??U?U*) ulong_arg_2=5;;
+ ?:??U??U*) ulong_arg_2=6;;
+ ?:??U???U*) ulong_arg_2=7;;
+ ?:??U????U*) ulong_arg_2=8;;
+ ?:??U?????U) ulong_arg_2=9;;
+ esac
+ ;;
+ ?:???U*)
+ ulong_arg_1=4
+ case $args in
+ ?:???UU*) ulong_arg_2=5;;
+ ?:???U?U*) ulong_arg_2=6;;
+ ?:???U??U*) ulong_arg_2=7;;
+ ?:???U???U*) ulong_arg_2=8;;
+ ?:???U????U) ulong_arg_2=9;;
+ esac
+ ;;
+ ?:????U*)
+ ulong_arg_1=5
+ case $args in
+ ?:????UU*) ulong_arg_2=6;;
+ ?:????U?U*) ulong_arg_2=7;;
+ ?:????U??U*) ulong_arg_2=8;;
+ ?:????U???U) ulong_arg_2=9;;
+ esac
+ ;;
+ ?:?????U*)
+ ulong_arg_1=6
+ case $args in
+ ?:?????UU*) ulong_arg_2=7;;
+ ?:?????U?U*) ulong_arg_2=8;;
+ ?:?????U??U) ulong_arg_2=9;;
+ esac
+ ;;
+ ?:??????U*)
+ ulong_arg_1=7
+ case $args in
+ ?:??????UU*) ulong_arg_2=8;;
+ ?:??????U?U) ulong_arg_2=9;;
+ esac
+ ;;
+ ?:???????U*)
+ ulong_arg_1=8
+ case $args in
+ ?:??????UU) ulong_arg_2=9;;
+ esac
+ ;;
+ ?:????????U)
+ ulong_arg_1=9
+ ;;
+ esac
+
# Make sure only the first syscall rule is used, if multiple dirs
# define the same syscall.
echo ''
@@ -245,6 +331,8 @@ while read file srcfile caller syscall args strong weak; do
\$(make-target-directory)
(echo '#define SYSCALL_NAME $syscall'; \\
echo '#define SYSCALL_NARGS $nargs'; \\
+ echo '#define SYSCALL_ULONG_ARG_1 $ulong_arg_1'; \\
+ echo '#define SYSCALL_ULONG_ARG_2 $ulong_arg_2'; \\
echo '#define SYSCALL_SYMBOL $strong'; \\
echo '#define SYSCALL_NOERRNO $noerrno'; \\
echo '#define SYSCALL_ERRVAL $errval'; \\
@@ -25,6 +25,10 @@
defining a few macros:
SYSCALL_NAME syscall name
SYSCALL_NARGS number of arguments this call takes
+ SYSCALL_ULONG_ARG_1 the first unsigned long argument this
+ call takes
+ SYSCALL_ULONG_ARG_2 the second unsigned long argument this
+ call takes
SYSCALL_SYMBOL primary symbol name
SYSCALL_NOERRNO 1 to define a no-errno version (see below)
SYSCALL_ERRVAL 1 to define an error-value version (see below)
@@ -44,9 +48,27 @@
/* This indirection is needed so that SYMBOL gets macro-expanded. */
#define syscall_hidden_def(SYMBOL) hidden_def (SYMBOL)
-#define T_PSEUDO(SYMBOL, NAME, N) PSEUDO (SYMBOL, NAME, N)
-#define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) PSEUDO_NOERRNO (SYMBOL, NAME, N)
-#define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) PSEUDO_ERRVAL (SYMBOL, NAME, N)
+/* If PSEUDOS_HAVE_4_ARGS is defined, PSEUDO macros have 4 arguments. */
+#ifndef PSEUDOS_HAVE_4_ARGS
+# undef SYSCALL_ULONG_ARG_1
+# define SYSCALL_ULONG_ARG_1 0
+#endif
+
+#if SYSCALL_ULONG_ARG_1
+# define T_PSEUDO(SYMBOL, NAME, N, U1, U2) \
+ PSEUDO (SYMBOL, NAME, N, U1, U2)
+# define T_PSEUDO_NOERRNO(SYMBOL, NAME, N, U1, U2) \
+ PSEUDO_NOERRNO (SYMBOL, NAME, N, U1, U2)
+# define T_PSEUDO_ERRVAL(SYMBOL, NAME, N, U1, U2) \
+ PSEUDO_ERRVAL (SYMBOL, NAME, N, U1, U2)
+#else
+# define T_PSEUDO(SYMBOL, NAME, N) \
+ PSEUDO (SYMBOL, NAME, N)
+# define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) \
+ PSEUDO_NOERRNO (SYMBOL, NAME, N)
+# define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) \
+ PSEUDO_ERRVAL (SYMBOL, NAME, N)
+#endif
#define T_PSEUDO_END(SYMBOL) PSEUDO_END (SYMBOL)
#define T_PSEUDO_END_NOERRNO(SYMBOL) PSEUDO_END_NOERRNO (SYMBOL)
#define T_PSEUDO_END_ERRVAL(SYMBOL) PSEUDO_END_ERRVAL (SYMBOL)
@@ -56,7 +78,12 @@
/* This kind of system call stub never returns an error.
We return the return value register to the caller unexamined. */
+# if SYSCALL_ULONG_ARG_1
+T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS,
+ SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2)
+# else
T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
+# endif
ret_NOERRNO
T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL)
@@ -66,7 +93,12 @@ T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL)
value, or zero for success. We may massage the kernel's return value
to meet that ABI, but we never set errno here. */
+# if SYSCALL_ULONG_ARG_1
+T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS,
+ SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2)
+# else
T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
+# endif
ret_ERRVAL
T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL)
@@ -75,7 +107,12 @@ T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL)
/* This is a "normal" system call stub: if there is an error,
it returns -1 and sets errno. */
+# if SYSCALL_ULONG_ARG_1
+T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS,
+ SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2)
+# else
T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
+# endif
ret
T_PSEUDO_END (SYSCALL_SYMBOL)
@@ -37,11 +37,11 @@ kill - kill i:ii __kill kill
link - link i:ss __link link
listen - listen i:ii __listen listen
lseek - lseek i:iii __libc_lseek __lseek lseek
-madvise - madvise i:pii __madvise madvise
+madvise - madvise i:pUi __madvise madvise
mkdir - mkdir i:si __mkdir mkdir
mmap - mmap b:aniiii __mmap mmap
-mprotect - mprotect i:aii __mprotect mprotect
-munmap - munmap i:ai __munmap munmap
+mprotect - mprotect i:aUi __mprotect mprotect
+munmap - munmap i:aU __munmap munmap
open - open Ci:siv __libc_open __open open
profil - profil i:piii __profil profil
ptrace - ptrace i:iiii ptrace
@@ -32,12 +32,12 @@ ioperm - ioperm i:iii ioperm
iopl - iopl i:i iopl
klogctl EXTRA syslog i:isi klogctl
lchown - lchown i:sii __lchown lchown
-mincore - mincore i:anV mincore
-mlock - mlock i:bn mlock
+mincore - mincore i:aUV mincore
+mlock - mlock i:bU mlock
mlockall - mlockall i:i mlockall
-mount EXTRA mount i:sssip __mount mount
-mremap EXTRA mremap b:ainip __mremap mremap
-munlock - munlock i:ai munlock
+mount EXTRA mount i:sssUp __mount mount
+mremap EXTRA mremap b:aUUip __mremap mremap
+munlock - munlock i:aU munlock
munlockall - munlockall i: munlockall
nfsservctl EXTRA nfsservctl i:ipp __compat_nfsservctl nfsservctl@GLIBC_2.0:GLIBC_2.28
pipe - pipe i:f __pipe pipe
@@ -46,7 +46,7 @@ pivot_root EXTRA pivot_root i:ss pivot_root
prctl EXTRA prctl i:iiiii __prctl prctl
query_module EXTRA query_module i:sipip __compat_query_module query_module@GLIBC_2.0:GLIBC_2.23
quotactl EXTRA quotactl i:isip quotactl
-remap_file_pages - remap_file_pages i:piiii __remap_file_pages remap_file_pages
+remap_file_pages - remap_file_pages i:pUiUi __remap_file_pages remap_file_pages
sched_getp - sched_getparam i:ip __sched_getparam sched_getparam
sched_gets - sched_getscheduler i:i __sched_getscheduler sched_getscheduler
sched_primax - sched_get_priority_max i:i __sched_get_priority_max sched_get_priority_max
@@ -54,7 +54,7 @@ sched_primin - sched_get_priority_min i:i __sched_get_priority_min sched_get_pri
sched_setp - sched_setparam i:ip __sched_setparam sched_setparam
sched_sets - sched_setscheduler i:iip __sched_setscheduler sched_setscheduler
sched_yield - sched_yield i: __sched_yield sched_yield
-sendfile - sendfile i:iipi sendfile
+sendfile - sendfile i:iipU sendfile
sendfile64 - sendfile64 i:iipi sendfile64
setfsgid EXTRA setfsgid i:i setfsgid
setfsuid EXTRA setfsuid i:i setfsuid
@@ -57,13 +57,30 @@
# define SYSCALL_ERROR_LABEL syscall_error
# endif
+/* PSEUDO macros have 4 arguments. */
+# define PSEUDOS_HAVE_4_ARGS 1
+
+# ifndef SYSCALL_ULONG_ARG_1
+# define SYSCALL_ULONG_ARG_1 0
+# define SYSCALL_ULONG_ARG_2 0
+# endif
+
# undef PSEUDO
-# define PSEUDO(name, syscall_name, args) \
- .text; \
- ENTRY (name) \
- DO_CALL (syscall_name, args); \
- cmpq $-4095, %rax; \
+# if SYSCALL_ULONG_ARG_1
+# define PSEUDO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2); \
+ cmpq $-4095, %rax; \
jae SYSCALL_ERROR_LABEL
+# else
+# define PSEUDO(name, syscall_name, args) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args, 0, 0); \
+ cmpq $-4095, %rax; \
+ jae SYSCALL_ERROR_LABEL
+# endif
# undef PSEUDO_END
# define PSEUDO_END(name) \
@@ -71,10 +88,17 @@
END (name)
# undef PSEUDO_NOERRNO
-# define PSEUDO_NOERRNO(name, syscall_name, args) \
- .text; \
- ENTRY (name) \
- DO_CALL (syscall_name, args)
+# if SYSCALL_ULONG_ARG_1
+# define PSEUDO_NOERRNO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2)
+# else
+# define PSEUDO_NOERRNO(name, syscall_name, args) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args, 0, 0)
+# endif
# undef PSEUDO_END_NOERRNO
# define PSEUDO_END_NOERRNO(name) \
@@ -83,11 +107,19 @@
# define ret_NOERRNO ret
# undef PSEUDO_ERRVAL
-# define PSEUDO_ERRVAL(name, syscall_name, args) \
- .text; \
- ENTRY (name) \
- DO_CALL (syscall_name, args); \
+# if SYSCALL_ULONG_ARG_1
+# define PSEUDO_ERRVAL(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2); \
+ negq %rax
+# else
+# define PSEUDO_ERRVAL(name, syscall_name, args) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args, 0, 0); \
negq %rax
+# endif
# undef PSEUDO_END_ERRVAL
# define PSEUDO_END_ERRVAL(name) \
@@ -159,8 +191,10 @@
Syscalls of more than 6 arguments are not supported. */
# undef DO_CALL
-# define DO_CALL(syscall_name, args) \
+# define DO_CALL(syscall_name, args, ulong_arg_1, ulong_arg_2) \
DOARGS_##args \
+ ZERO_EXTEND_##ulong_arg_1 \
+ ZERO_EXTEND_##ulong_arg_2 \
movl $SYS_ify (syscall_name), %eax; \
syscall;
@@ -172,6 +206,14 @@
# define DOARGS_5 DOARGS_4
# define DOARGS_6 DOARGS_5
+# define ZERO_EXTEND_0 /* nothing */
+# define ZERO_EXTEND_1 /* nothing */
+# define ZERO_EXTEND_2 /* nothing */
+# define ZERO_EXTEND_3 /* nothing */
+# define ZERO_EXTEND_4 /* nothing */
+# define ZERO_EXTEND_5 /* nothing */
+# define ZERO_EXTEND_6 /* nothing */
+
#else /* !__ASSEMBLER__ */
/* Registers clobbered by syscall. */
@@ -26,7 +26,25 @@
#undef LO_HI_LONG
#define LO_HI_LONG(val) (val)
-#ifndef __ASSEMBLER__
+#ifdef __ASSEMBLER__
+# undef ZERO_EXTEND_1
+# define ZERO_EXTEND_1 movl %edi, %edi;
+# undef ZERO_EXTEND_2
+# define ZERO_EXTEND_2 movl %esi, %esi;
+# undef ZERO_EXTEND_3
+# define ZERO_EXTEND_3 movl %edx, %edx;
+# if SYSCALL_ULONG_ARG_1 == 4 || SYSCALL_ULONG_ARG_2 == 4
+# undef DOARGS_4
+# define DOARGS_4 movl %ecx, %r10d;
+# else
+# undef ZERO_EXTEND_4
+# define ZERO_EXTEND_4 movl %r10d, %r10d;
+# endif
+# undef ZERO_EXTEND_5
+# 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