Message ID | 20200410212249.3529885-1-hjl.tools@gmail.com |
---|---|
State | New |
Headers | show |
Series | Add SYSCALL_LONG/SYSCALL_ULONG to pass long to syscall [BZ #25810] | expand |
* H. J. Lu via Libc-alpha: > For inline syscalls, SYSCALL_LONG and SYSCALL_ULONG are introduced as > wrappers for long and unsigned long arguments. Do the arguments have the correct types? Then I think you can do the adjustment in the guts of INLINE_SYSCALL machinery, and we do not have to remember to annotate each and every call site with the new macros. Changes to sysdeps/unix/make-syscalls.sh and syscalls.list appear unavoidable, but I think tget should be made to the global Linux version, not the x32 variant, so that other targets with the same issue can benefit from them. (I have not reviewed the make-syscalls.sh changes.) The core problem is that the psABI has a different calling convention than the syscall interface, right? This looks like a cautionary tale that one should not do this.
On Sat, Apr 11, 2020 at 3:01 AM Florian Weimer <fw@deneb.enyo.de> wrote: > > * H. J. Lu via Libc-alpha: > > > For inline syscalls, SYSCALL_LONG and SYSCALL_ULONG are introduced as > > wrappers for long and unsigned long arguments. > > Do the arguments have the correct types? Then I think you can do the Yes, they have correct types. But it is not the problem. Take this example: int munmap(void *addr, size_t length); The type of length is unsigned int (size_t) for x32 and is unsigned long (64bit) in kernel. We have no way to know the type which kernel expects. > adjustment in the guts of INLINE_SYSCALL machinery, and we do not have > to remember to annotate each and every call site with the new macros. > > Changes to sysdeps/unix/make-syscalls.sh and syscalls.list appear > unavoidable, but I think tget should be made to the global Linux > version, not the x32 variant, so that other targets with the same Will do. > issue can benefit from them. (I have not reviewed the > make-syscalls.sh changes.) > > The core problem is that the psABI has a different calling convention > than the syscall interface, right? This looks like a cautionary tale > that one should not do this. Something to consider for the new kernel interface.
* H. J. Lu: > On Sat, Apr 11, 2020 at 3:01 AM Florian Weimer <fw@deneb.enyo.de> wrote: >> >> * H. J. Lu via Libc-alpha: >> >> > For inline syscalls, SYSCALL_LONG and SYSCALL_ULONG are introduced as >> > wrappers for long and unsigned long arguments. >> >> Do the arguments have the correct types? Then I think you can do the > > Yes, they have correct types. But it is not the problem. Take this example: > > int munmap(void *addr, size_t length); > > The type of length is unsigned int (size_t) for x32 and is unsigned long > (64bit) in kernel. We have no way to know the type which kernel expects. Is it possible to extend all 32-bit arguments? Ot is this incorrect for negative int arguments, which must not have their upper bits set?
On Sat, Apr 11, 2020 at 7:45 AM Florian Weimer <fw@deneb.enyo.de> wrote: > > * H. J. Lu: > > > On Sat, Apr 11, 2020 at 3:01 AM Florian Weimer <fw@deneb.enyo.de> wrote: > >> > >> * H. J. Lu via Libc-alpha: > >> > >> > For inline syscalls, SYSCALL_LONG and SYSCALL_ULONG are introduced as > >> > wrappers for long and unsigned long arguments. > >> > >> Do the arguments have the correct types? Then I think you can do the > > > > Yes, they have correct types. But it is not the problem. Take this example: > > > > int munmap(void *addr, size_t length); > > > > The type of length is unsigned int (size_t) for x32 and is unsigned long > > (64bit) in kernel. We have no way to know the type which kernel expects. > > Is it possible to extend all 32-bit arguments? Ot is this incorrect > for negative int arguments, which must not have their upper bits set? ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); * If msgtyp is 0, then the first message in the queue is read. * If msgtyp is greater than 0, then the first message in the queue of type msgtyp is read, unless MSG_EXCEPT was specified in msgflg, in which case the first message in the queue of type not equal to msgtyp will be read. * If msgtyp is less than 0, then the first message in the queue with the lowest type less than or equal to the absolute value of msgtyp will be read. In this syscall, msgtyp should be sign-extended to 64-bit. H.J.
* H. J. Lu: > On Sat, Apr 11, 2020 at 7:45 AM Florian Weimer <fw@deneb.enyo.de> wrote: >> >> * H. J. Lu: >> >> > On Sat, Apr 11, 2020 at 3:01 AM Florian Weimer <fw@deneb.enyo.de> wrote: >> >> >> >> * H. J. Lu via Libc-alpha: >> >> >> >> > For inline syscalls, SYSCALL_LONG and SYSCALL_ULONG are introduced as >> >> > wrappers for long and unsigned long arguments. >> >> >> >> Do the arguments have the correct types? Then I think you can do the >> > >> > Yes, they have correct types. But it is not the problem. Take this example: >> > >> > int munmap(void *addr, size_t length); >> > >> > The type of length is unsigned int (size_t) for x32 and is unsigned long >> > (64bit) in kernel. We have no way to know the type which kernel expects. >> >> Is it possible to extend all 32-bit arguments? Ot is this incorrect >> for negative int arguments, which must not have their upper bits set? > > ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, > int msgflg); > > * If msgtyp is 0, then the first message in the queue is read. > > * If msgtyp is greater than 0, then the first message in the queue of > type msgtyp is read, unless MSG_EXCEPT was specified in msgflg, in > which case the first message in the queue of type not equal to msgtyp > will be read. > > * If msgtyp is less than 0, then the first message in the queue with > the lowest type less than or equal to the absolute value of msgtyp > will be read. > > In this syscall, msgtyp should be sign-extended to 64-bit. As far as I can tell, this is not a problematic exception.
On Sat, Apr 11, 2020 at 8:10 AM Florian Weimer <fw@deneb.enyo.de> wrote: > > * H. J. Lu: > > > On Sat, Apr 11, 2020 at 7:45 AM Florian Weimer <fw@deneb.enyo.de> wrote: > >> > >> * H. J. Lu: > >> > >> > On Sat, Apr 11, 2020 at 3:01 AM Florian Weimer <fw@deneb.enyo.de> wrote: > >> >> > >> >> * H. J. Lu via Libc-alpha: > >> >> > >> >> > For inline syscalls, SYSCALL_LONG and SYSCALL_ULONG are introduced as > >> >> > wrappers for long and unsigned long arguments. > >> >> > >> >> Do the arguments have the correct types? Then I think you can do the > >> > > >> > Yes, they have correct types. But it is not the problem. Take this example: > >> > > >> > int munmap(void *addr, size_t length); > >> > > >> > The type of length is unsigned int (size_t) for x32 and is unsigned long > >> > (64bit) in kernel. We have no way to know the type which kernel expects. > >> > >> Is it possible to extend all 32-bit arguments? Ot is this incorrect > >> for negative int arguments, which must not have their upper bits set? > > > > ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, > > int msgflg); > > > > * If msgtyp is 0, then the first message in the queue is read. > > > > * If msgtyp is greater than 0, then the first message in the queue of > > type msgtyp is read, unless MSG_EXCEPT was specified in msgflg, in > > which case the first message in the queue of type not equal to msgtyp > > will be read. > > > > * If msgtyp is less than 0, then the first message in the queue with > > the lowest type less than or equal to the absolute value of msgtyp > > will be read. > > > > In this syscall, msgtyp should be sign-extended to 64-bit. > > As far as I can tell, this is not a problematic exception. There is no need to extend int nor unsigned int passed to kernel. Only long and unsigned long are the problem.
* H. J. Lu: > On Sat, Apr 11, 2020 at 8:10 AM Florian Weimer <fw@deneb.enyo.de> wrote: >> >> * H. J. Lu: >> >> > On Sat, Apr 11, 2020 at 7:45 AM Florian Weimer <fw@deneb.enyo.de> wrote: >> >> >> >> * H. J. Lu: >> >> >> >> > On Sat, Apr 11, 2020 at 3:01 AM Florian Weimer <fw@deneb.enyo.de> wrote: >> >> >> >> >> >> * H. J. Lu via Libc-alpha: >> >> >> >> >> >> > For inline syscalls, SYSCALL_LONG and SYSCALL_ULONG are introduced as >> >> >> > wrappers for long and unsigned long arguments. >> >> >> >> >> >> Do the arguments have the correct types? Then I think you can do the >> >> > >> >> > Yes, they have correct types. But it is not the problem. Take this example: >> >> > >> >> > int munmap(void *addr, size_t length); >> >> > >> >> > The type of length is unsigned int (size_t) for x32 and is unsigned long >> >> > (64bit) in kernel. We have no way to know the type which kernel expects. >> >> >> >> Is it possible to extend all 32-bit arguments? Ot is this incorrect >> >> for negative int arguments, which must not have their upper bits set? >> > >> > ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, >> > int msgflg); >> > >> > * If msgtyp is 0, then the first message in the queue is read. >> > >> > * If msgtyp is greater than 0, then the first message in the queue of >> > type msgtyp is read, unless MSG_EXCEPT was specified in msgflg, in >> > which case the first message in the queue of type not equal to msgtyp >> > will be read. >> > >> > * If msgtyp is less than 0, then the first message in the queue with >> > the lowest type less than or equal to the absolute value of msgtyp >> > will be read. >> > >> > In this syscall, msgtyp should be sign-extended to 64-bit. >> >> As far as I can tell, this is not a problematic exception. > > There is no need to extend int nor unsigned int passed to kernel. > Only long and unsigned long are the problem. But is there harm in sign-extending int? I'm not convinced to annotate INLINE_SYSCALLs in this way just to avoid argument extensions for a subset of the x32 system calls.
On Sat, Apr 11, 2020 at 8:31 AM Florian Weimer <fw@deneb.enyo.de> wrote: > > * H. J. Lu: > > > On Sat, Apr 11, 2020 at 8:10 AM Florian Weimer <fw@deneb.enyo.de> wrote: > >> > >> * H. J. Lu: > >> > >> > On Sat, Apr 11, 2020 at 7:45 AM Florian Weimer <fw@deneb.enyo.de> wrote: > >> >> > >> >> * H. J. Lu: > >> >> > >> >> > On Sat, Apr 11, 2020 at 3:01 AM Florian Weimer <fw@deneb.enyo.de> wrote: > >> >> >> > >> >> >> * H. J. Lu via Libc-alpha: > >> >> >> > >> >> >> > For inline syscalls, SYSCALL_LONG and SYSCALL_ULONG are introduced as > >> >> >> > wrappers for long and unsigned long arguments. > >> >> >> > >> >> >> Do the arguments have the correct types? Then I think you can do the > >> >> > > >> >> > Yes, they have correct types. But it is not the problem. Take this example: > >> >> > > >> >> > int munmap(void *addr, size_t length); > >> >> > > >> >> > The type of length is unsigned int (size_t) for x32 and is unsigned long > >> >> > (64bit) in kernel. We have no way to know the type which kernel expects. > >> >> > >> >> Is it possible to extend all 32-bit arguments? Ot is this incorrect > >> >> for negative int arguments, which must not have their upper bits set? > >> > > >> > ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, > >> > int msgflg); > >> > > >> > * If msgtyp is 0, then the first message in the queue is read. > >> > > >> > * If msgtyp is greater than 0, then the first message in the queue of > >> > type msgtyp is read, unless MSG_EXCEPT was specified in msgflg, in > >> > which case the first message in the queue of type not equal to msgtyp > >> > will be read. > >> > > >> > * If msgtyp is less than 0, then the first message in the queue with > >> > the lowest type less than or equal to the absolute value of msgtyp > >> > will be read. > >> > > >> > In this syscall, msgtyp should be sign-extended to 64-bit. > >> > >> As far as I can tell, this is not a problematic exception. > > > > There is no need to extend int nor unsigned int passed to kernel. > > Only long and unsigned long are the problem. > > But is there harm in sign-extending int? > > I'm not convinced to annotate INLINE_SYSCALLs in this way just to > avoid argument extensions for a subset of the x32 system calls. What x32 needs are 1. Pointer arguments: no cast. 2. 64-bit integer arguments: no cast. 3. 32-bit integer arguments: extend to 64 bits. I am having a very hard time to do it in INLINE_SYSCALLs. If SYSCALL_LONG and SYSCALL_ULONG isn't an option, I can duplicate the whole set of these functions and convert them in x32 directory.
* H. J. Lu: > What x32 needs are > > 1. Pointer arguments: no cast. > 2. 64-bit integer arguments: no cast. > 3. 32-bit integer arguments: extend to 64 bits. > > I am having a very hard time to do it in INLINE_SYSCALLs. Is the problem avoiding sign extension on pointer values? I'm not sure if that is actually necessary to distinguish pointers and integer. It should be possible to lump pointers together with unsigned 32-bit arguments, like this: #define ARGIFY(X) \ (((__typeof__ (X)) 0 < (__typeof__ (X)) -1 && sizeof (X) == 4) ? (long long int) (uintptr_t) (X) \ : (long long int) (X)) The first branch is used for pointers and unsigned int values, resulting in zero extension. The other branch uses zero or sign extension, depending on the type of X.
On Sat, Apr 11, 2020 at 1:47 PM Florian Weimer <fw@deneb.enyo.de> wrote: > > * H. J. Lu: > > > What x32 needs are > > > > 1. Pointer arguments: no cast. > > 2. 64-bit integer arguments: no cast. > > 3. 32-bit integer arguments: extend to 64 bits. > > > > I am having a very hard time to do it in INLINE_SYSCALLs. > > Is the problem avoiding sign extension on pointer values? > > I'm not sure if that is actually necessary to distinguish pointers and > integer. It should be possible to lump pointers together with > unsigned 32-bit arguments, like this: > > #define ARGIFY(X) \ > (((__typeof__ (X)) 0 < (__typeof__ (X)) -1 && sizeof (X) == 4) > ? (long long int) (uintptr_t) (X) \ > : (long long int) (X)) > > The first branch is used for pointers and unsigned int values, > resulting in zero extension. The other branch uses zero or sign > extension, depending on the type of X. I tried variants of this. I got /usr/gcc-9.3.1-x32/bin/gcc -mx32 ../sysdeps/unix/sysv/linux/fexecve.c -c -std=gnu11 -fgnu89-inline -O2 -g -Wall -Wwrite-strings -Wundef -Werror -fmerge-all-constants -frounding-math -fno-stack-protector -Wstrict-prototypes -Wold-style-definition -fmath-errno -ftls-model=initial-exec -I../include -I/export/build/gnu/tools-build/glibc-x32-gitlab/build-x86_64-linux/posix -I/export/build/gnu/tools-build/glibc-x32-gitlab/build-x86_64-linux -I../sysdeps/unix/sysv/linux/x86_64/x32 -I../sysdeps/unix/sysv/linux/x86_64 -I../sysdeps/unix/sysv/linux/x86/include -I../sysdeps/unix/sysv/linux/x86 -I../sysdeps/x86/nptl -I../sysdeps/unix/sysv/linux/wordsize-64 -I../sysdeps/x86_64/nptl -I../sysdeps/unix/sysv/linux/include -I../sysdeps/unix/sysv/linux -I../sysdeps/nptl -I../sysdeps/pthread -I../sysdeps/gnu -I../sysdeps/unix/inet -I../sysdeps/unix/sysv -I../sysdeps/unix/x86_64 -I../sysdeps/unix -I../sysdeps/posix -I../sysdeps/x86_64/x32/fpu -I../sysdeps/x86_64/x32 -I../sysdeps/x86_64/fpu/multiarch -I../sysdeps/x86_64/fpu -I../sysdeps/x86/fpu -I../sysdeps/x86_64/multiarch -I../sysdeps/x86_64 -I../sysdeps/x86 -I../sysdeps/ieee754/float128 -I../sysdeps/ieee754/ldbl-96/include -I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64/wordsize-64 -I../sysdeps/ieee754/dbl-64 -I../sysdeps/ieee754/flt-32 -I../sysdeps/wordsize-32 -I../sysdeps/ieee754 -I../sysdeps/generic -I.. -I../libio -I. -D_LIBC_REENTRANT -include /export/build/gnu/tools-build/glibc-x32-gitlab/build-x86_64-linux/libc-modules.h -DMODULE_NAME=libc -include ../include/libc-symbols.h -DTOP_NAMESPACE=glibc -o /export/build/gnu/tools-build/glibc-x32-gitlab/build-x86_64-linux/posix/fexecve.o -MD -MP -MF /export/build/gnu/tools-build/glibc-x32-gitlab/build-x86_64-linux/posix/fexecve.o.dt -MT /export/build/gnu/tools-build/glibc-x32-gitlab/build-x86_64-linux/posix/fexecve.o nohup: ignoring input and appending output to 'nohup.out' gnu-tools-1:pts/5[130]> m nohup.out In file included from ../sysdeps/x86_64/nptl/tls.h:28, from ../include/errno.h:25, from ../sysdeps/unix/sysv/linux/fexecve.c:18: ../sysdeps/unix/sysv/linux/fexecve.c: In function ‘fexecve’: ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] 56 | : (long long int) (X)) | ^ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:313:29: note: in expansion of macro ‘ ARGIFY’ 313 | TYPEFY (arg4, __arg4) = ARGIFY (arg4); \ | ^~~~~~ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:222:2: note: in expansion of macro ‘i nternal_syscall5’ 222 | internal_syscall##nr (SYS_ify (name), args) | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/sysdep.h:43:23: note: in expansion of macro ‘INTERNAL _SYSCALL’ 43 | long int sc_ret = INTERNAL_SYSCALL (name, nr, args); \ | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/fexecve.c:43:3: note: in expansion of macro ‘INLINE_S YSCALL’ 43 | INLINE_SYSCALL (execveat, 5, fd, "", &argv[0], &envp[0], AT_EMPTY_PATH gnu-tools-1:pts/5[131]> cat nohup.out In file included from ../sysdeps/x86_64/nptl/tls.h:28, from ../include/errno.h:25, from ../sysdeps/unix/sysv/linux/fexecve.c:18: ../sysdeps/unix/sysv/linux/fexecve.c: In function ‘fexecve’: ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] 56 | : (long long int) (X)) | ^ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:313:29: note: in expansion of macro ‘ARGIFY’ 313 | TYPEFY (arg4, __arg4) = ARGIFY (arg4); \ | ^~~~~~ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:222:2: note: in expansion of macro ‘internal_syscall5’ 222 | internal_syscall##nr (SYS_ify (name), args) | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/sysdep.h:43:23: note: in expansion of macro ‘INTERNAL_SYSCALL’ 43 | long int sc_ret = INTERNAL_SYSCALL (name, nr, args); \ | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/fexecve.c:43:3: note: in expansion of macro ‘INLINE_SYSCALL’ 43 | INLINE_SYSCALL (execveat, 5, fd, "", &argv[0], &envp[0], AT_EMPTY_PATH); | ^~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] 56 | : (long long int) (X)) | ^ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:314:29: note: in expansion of macro ‘ARGIFY’ 314 | TYPEFY (arg3, __arg3) = ARGIFY (arg3); \ | ^~~~~~ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:222:2: note: in expansion of macro ‘internal_syscall5’ 222 | internal_syscall##nr (SYS_ify (name), args) | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/sysdep.h:43:23: note: in expansion of macro ‘INTERNAL_SYSCALL’ 43 | long int sc_ret = INTERNAL_SYSCALL (name, nr, args); \ | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/fexecve.c:43:3: note: in expansion of macro ‘INLINE_SYSCALL’ 43 | INLINE_SYSCALL (execveat, 5, fd, "", &argv[0], &envp[0], AT_EMPTY_PATH); | ^~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:54:5: error: cast specifies array type 54 | (((__typeof__ (X)) 0 < (__typeof__ (X)) -1 && sizeof (X) == 4) \ | ^ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:315:29: note: in expansion of macro ‘ARGIFY’ 315 | TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ | ^~~~~~ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:222:2: note: in expansion of macro ‘internal_syscall5’ 222 | internal_syscall##nr (SYS_ify (name), args) | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/sysdep.h:43:23: note: in expansion of macro ‘INTERNAL_SYSCALL’ 43 | long int sc_ret = INTERNAL_SYSCALL (name, nr, args); \ | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/fexecve.c:43:3: note: in expansion of macro ‘INLINE_SYSCALL’ 43 | INLINE_SYSCALL (execveat, 5, fd, "", &argv[0], &envp[0], AT_EMPTY_PATH); | ^~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:54:26: error: cast specifies array type 54 | (((__typeof__ (X)) 0 < (__typeof__ (X)) -1 && sizeof (X) == 4) \ | ^ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:315:29: note: in expansion of macro ‘ARGIFY’ 315 | TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ | ^~~~~~ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:222:2: note: in expansion of macro ‘internal_syscall5’ 222 | internal_syscall##nr (SYS_ify (name), args) | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/sysdep.h:43:23: note: in expansion of macro ‘INTERNAL_SYSCALL’ 43 | long int sc_ret = INTERNAL_SYSCALL (name, nr, args); \ | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/fexecve.c:43:3: note: in expansion of macro ‘INLINE_SYSCALL’ 43 | INLINE_SYSCALL (execveat, 5, fd, "", &argv[0], &envp[0], AT_EMPTY_PATH); | ^~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] 56 | : (long long int) (X)) | ^ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:315:29: note: in expansion of macro ‘ARGIFY’ 315 | TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ | ^~~~~~ ../sysdeps/unix/sysv/linux/x86_64/sysdep.h:222:2: note: in expansion of macro ‘internal_syscall5’ 222 | internal_syscall##nr (SYS_ify (name), args) | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/sysdep.h:43:23: note: in expansion of macro ‘INTERNAL_SYSCALL’ 43 | long int sc_ret = INTERNAL_SYSCALL (name, nr, args); \ | ^~~~~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/fexecve.c:43:3: note: in expansion of macro ‘INLINE_SYSCALL’ 43 | INLINE_SYSCALL (execveat, 5, fd, "", &argv[0], &envp[0], AT_EMPTY_PATH); | ^~~~~~~~~~~~~~
* H. J. Lu: > nohup: ignoring input and appending output to 'nohup.out' > gnu-tools-1:pts/5[130]> m nohup.out > In file included from ../sysdeps/x86_64/nptl/tls.h:28, > from ../include/errno.h:25, > from ../sysdeps/unix/sysv/linux/fexecve.c:18: > ../sysdeps/unix/sysv/linux/fexecve.c: In function ‘fexecve’: > ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to > integer of different size [-Werror=pointer-to-int-cast] > 56 | : (long long int) (X)) > | ^ Please try something like this: #define ARGIFY(X) \ ({ \ _Pragma ("GCC diagnostic push"); \ _Pragma ("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \ (sizeof (X) <= 4 && (__typeof__ (X)) 0 < (__typeof__ (X)) -1) \ ? (long long int) (unsigned long int) (X) \ : (long int long) (X); \ _Pragma ("GCC diagnostic pop"); \ }) (__builtin_choose_expr does not work because it only suppresses errors, not warnings.) It may not work in some cases because (__typeof__ (X)) 0 is not valid if X is an array.
On Sun, Apr 12, 2020 at 1:44 PM Florian Weimer <fw@deneb.enyo.de> wrote: > > * H. J. Lu: > > > nohup: ignoring input and appending output to 'nohup.out' > > gnu-tools-1:pts/5[130]> m nohup.out > > In file included from ../sysdeps/x86_64/nptl/tls.h:28, > > from ../include/errno.h:25, > > from ../sysdeps/unix/sysv/linux/fexecve.c:18: > > ../sysdeps/unix/sysv/linux/fexecve.c: In function ‘fexecve’: > > ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to > > integer of different size [-Werror=pointer-to-int-cast] > > 56 | : (long long int) (X)) > > | ^ > > Please try something like this: > > #define ARGIFY(X) \ > ({ \ > _Pragma ("GCC diagnostic push"); \ > _Pragma ("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \ > (sizeof (X) <= 4 && (__typeof__ (X)) 0 < (__typeof__ (X)) -1) \ > ? (long long int) (unsigned long int) (X) \ > : (long int long) (X); \ > _Pragma ("GCC diagnostic pop"); \ > }) > > (__builtin_choose_expr does not work because it only suppresses > errors, not warnings.) > > It may not work in some cases because (__typeof__ (X)) 0 is not valid > if X is an array. It compiles, but doesn't work. We need to cast the input of #define TYPEFY(X, name) __typeof__ ((X) - (X)) name #define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) to unsigned long long.
* H. J. Lu: > On Sun, Apr 12, 2020 at 1:44 PM Florian Weimer <fw@deneb.enyo.de> wrote: >> >> * H. J. Lu: >> >> > nohup: ignoring input and appending output to 'nohup.out' >> > gnu-tools-1:pts/5[130]> m nohup.out >> > In file included from ../sysdeps/x86_64/nptl/tls.h:28, >> > from ../include/errno.h:25, >> > from ../sysdeps/unix/sysv/linux/fexecve.c:18: >> > ../sysdeps/unix/sysv/linux/fexecve.c: In function ‘fexecve’: >> > ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to >> > integer of different size [-Werror=pointer-to-int-cast] >> > 56 | : (long long int) (X)) >> > | ^ >> >> Please try something like this: >> >> #define ARGIFY(X) \ >> ({ \ >> _Pragma ("GCC diagnostic push"); \ >> _Pragma ("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \ >> (sizeof (X) <= 4 && (__typeof__ (X)) 0 < (__typeof__ (X)) -1) \ >> ? (long long int) (unsigned long int) (X) \ >> : (long int long) (X); \ >> _Pragma ("GCC diagnostic pop"); \ >> }) >> >> (__builtin_choose_expr does not work because it only suppresses >> errors, not warnings.) >> >> It may not work in some cases because (__typeof__ (X)) 0 is not valid >> if X is an array. > > It compiles, but doesn't work. We need to cast the input of > > #define TYPEFY(X, name) __typeof__ ((X) - (X)) name > #define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) > > to unsigned long long. Why does it fail? Are there any arguments besides pointers which must not be sign-extended to 64 bits? According to syscall(2), I don't think, so I still think we can make this work if we just avoid sign-extending pointers.
On Mon, Apr 13, 2020 at 1:23 AM Florian Weimer <fw@deneb.enyo.de> wrote: > > * H. J. Lu: > > > On Sun, Apr 12, 2020 at 1:44 PM Florian Weimer <fw@deneb.enyo.de> wrote: > >> > >> * H. J. Lu: > >> > >> > nohup: ignoring input and appending output to 'nohup.out' > >> > gnu-tools-1:pts/5[130]> m nohup.out > >> > In file included from ../sysdeps/x86_64/nptl/tls.h:28, > >> > from ../include/errno.h:25, > >> > from ../sysdeps/unix/sysv/linux/fexecve.c:18: > >> > ../sysdeps/unix/sysv/linux/fexecve.c: In function ‘fexecve’: > >> > ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to > >> > integer of different size [-Werror=pointer-to-int-cast] > >> > 56 | : (long long int) (X)) > >> > | ^ > >> > >> Please try something like this: > >> > >> #define ARGIFY(X) \ > >> ({ \ > >> _Pragma ("GCC diagnostic push"); \ > >> _Pragma ("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \ > >> (sizeof (X) <= 4 && (__typeof__ (X)) 0 < (__typeof__ (X)) -1) \ > >> ? (long long int) (unsigned long int) (X) \ > >> : (long int long) (X); \ > >> _Pragma ("GCC diagnostic pop"); \ > >> }) > >> > >> (__builtin_choose_expr does not work because it only suppresses > >> errors, not warnings.) > >> > >> It may not work in some cases because (__typeof__ (X)) 0 is not valid > >> if X is an array. > > > > It compiles, but doesn't work. We need to cast the input of > > > > #define TYPEFY(X, name) __typeof__ ((X) - (X)) name > > #define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) > > > > to unsigned long long. > > Why does it fail? Are there any arguments besides pointers which must > not be sign-extended to 64 bits? According to syscall(2), I don't > think, so I still think we can make this work if we just avoid > sign-extending pointers. Here is a simple testcase: --- #define TYPEFY(X, name) __typeof__ ((X) - (X)) name #define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) int foo (unsigned int 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" (0xff), "r" (_a1) : "memory"); return resultvar; } --- When compiled with -O2 -mx32, we need "movl %edi, %edi" before syscall
On Mon, Apr 13, 2020 at 4:44 AM H.J. Lu <hjl.tools@gmail.com> wrote: > > On Mon, Apr 13, 2020 at 1:23 AM Florian Weimer <fw@deneb.enyo.de> wrote: > > > > * H. J. Lu: > > > > > On Sun, Apr 12, 2020 at 1:44 PM Florian Weimer <fw@deneb.enyo.de> wrote: > > >> > > >> * H. J. Lu: > > >> > > >> > nohup: ignoring input and appending output to 'nohup.out' > > >> > gnu-tools-1:pts/5[130]> m nohup.out > > >> > In file included from ../sysdeps/x86_64/nptl/tls.h:28, > > >> > from ../include/errno.h:25, > > >> > from ../sysdeps/unix/sysv/linux/fexecve.c:18: > > >> > ../sysdeps/unix/sysv/linux/fexecve.c: In function ‘fexecve’: > > >> > ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to > > >> > integer of different size [-Werror=pointer-to-int-cast] > > >> > 56 | : (long long int) (X)) > > >> > | ^ > > >> > > >> Please try something like this: > > >> > > >> #define ARGIFY(X) \ > > >> ({ \ > > >> _Pragma ("GCC diagnostic push"); \ > > >> _Pragma ("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \ > > >> (sizeof (X) <= 4 && (__typeof__ (X)) 0 < (__typeof__ (X)) -1) \ > > >> ? (long long int) (unsigned long int) (X) \ > > >> : (long int long) (X); \ > > >> _Pragma ("GCC diagnostic pop"); \ > > >> }) > > >> > > >> (__builtin_choose_expr does not work because it only suppresses > > >> errors, not warnings.) > > >> > > >> It may not work in some cases because (__typeof__ (X)) 0 is not valid > > >> if X is an array. > > > > > > It compiles, but doesn't work. We need to cast the input of > > > > > > #define TYPEFY(X, name) __typeof__ ((X) - (X)) name > > > #define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) > > > > > > to unsigned long long. > > > > Why does it fail? Are there any arguments besides pointers which must > > not be sign-extended to 64 bits? According to syscall(2), I don't > > think, so I still think we can make this work if we just avoid > > sign-extending pointers. > > Here is a simple testcase: > > --- > #define TYPEFY(X, name) __typeof__ ((X) - (X)) name > #define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) > > int > foo (unsigned int 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" (0xff), "r" (_a1) > : "memory"); > return resultvar; > } > --- > > When compiled with -O2 -mx32, we need "movl %edi, %edi" before > syscall > I may have found a solution.
On Mon, Apr 13, 2020 at 4:54 AM H.J. Lu <hjl.tools@gmail.com> wrote: > > On Mon, Apr 13, 2020 at 4:44 AM H.J. Lu <hjl.tools@gmail.com> wrote: > > > > On Mon, Apr 13, 2020 at 1:23 AM Florian Weimer <fw@deneb.enyo.de> wrote: > > > > > > * H. J. Lu: > > > > > > > On Sun, Apr 12, 2020 at 1:44 PM Florian Weimer <fw@deneb.enyo.de> wrote: > > > >> > > > >> * H. J. Lu: > > > >> > > > >> > nohup: ignoring input and appending output to 'nohup.out' > > > >> > gnu-tools-1:pts/5[130]> m nohup.out > > > >> > In file included from ../sysdeps/x86_64/nptl/tls.h:28, > > > >> > from ../include/errno.h:25, > > > >> > from ../sysdeps/unix/sysv/linux/fexecve.c:18: > > > >> > ../sysdeps/unix/sysv/linux/fexecve.c: In function ‘fexecve’: > > > >> > ../sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h:56:6: error: cast from pointer to > > > >> > integer of different size [-Werror=pointer-to-int-cast] > > > >> > 56 | : (long long int) (X)) > > > >> > | ^ > > > >> > > > >> Please try something like this: > > > >> > > > >> #define ARGIFY(X) \ > > > >> ({ \ > > > >> _Pragma ("GCC diagnostic push"); \ > > > >> _Pragma ("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \ > > > >> (sizeof (X) <= 4 && (__typeof__ (X)) 0 < (__typeof__ (X)) -1) \ > > > >> ? (long long int) (unsigned long int) (X) \ > > > >> : (long int long) (X); \ > > > >> _Pragma ("GCC diagnostic pop"); \ > > > >> }) > > > >> > > > >> (__builtin_choose_expr does not work because it only suppresses > > > >> errors, not warnings.) > > > >> > > > >> It may not work in some cases because (__typeof__ (X)) 0 is not valid > > > >> if X is an array. > > > > > > > > It compiles, but doesn't work. We need to cast the input of > > > > > > > > #define TYPEFY(X, name) __typeof__ ((X) - (X)) name > > > > #define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) > > > > > > > > to unsigned long long. > > > > > > Why does it fail? Are there any arguments besides pointers which must > > > not be sign-extended to 64 bits? According to syscall(2), I don't > > > think, so I still think we can make this work if we just avoid > > > sign-extending pointers. > > > > Here is a simple testcase: > > > > --- > > #define TYPEFY(X, name) __typeof__ ((X) - (X)) name > > #define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) > > > > int > > foo (unsigned int 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" (0xff), "r" (_a1) > > : "memory"); > > return resultvar; > > } > > --- > > > > When compiled with -O2 -mx32, we need "movl %edi, %edi" before > > syscall > > > > I may have found a solution. A new patch set is posted at https://sourceware.org/pipermail/libc-alpha/2020-April/112748.html
diff --git a/misc/Makefile b/misc/Makefile index b8fed5783d..67c5237f97 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -87,7 +87,7 @@ tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \ tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \ tst-preadvwritev2 tst-preadvwritev64v2 tst-warn-wide \ tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt \ - tst-mntent-autofs + tst-mntent-autofs tst-syscalls # Tests which need libdl. ifeq (yes,$(build-shared)) diff --git a/misc/tst-syscalls.c b/misc/tst-syscalls.c new file mode 100644 index 0000000000..d07f03633b --- /dev/null +++ b/misc/tst-syscalls.c @@ -0,0 +1,146 @@ +/* Test for syscall interfaces. + Copyright (C) 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <support/check.h> +#include <support/xunistd.h> + +struct Array +{ + size_t length; + void *ptr; +}; + +static int error_count; + +__attribute__ ((noclone, noinline)) +struct Array +allocate (size_t bytes) +{ + if (!bytes) + return __extension__ (struct Array) {0, 0}; + + void *p = mmap (0x0, bytes, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (p == MAP_FAILED) + return __extension__ (struct Array) {0, 0}; + + return __extension__ (struct Array) {bytes, p}; +} + +__attribute__ ((noclone, noinline)) +void +deallocate (struct Array b) +{ + if (b.length && munmap (b.ptr, b.length)) + { + printf ("munmap error: %m\n"); + error_count++; + } +} + +__attribute__ ((noclone, noinline)) +void * +do_mmap (void *addr, size_t length) +{ + return mmap (addr, length, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); +} + +__attribute__ ((noclone, noinline)) +void * +reallocate (struct Array b) +{ + if (b.length) + return do_mmap (b.ptr, b.length); + return NULL; +} + +__attribute__ ((noclone, noinline)) +void +protect (struct Array b) +{ + if (b.length) + { + if (mprotect (b.ptr, b.length, + PROT_READ | PROT_WRITE | PROT_EXEC)) + { + printf ("mprotect error: %m\n"); + error_count++; + } + } +} + +__attribute__ ((noclone, noinline)) +ssize_t +do_read (int fd, void *ptr, struct Array b) +{ + if (b.length) + return read (fd, ptr, b.length); + return 0; +} + +__attribute__ ((noclone, noinline)) +ssize_t +do_write (int fd, void *ptr, struct Array b) +{ + if (b.length) + return write (fd, ptr, b.length); + return 0; +} + +static int +do_test (void) +{ + struct Array array; + + array = allocate (1); + protect (array); + deallocate (array); + void *p = reallocate (array); + if (p == MAP_FAILED) + { + printf ("mmap error: %m\n"); + error_count++; + } + array.ptr = p; + protect (array); + deallocate (array); + + int fd = xopen ("/dev/null", O_RDWR, 0); + char buf[2]; + array.ptr = buf; + if (do_read (fd, array.ptr, array) == -1) + { + printf ("read error: %m\n"); + error_count++; + } + if (do_write (fd, array.ptr, array) == -1) + { + printf ("write error: %m\n"); + error_count++; + } + xclose (fd); + + return error_count ? EXIT_FAILURE : EXIT_SUCCESS; +} + +#include <support/test-driver.c> diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh index c07626677f..52cf7e2f16 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 # 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 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'; \\ diff --git a/sysdeps/unix/syscall-template.S b/sysdeps/unix/syscall-template.S index cf6c7a58fb..e8d6d59b15 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 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,21 @@ /* 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 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 +72,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 +87,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 +101,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) diff --git a/sysdeps/unix/sysv/linux/copy_file_range.c b/sysdeps/unix/sysv/linux/copy_file_range.c index a73c89f079..50487df77c 100644 --- a/sysdeps/unix/sysv/linux/copy_file_range.c +++ b/sysdeps/unix/sysv/linux/copy_file_range.c @@ -26,5 +26,5 @@ copy_file_range (int infd, __off64_t *pinoff, size_t length, unsigned int flags) { return SYSCALL_CANCEL (copy_file_range, infd, pinoff, outfd, poutoff, - length, flags); + SYSCALL_ULONG (length), flags); } diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c index fabc4bb8cc..d228467edf 100644 --- a/sysdeps/unix/sysv/linux/getcwd.c +++ b/sysdeps/unix/sysv/linux/getcwd.c @@ -75,7 +75,7 @@ __getcwd (char *buf, size_t size) int retval; - retval = INLINE_SYSCALL (getcwd, 2, path, alloc_size); + retval = INLINE_SYSCALL (getcwd, 2, path, SYSCALL_ULONG (alloc_size)); if (retval > 0 && path[0] == '/') { #ifndef NO_ALLOCATION diff --git a/sysdeps/unix/sysv/linux/getdents.c b/sysdeps/unix/sysv/linux/getdents.c index a76be2e5e7..fc8da0caae 100644 --- a/sysdeps/unix/sysv/linux/getdents.c +++ b/sysdeps/unix/sysv/linux/getdents.c @@ -53,7 +53,8 @@ __getdents (int fd, void *buf0, size_t nbytes) if (nbytes <= sizeof (struct dirent)) kbuf = (void*) kbuftmp; - retval = INLINE_SYSCALL_CALL (getdents64, fd, kbuf, kbytes); + retval = INLINE_SYSCALL_CALL (getdents64, fd, kbuf, + SYSCALL_ULONG (kbytes)); if (retval == -1) return -1; diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c index 75892c2823..63c89c7d60 100644 --- a/sysdeps/unix/sysv/linux/getdents64.c +++ b/sysdeps/unix/sysv/linux/getdents64.c @@ -29,7 +29,8 @@ __getdents64 (int fd, void *buf, size_t nbytes) checks in the kernel use an int type. */ if (nbytes > INT_MAX) nbytes = INT_MAX; - return INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes); + return INLINE_SYSCALL_CALL (getdents64, fd, buf, + SYSCALL_ULONG (nbytes)); } libc_hidden_def (__getdents64) weak_alias (__getdents64, getdents64) @@ -74,7 +75,8 @@ __old_getdents64 (int fd, char *buf, size_t nbytes) <= __alignof__ (struct dirent64), "alignment of __old_dirent64 is larger than dirent64"); - ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes); + ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, + SYSCALL_ULONG (nbytes)); if (retval > 0) { /* This is the marker for the first entry. Offset 0 is reserved diff --git a/sysdeps/unix/sysv/linux/getentropy.c b/sysdeps/unix/sysv/linux/getentropy.c index 2f3a4e4692..f99d2783a1 100644 --- a/sysdeps/unix/sysv/linux/getentropy.c +++ b/sysdeps/unix/sysv/linux/getentropy.c @@ -41,7 +41,9 @@ getentropy (void *buffer, size_t length) while (buffer < end) { /* NB: No cancellation point. */ - ssize_t bytes = INLINE_SYSCALL_CALL (getrandom, buffer, end - buffer, 0); + ssize_t bytes = INLINE_SYSCALL_CALL (getrandom, buffer, + SYSCALL_ULONG (end - buffer), + 0); if (bytes < 0) { if (errno == EINTR) diff --git a/sysdeps/unix/sysv/linux/getrandom.c b/sysdeps/unix/sysv/linux/getrandom.c index 63b8d36bf4..8008890939 100644 --- a/sysdeps/unix/sysv/linux/getrandom.c +++ b/sysdeps/unix/sysv/linux/getrandom.c @@ -26,7 +26,8 @@ ssize_t __getrandom (void *buffer, size_t length, unsigned int flags) { - return SYSCALL_CANCEL (getrandom, buffer, length, flags); + return SYSCALL_CANCEL (getrandom, buffer, SYSCALL_ULONG (length), + flags); } libc_hidden_def (__getrandom) weak_alias (__getrandom, getrandom) diff --git a/sysdeps/unix/sysv/linux/mlock2.c b/sysdeps/unix/sysv/linux/mlock2.c index e52f43f35c..599ed5c351 100644 --- a/sysdeps/unix/sysv/linux/mlock2.c +++ b/sysdeps/unix/sysv/linux/mlock2.c @@ -23,11 +23,13 @@ int mlock2 (const void *addr, size_t length, unsigned int flags) { #ifdef __ASSUME_MLOCK2 - return INLINE_SYSCALL_CALL (mlock2, addr, length, flags); + return INLINE_SYSCALL_CALL (mlock2, addr, SYSCALL_ULONG (length), + flags); #else if (flags == 0) - return INLINE_SYSCALL_CALL (mlock, addr, length); - int ret = INLINE_SYSCALL_CALL (mlock2, addr, length, flags); + return INLINE_SYSCALL_CALL (mlock, addr, SYSCALL_ULONG (length)); + int ret = INLINE_SYSCALL_CALL (mlock2, addr, SYSCALL_ULONG (length), + flags); if (ret == 0 || errno != ENOSYS) return ret; /* Treat the missing system call as an invalid (non-zero) flag diff --git a/sysdeps/unix/sysv/linux/mmap64.c b/sysdeps/unix/sysv/linux/mmap64.c index 8074deb466..7efe7f171d 100644 --- a/sysdeps/unix/sysv/linux/mmap64.c +++ b/sysdeps/unix/sysv/linux/mmap64.c @@ -53,10 +53,11 @@ __mmap64 (void *addr, size_t len, int prot, int flags, int fd, off64_t offset) MMAP_PREPARE (addr, len, prot, flags, fd, offset); #ifdef __NR_mmap2 - return (void *) MMAP_CALL (mmap2, addr, len, prot, flags, fd, - (off_t) (offset / MMAP2_PAGE_UNIT)); + return (void *) MMAP_CALL (mmap2, addr, SYSCALL_ULONG (len), prot, flags, + fd, (off_t) (offset / MMAP2_PAGE_UNIT)); #else - return (void *) MMAP_CALL (mmap, addr, len, prot, flags, fd, offset); + return (void *) MMAP_CALL (mmap, addr, SYSCALL_ULONG (len), prot, flags, + fd, offset); #endif } weak_alias (__mmap64, mmap64) diff --git a/sysdeps/unix/sysv/linux/mq_timedreceive.c b/sysdeps/unix/sysv/linux/mq_timedreceive.c index 728a63d1ec..aae1443196 100644 --- a/sysdeps/unix/sysv/linux/mq_timedreceive.c +++ b/sysdeps/unix/sysv/linux/mq_timedreceive.c @@ -30,11 +30,12 @@ __mq_timedreceive_time64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len, # ifndef __NR_mq_timedreceive_time64 # define __NR_mq_timedreceive_time64 __NR_mq_timedreceive # endif - return SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, msg_len, - msg_prio, abs_timeout); + return SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, + SYSCALL_ULONG (msg_len), msg_prio, abs_timeout); #else - int ret = SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, msg_len, - msg_prio, abs_timeout); + int ret = SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, + SYSCALL_ULONG (msg_len), msg_prio, + abs_timeout); if (ret == 0 || errno != ENOSYS) return ret; @@ -50,7 +51,8 @@ __mq_timedreceive_time64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len, ts32 = valid_timespec64_to_timespec (*abs_timeout); } - return SYSCALL_CANCEL (mq_timedreceive, mqdes, msg_ptr, msg_len, msg_prio, + return SYSCALL_CANCEL (mq_timedreceive, mqdes, msg_ptr, + SYSCALL_ULONG (msg_len), msg_prio, abs_timeout != NULL ? &ts32 : NULL); #endif } diff --git a/sysdeps/unix/sysv/linux/mq_timedsend.c b/sysdeps/unix/sysv/linux/mq_timedsend.c index f2a43df300..7e174df888 100644 --- a/sysdeps/unix/sysv/linux/mq_timedsend.c +++ b/sysdeps/unix/sysv/linux/mq_timedsend.c @@ -30,11 +30,11 @@ __mq_timedsend_time64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len, # ifndef __NR_mq_timedsend_time64 # define __NR_mq_timedsend_time64 __NR_mq_timedsend # endif - return SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, msg_len, - msg_prio, abs_timeout); + return SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, + SYSCALL_ULONG (msg_len), msg_prio, abs_timeout); #else - int ret = SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, msg_len, - msg_prio, abs_timeout); + int ret = SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, + SYSCALL_ULONG (msg_len), msg_prio, abs_timeout); if (ret == 0 || errno != ENOSYS) return ret; @@ -50,7 +50,8 @@ __mq_timedsend_time64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len, ts32 = valid_timespec64_to_timespec (*abs_timeout); } - return SYSCALL_CANCEL (mq_timedsend, mqdes, msg_ptr, msg_len, msg_prio, + return SYSCALL_CANCEL (mq_timedsend, mqdes, msg_ptr, + SYSCALL_ULONG (msg_len), msg_prio, abs_timeout != NULL ? &ts32 : NULL); #endif } @@ -66,7 +67,8 @@ __mq_timedsend (mqd_t mqdes, const char *msg_ptr, size_t msg_len, if (abs_timeout != NULL) ts64 = valid_timespec_to_timespec64 (*abs_timeout); - return __mq_timedsend_time64 (mqdes, msg_ptr, msg_len, msg_prio, + return __mq_timedsend_time64 (mqdes, msg_ptr, + SYSCALL_ULONG (msg_len), msg_prio, abs_timeout != NULL ? &ts64 : NULL); } #endif diff --git a/sysdeps/unix/sysv/linux/msgrcv.c b/sysdeps/unix/sysv/linux/msgrcv.c index 95edc7a787..ecfa2df4fb 100644 --- a/sysdeps/unix/sysv/linux/msgrcv.c +++ b/sysdeps/unix/sysv/linux/msgrcv.c @@ -25,10 +25,11 @@ __libc_msgrcv (int msqid, void *msgp, size_t msgsz, long int msgtyp, int msgflg) { #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS - return SYSCALL_CANCEL (msgrcv, msqid, msgp, msgsz, msgtyp, msgflg); + return SYSCALL_CANCEL (msgrcv, msqid, msgp, SYSCALL_ULONG (msgsz), + SYSCALL_LONG (msgtyp), msgflg); #else - return SYSCALL_CANCEL (ipc, IPCOP_msgrcv, msqid, msgsz, msgflg, - MSGRCV_ARGS (msgp, msgtyp)); + return SYSCALL_CANCEL (ipc, IPCOP_msgrcv, msqid, SYSCALL_ULONG (msgsz), + msgflg, MSGRCV_ARGS (msgp, SYSCALL_LONG (msgtyp))); #endif } weak_alias (__libc_msgrcv, msgrcv) diff --git a/sysdeps/unix/sysv/linux/msgsnd.c b/sysdeps/unix/sysv/linux/msgsnd.c index 554516f2ca..9e329d8e72 100644 --- a/sysdeps/unix/sysv/linux/msgsnd.c +++ b/sysdeps/unix/sysv/linux/msgsnd.c @@ -24,10 +24,11 @@ int __libc_msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg) { #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS - return SYSCALL_CANCEL (msgsnd, msqid, msgp, msgsz, msgflg); + return SYSCALL_CANCEL (msgsnd, msqid, msgp, SYSCALL_ULONG (msgsz), + msgflg); #else - return SYSCALL_CANCEL (ipc, IPCOP_msgsnd, msqid, msgsz, msgflg, - msgp); + return SYSCALL_CANCEL (ipc, IPCOP_msgsnd, msqid, SYSCALL_ULONG (msgsz), + msgflg, msgp); #endif } weak_alias (__libc_msgsnd, msgsnd) diff --git a/sysdeps/unix/sysv/linux/msync.c b/sysdeps/unix/sysv/linux/msync.c index de1dd2ac5e..0ef48a1eaf 100644 --- a/sysdeps/unix/sysv/linux/msync.c +++ b/sysdeps/unix/sysv/linux/msync.c @@ -22,5 +22,5 @@ int msync (void *addr, size_t length, int flags) { - return SYSCALL_CANCEL (msync, addr, length, flags); + return SYSCALL_CANCEL (msync, addr, SYSCALL_ULONG (length), flags); } diff --git a/sysdeps/unix/sysv/linux/pkey_mprotect.c b/sysdeps/unix/sysv/linux/pkey_mprotect.c index 4ec1feba2e..9130bbdef6 100644 --- a/sysdeps/unix/sysv/linux/pkey_mprotect.c +++ b/sysdeps/unix/sysv/linux/pkey_mprotect.c @@ -28,5 +28,6 @@ pkey_mprotect (void *addr, size_t len, int prot, int pkey) /* If the key is -1, the system call is precisely equivalent to mprotect. */ return __mprotect (addr, len, prot); - return INLINE_SYSCALL_CALL (pkey_mprotect, addr, len, prot, pkey); + return INLINE_SYSCALL_CALL (pkey_mprotect, addr, SYSCALL_ULONG (len), + prot, pkey); } diff --git a/sysdeps/unix/sysv/linux/pread.c b/sysdeps/unix/sysv/linux/pread.c index 8dd87b3976..41d51d810c 100644 --- a/sysdeps/unix/sysv/linux/pread.c +++ b/sysdeps/unix/sysv/linux/pread.c @@ -24,7 +24,8 @@ ssize_t __libc_pread (int fd, void *buf, size_t count, off_t offset) { - return SYSCALL_CANCEL (pread64, fd, buf, count, SYSCALL_LL_PRW (offset)); + return SYSCALL_CANCEL (pread64, fd, buf, SYSCALL_ULONG (count), + SYSCALL_LL_PRW (offset)); } strong_alias (__libc_pread, __pread) diff --git a/sysdeps/unix/sysv/linux/pread64.c b/sysdeps/unix/sysv/linux/pread64.c index 3d4ffbafc1..7a7bf7076c 100644 --- a/sysdeps/unix/sysv/linux/pread64.c +++ b/sysdeps/unix/sysv/linux/pread64.c @@ -22,7 +22,8 @@ ssize_t __libc_pread64 (int fd, void *buf, size_t count, off64_t offset) { - return SYSCALL_CANCEL (pread64, fd, buf, count, SYSCALL_LL64_PRW (offset)); + return SYSCALL_CANCEL (pread64, fd, buf, SYSCALL_ULONG (count), + SYSCALL_LL64_PRW (offset)); } weak_alias (__libc_pread64, __pread64) diff --git a/sysdeps/unix/sysv/linux/pread64_nocancel.c b/sysdeps/unix/sysv/linux/pread64_nocancel.c index af33985959..ea9e3be552 100644 --- a/sysdeps/unix/sysv/linux/pread64_nocancel.c +++ b/sysdeps/unix/sysv/linux/pread64_nocancel.c @@ -23,6 +23,7 @@ ssize_t __pread64_nocancel (int fd, void *buf, size_t count, off64_t offset) { - return INLINE_SYSCALL_CALL (pread64, fd, buf, count, SYSCALL_LL64_PRW (offset)); + return INLINE_SYSCALL_CALL (pread64, fd, buf, SYSCALL_ULONG (count), + SYSCALL_LL64_PRW (offset)); } hidden_def (__pread64_nocancel) diff --git a/sysdeps/unix/sysv/linux/pwrite.c b/sysdeps/unix/sysv/linux/pwrite.c index 17964686e5..c1cddbfe81 100644 --- a/sysdeps/unix/sysv/linux/pwrite.c +++ b/sysdeps/unix/sysv/linux/pwrite.c @@ -24,7 +24,8 @@ ssize_t __libc_pwrite (int fd, const void *buf, size_t count, off_t offset) { - return SYSCALL_CANCEL (pwrite64, fd, buf, count, SYSCALL_LL_PRW (offset)); + return SYSCALL_CANCEL (pwrite64, fd, buf, SYSCALL_ULONG (count), + SYSCALL_LL_PRW (offset)); } strong_alias (__libc_pwrite, __pwrite) diff --git a/sysdeps/unix/sysv/linux/pwrite64.c b/sysdeps/unix/sysv/linux/pwrite64.c index 709775c207..a47c309144 100644 --- a/sysdeps/unix/sysv/linux/pwrite64.c +++ b/sysdeps/unix/sysv/linux/pwrite64.c @@ -22,7 +22,8 @@ ssize_t __libc_pwrite64 (int fd, const void *buf, size_t count, off64_t offset) { - return SYSCALL_CANCEL (pwrite64, fd, buf, count, SYSCALL_LL64_PRW (offset)); + return SYSCALL_CANCEL (pwrite64, fd, buf, SYSCALL_ULONG (count), + SYSCALL_LL64_PRW (offset)); } weak_alias (__libc_pwrite64, __pwrite64) diff --git a/sysdeps/unix/sysv/linux/read.c b/sysdeps/unix/sysv/linux/read.c index 64f558a587..6c37b4fba9 100644 --- a/sysdeps/unix/sysv/linux/read.c +++ b/sysdeps/unix/sysv/linux/read.c @@ -23,7 +23,7 @@ ssize_t __libc_read (int fd, void *buf, size_t nbytes) { - return SYSCALL_CANCEL (read, fd, buf, nbytes); + return SYSCALL_CANCEL (read, fd, buf, SYSCALL_ULONG (nbytes)); } libc_hidden_def (__libc_read) diff --git a/sysdeps/unix/sysv/linux/read_nocancel.c b/sysdeps/unix/sysv/linux/read_nocancel.c index f9d8a3b563..4a734e9d83 100644 --- a/sysdeps/unix/sysv/linux/read_nocancel.c +++ b/sysdeps/unix/sysv/linux/read_nocancel.c @@ -23,6 +23,6 @@ ssize_t __read_nocancel (int fd, void *buf, size_t nbytes) { - return INLINE_SYSCALL_CALL (read, fd, buf, nbytes); + return INLINE_SYSCALL_CALL (read, fd, buf, SYSCALL_ULONG (nbytes)); } hidden_def (__read_nocancel) diff --git a/sysdeps/unix/sysv/linux/readahead.c b/sysdeps/unix/sysv/linux/readahead.c index a189c3ac79..46a98c000a 100644 --- a/sysdeps/unix/sysv/linux/readahead.c +++ b/sysdeps/unix/sysv/linux/readahead.c @@ -25,6 +25,6 @@ __readahead (int fd, off64_t offset, size_t count) { return INLINE_SYSCALL_CALL (readahead, fd, __ALIGNMENT_ARG SYSCALL_LL64 (offset), - count); + SYSCALL_ULONG (count)); } weak_alias (__readahead, readahead) diff --git a/sysdeps/unix/sysv/linux/recv.c b/sysdeps/unix/sysv/linux/recv.c index 79fb3c32d1..9ab079cc7c 100644 --- a/sysdeps/unix/sysv/linux/recv.c +++ b/sysdeps/unix/sysv/linux/recv.c @@ -23,11 +23,12 @@ ssize_t __libc_recv (int fd, void *buf, size_t len, int flags) { #ifdef __ASSUME_RECV_SYSCALL - return SYSCALL_CANCEL (recv, fd, buf, len, flags); + return SYSCALL_CANCEL (recv, fd, buf, SYSCALL_ULONG (len), flags); #elif defined __ASSUME_RECVFROM_SYSCALL - return SYSCALL_CANCEL (recvfrom, fd, buf, len, flags, NULL, NULL); + return SYSCALL_CANCEL (recvfrom, fd, buf, SYSCALL_ULONG (len), flags, + NULL, NULL); #else - return SOCKETCALL_CANCEL (recv, fd, buf, len, flags); + return SOCKETCALL_CANCEL (recv, fd, buf, SYSCALL_ULONG (len), flags); #endif } weak_alias (__libc_recv, recv) diff --git a/sysdeps/unix/sysv/linux/recvfrom.c b/sysdeps/unix/sysv/linux/recvfrom.c index 70532529c9..caf3b66738 100644 --- a/sysdeps/unix/sysv/linux/recvfrom.c +++ b/sysdeps/unix/sysv/linux/recvfrom.c @@ -24,11 +24,11 @@ __libc_recvfrom (int fd, void *buf, size_t len, int flags, __SOCKADDR_ARG addr, socklen_t *addrlen) { #ifdef __ASSUME_RECVFROM_SYSCALL - return SYSCALL_CANCEL (recvfrom, fd, buf, len, flags, addr.__sockaddr__, - addrlen); + return SYSCALL_CANCEL (recvfrom, fd, buf, SYSCALL_ULONG (len), flags, + addr.__sockaddr__, addrlen); #else - return SOCKETCALL_CANCEL (recvfrom, fd, buf, len, flags, addr.__sockaddr__, - addrlen); + return SOCKETCALL_CANCEL (recvfrom, fd, buf, SYSCALL_ULONG (len), + flags, addr.__sockaddr__, addrlen); #endif } weak_alias (__libc_recvfrom, recvfrom) diff --git a/sysdeps/unix/sysv/linux/sched_setaffinity.c b/sysdeps/unix/sysv/linux/sched_setaffinity.c index fc2c692783..aea179464c 100644 --- a/sysdeps/unix/sysv/linux/sched_setaffinity.c +++ b/sysdeps/unix/sysv/linux/sched_setaffinity.c @@ -30,7 +30,8 @@ libc_hidden_proto (__sched_setaffinity_new) int __sched_setaffinity_new (pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset) { - int result = INLINE_SYSCALL (sched_setaffinity, 3, pid, cpusetsize, cpuset); + int result = INLINE_SYSCALL (sched_setaffinity, 3, pid, + SYSCALL_ULONG (cpusetsize), cpuset); #ifdef RESET_VGETCPU_CACHE if (result != -1) diff --git a/sysdeps/unix/sysv/linux/semtimedop.c b/sysdeps/unix/sysv/linux/semtimedop.c index 6fdde09bad..f3b240ca9b 100644 --- a/sysdeps/unix/sysv/linux/semtimedop.c +++ b/sysdeps/unix/sysv/linux/semtimedop.c @@ -30,10 +30,12 @@ __semtimedop (int semid, struct sembuf *sops, size_t nsops, /* semtimedop wire-up syscall is not exported for 32-bit ABIs (they have semtimedop_time64 instead with uses a 64-bit time_t). */ #if defined __ASSUME_DIRECT_SYSVIPC_SYSCALLS && defined __NR_semtimedop - return INLINE_SYSCALL_CALL (semtimedop, semid, sops, nsops, timeout); + return INLINE_SYSCALL_CALL (semtimedop, semid, sops, + SYSCALL_ULONG (nsops), timeout); #else return INLINE_SYSCALL_CALL (ipc, IPCOP_semtimedop, semid, - SEMTIMEDOP_IPC_ARGS (nsops, sops, timeout)); + SEMTIMEDOP_IPC_ARGS (SYSCALL_ULONG (nsops), + sops, timeout)); #endif } weak_alias (__semtimedop, semtimedop) diff --git a/sysdeps/unix/sysv/linux/send.c b/sysdeps/unix/sysv/linux/send.c index aed7d06585..cd8725d05b 100644 --- a/sysdeps/unix/sysv/linux/send.c +++ b/sysdeps/unix/sysv/linux/send.c @@ -23,11 +23,12 @@ ssize_t __libc_send (int fd, const void *buf, size_t len, int flags) { #ifdef __ASSUME_SEND_SYSCALL - return SYSCALL_CANCEL (send, fd, buf, len, flags); + return SYSCALL_CANCEL (send, fd, buf, SYSCALL_ULONG (len), flags); #elif defined __ASSUME_SENDTO_SYSCALL - return SYSCALL_CANCEL (sendto, fd, buf, len, flags, NULL, 0); + return SYSCALL_CANCEL (sendto, fd, buf, SYSCALL_ULONG (len), flags, + NULL, 0); #else - return SOCKETCALL_CANCEL (send, fd, buf, len, flags); + return SOCKETCALL_CANCEL (send, fd, buf, SYSCALL_ULONG (len), flags); #endif } weak_alias (__libc_send, send) diff --git a/sysdeps/unix/sysv/linux/sendto.c b/sysdeps/unix/sysv/linux/sendto.c index 670d0679ea..ceb61305af 100644 --- a/sysdeps/unix/sysv/linux/sendto.c +++ b/sysdeps/unix/sysv/linux/sendto.c @@ -24,11 +24,11 @@ __libc_sendto (int fd, const void *buf, size_t len, int flags, __CONST_SOCKADDR_ARG addr, socklen_t addrlen) { #ifdef __ASSUME_SENDTO_SYSCALL - return SYSCALL_CANCEL (sendto, fd, buf, len, flags, addr.__sockaddr__, - addrlen); + return SYSCALL_CANCEL (sendto, fd, buf, SYSCALL_ULONG (len), flags, + addr.__sockaddr__, addrlen); #else - return SOCKETCALL_CANCEL (sendto, fd, buf, len, flags, addr.__sockaddr__, - addrlen); + return SOCKETCALL_CANCEL (sendto, fd, buf, SYSCALL_ULONG (len), flags, + addr.__sockaddr__, addrlen); #endif } weak_alias (__libc_sendto, sendto) diff --git a/sysdeps/unix/sysv/linux/shmget.c b/sysdeps/unix/sysv/linux/shmget.c index 6f7ce8c057..1032142170 100644 --- a/sysdeps/unix/sysv/linux/shmget.c +++ b/sysdeps/unix/sysv/linux/shmget.c @@ -28,8 +28,10 @@ int shmget (key_t key, size_t size, int shmflg) { #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS - return INLINE_SYSCALL_CALL (shmget, key, size, shmflg, NULL); + return INLINE_SYSCALL_CALL (shmget, key, SYSCALL_ULONG (size), + shmflg, NULL); #else - return INLINE_SYSCALL_CALL (ipc, IPCOP_shmget, key, size, shmflg, NULL); + return INLINE_SYSCALL_CALL (ipc, IPCOP_shmget, key, + SYSCALL_ULONG (size), shmflg, NULL); #endif } diff --git a/sysdeps/unix/sysv/linux/splice.c b/sysdeps/unix/sysv/linux/splice.c index fe21cf1988..199608fffa 100644 --- a/sysdeps/unix/sysv/linux/splice.c +++ b/sysdeps/unix/sysv/linux/splice.c @@ -23,5 +23,6 @@ ssize_t splice (int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) { - return SYSCALL_CANCEL (splice, fd_in, off_in, fd_out, off_out, len, flags); + return SYSCALL_CANCEL (splice, fd_in, off_in, fd_out, off_out, + SYSCALL_ULONG (len), flags); } diff --git a/sysdeps/unix/sysv/linux/sysdep.h b/sysdeps/unix/sysv/linux/sysdep.h index 5e7b6c5765..0ab65e40a5 100644 --- a/sysdeps/unix/sysv/linux/sysdep.h +++ b/sysdeps/unix/sysv/linux/sysdep.h @@ -94,6 +94,11 @@ (long) (val), \ (long) (((uint64_t) (val)) >> 32) +/* Provide common macros to pass long/unsigned long (ssize_t/size_t) + values on syscalls. */ +#define SYSCALL_LONG(val) (val) +#define SYSCALL_ULONG(val) (val) + /* Exports the __send symbol on send.c linux implementation (some ABI have it missing due the usage of a old generic version without it). */ #define HAVE_INTERNAL_SEND_SYMBOL 1 diff --git a/sysdeps/unix/sysv/linux/tee.c b/sysdeps/unix/sysv/linux/tee.c index 0e62c226dd..f404768ef6 100644 --- a/sysdeps/unix/sysv/linux/tee.c +++ b/sysdeps/unix/sysv/linux/tee.c @@ -22,5 +22,5 @@ ssize_t tee (int src, int dest, size_t len, unsigned int flags) { - return SYSCALL_CANCEL (tee, src, dest, len, flags); + return SYSCALL_CANCEL (tee, src, dest, SYSCALL_ULONG (len), flags); } diff --git a/sysdeps/unix/sysv/linux/vmsplice.c b/sysdeps/unix/sysv/linux/vmsplice.c index 17cc7bf8e7..e338a73944 100644 --- a/sysdeps/unix/sysv/linux/vmsplice.c +++ b/sysdeps/unix/sysv/linux/vmsplice.c @@ -23,5 +23,5 @@ ssize_t vmsplice (int fd, const struct iovec *iov, size_t count, unsigned int flags) { - return SYSCALL_CANCEL (vmsplice, fd, iov, count, flags); + return SYSCALL_CANCEL (vmsplice, fd, iov, SYSCALL_ULONG (count), flags); } diff --git a/sysdeps/unix/sysv/linux/write.c b/sysdeps/unix/sysv/linux/write.c index 7848f7de27..2176572425 100644 --- a/sysdeps/unix/sysv/linux/write.c +++ b/sysdeps/unix/sysv/linux/write.c @@ -23,7 +23,7 @@ ssize_t __libc_write (int fd, const void *buf, size_t nbytes) { - return SYSCALL_CANCEL (write, fd, buf, nbytes); + return SYSCALL_CANCEL (write, fd, buf, SYSCALL_ULONG (nbytes)); } libc_hidden_def (__libc_write) diff --git a/sysdeps/unix/sysv/linux/write_nocancel.c b/sysdeps/unix/sysv/linux/write_nocancel.c index 36d406cf74..17aa7d4797 100644 --- a/sysdeps/unix/sysv/linux/write_nocancel.c +++ b/sysdeps/unix/sysv/linux/write_nocancel.c @@ -23,6 +23,6 @@ ssize_t __write_nocancel (int fd, const void *buf, size_t nbytes) { - return INLINE_SYSCALL_CALL (write, fd, buf, nbytes); + return INLINE_SYSCALL_CALL (write, fd, buf, SYSCALL_ULONG (nbytes)); } hidden_def (__write_nocancel) diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h index 24d8b8ec20..a8a8e95fa5 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h @@ -57,13 +57,27 @@ # define SYSCALL_ERROR_LABEL syscall_error # endif +# 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, long_arg_1, long_arg_2) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args, long_arg_1, long_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 +85,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, long_arg_1, long_arg_2) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args, long_arg_1, long_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 +104,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, long_arg_1, long_arg_2) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args, long_arg_1, long_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,7 +188,7 @@ Syscalls of more than 6 arguments are not supported. */ # undef DO_CALL -# define DO_CALL(syscall_name, args) \ +# define DO_CALL(syscall_name, args, long_arg_1, long_arg_2) \ DOARGS_##args \ movl $SYS_ify (syscall_name), %eax; \ syscall; diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list b/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list index 58ea31d1fd..dfc551d402 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list +++ b/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list @@ -1,4 +1,14 @@ # File name Caller Syscall name # args Strong name Weak names +madvise - madvise i:pUi __madvise madvise +mincore - mincore i:aUV mincore +mprotect - mprotect i:aUi __mprotect mprotect +mlock - mlock i:bU mlock +mount EXTRA mount i:sssUp __mount mount +mremap EXTRA mremap b:aUUip __mremap mremap +munlock - munlock i:aU munlock +munmap - munmap i:aU __munmap munmap personality EXTRA personality Ei:i __personality personality posix_fadvise64 - fadvise64 Vi:iiii posix_fadvise posix_fadvise64 +remap_file_pages - remap_file_pages i:pUiUi __remap_file_pages remap_file_pages +sendfile - sendfile i:iipU sendfile sendfile64 diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h index 5bf9eed80b..d6898eb080 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h @@ -26,4 +26,34 @@ #undef LO_HI_LONG #define LO_HI_LONG(val) (val) +/* How to pass pass long/unsigned long (ssize_t/size_t) on syscalls. */ +#undef SYSCALL_LONG +#define SYSCALL_LONG(val) ((int64_t) (val)) +#undef SYSCALL_ULONG +#define SYSCALL_ULONG(val) ((uint64_t) (val)) + +#ifdef __ASSEMBLER__ +# undef DO_CALL +# define DO_CALL(syscall_name, args, long_arg_1, long_arg_2) \ + DOARGS_##args \ + ZERO_EXTEND_##long_arg_1 \ + ZERO_EXTEND_##long_arg_2 \ + movl $SYS_ify (syscall_name), %eax; \ + syscall; + +# define ZERO_EXTEND_0 /* nothing */ +# define ZERO_EXTEND_1 movl %edi, %edi; +# define ZERO_EXTEND_2 movl %esi, %esi; +# define ZERO_EXTEND_3 movl %edx, %edx; +# define ZERO_EXTEND_4 movl %r10d, %r10d; +# define ZERO_EXTEND_5 movl %r8d, %r8d; +# define ZERO_EXTEND_6 movl %r9d, %r9d; + +# if SYSCALL_ULONG_ARG_1 == 4 || SYSCALL_ULONG_ARG_2 == 4 +# undef ZERO_EXTEND_4 +# define ZERO_EXTEND_4 /* nothing */ +# define DOARGS_4 movl %ecx, %r10d; +# endif +#endif /* __ASSEMBLER__ */ + #endif /* linux/x86_64/x32/sysdep.h */