@@ -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))
new file mode 100644
@@ -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>
@@ -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'; \\
@@ -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)
@@ -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);
}
@@ -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
@@ -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;
@@ -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
@@ -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)
@@ -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)
@@ -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
@@ -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)
@@ -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
}
@@ -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
@@ -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)
@@ -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)
@@ -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);
}
@@ -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);
}
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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
}
@@ -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);
}
@@ -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
@@ -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);
}
@@ -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);
}
@@ -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)
@@ -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)
@@ -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;
@@ -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
@@ -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 */