Mark Wielaard 71cdb7
commit b0861063a8d2a55bb7423e90d26806bab0f78a12
Mark Wielaard 71cdb7
Author: Alexandra Hájková <ahajkova@redhat.com>
Mark Wielaard 71cdb7
Date:   Tue Jun 4 13:47:14 2019 +0200
Mark Wielaard 71cdb7
Mark Wielaard 71cdb7
    Add support for preadv2 and pwritev2 syscalls
Mark Wielaard 71cdb7
    
Mark Wielaard 71cdb7
    Support for amd64, x86 - 64 and 32 bit, arm64, ppc64, ppc64le,
Mark Wielaard 71cdb7
    s390x, mips64. This should work identically on all
Mark Wielaard 71cdb7
    arches, tested on x86 32bit and 64bit one, but enabled on all.
Mark Wielaard 71cdb7
    
Mark Wielaard 71cdb7
    Refactor the code to be reusable between old/new syscalls. Resolve TODO
Mark Wielaard 71cdb7
    items in the code. Add the testcase for the preadv2/pwritev2 and also
Mark Wielaard 71cdb7
    add the (similar) testcase for the older preadv/pwritev syscalls.
Mark Wielaard 71cdb7
    
Mark Wielaard 71cdb7
    Trying to test handling an uninitialized flag argument for the v2 syscalls
Mark Wielaard 71cdb7
    does not work because the flag always comes out as defined zero.
Mark Wielaard 71cdb7
    Turns out glibc does this deliberately on 64bit architectures because
Mark Wielaard 71cdb7
    the kernel does actually have a low_offset and high_offset argument, but
Mark Wielaard 71cdb7
    ignores the high_offset/assumes it is zero.
Mark Wielaard 71cdb7
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=601cc11d054ae4b5e9b5babec3d8e4667a2cb9b5
Mark Wielaard 71cdb7
    
Mark Wielaard 71cdb7
    https://bugs.kde.org/408414
Mark Wielaard 71cdb7
Mark Wielaard 71cdb7
diff --git a/configure.ac b/configure.ac
Mark Wielaard 71cdb7
index 352892565..3596d2fec 100755
Mark Wielaard 71cdb7
--- a/configure.ac
Mark Wielaard 71cdb7
+++ b/configure.ac
Mark Wielaard 71cdb7
@@ -4173,6 +4173,10 @@ AC_CHECK_FUNCS([     \
Mark Wielaard 71cdb7
         process_vm_readv  \
Mark Wielaard 71cdb7
         process_vm_writev \
Mark Wielaard 71cdb7
         copy_file_range \
Mark Wielaard 71cdb7
+        preadv \
Mark Wielaard 71cdb7
+        pwritev \
Mark Wielaard 71cdb7
+        preadv2 \
Mark Wielaard 71cdb7
+        pwritev2 \
Mark Wielaard 71cdb7
         ])
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
 # AC_CHECK_LIB adds any library found to the variable LIBS, and links these
Mark Wielaard 71cdb7
@@ -4190,6 +4194,10 @@ AM_CONDITIONAL([HAVE_PTHREAD_SETNAME_NP],
Mark Wielaard 71cdb7
                [test x$ac_cv_func_pthread_setname_np = xyes])
Mark Wielaard 71cdb7
 AM_CONDITIONAL([HAVE_COPY_FILE_RANGE],
Mark Wielaard 71cdb7
                [test x$ac_cv_func_copy_file_range = xyes])
Mark Wielaard 71cdb7
+AM_CONDITIONAL([HAVE_PREADV_PWRITEV],
Mark Wielaard 71cdb7
+               [test x$ac_cv_func_preadv = xyes && test x$ac_cv_func_pwritev = xyes])
Mark Wielaard 71cdb7
+AM_CONDITIONAL([HAVE_PREADV2_PWRITEV2],
Mark Wielaard 71cdb7
+               [test x$ac_cv_func_preadv2 = xyes && test x$ac_cv_func_pwritev2 = xyes])
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
 if test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \
Mark Wielaard 71cdb7
      -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX ; then
Mark Wielaard 71cdb7
diff --git a/coregrind/m_syswrap/priv_syswrap-generic.h b/coregrind/m_syswrap/priv_syswrap-generic.h
Mark Wielaard 71cdb7
index 3e1c8b682..73f9224f7 100644
Mark Wielaard 71cdb7
--- a/coregrind/m_syswrap/priv_syswrap-generic.h
Mark Wielaard 71cdb7
+++ b/coregrind/m_syswrap/priv_syswrap-generic.h
Mark Wielaard 71cdb7
@@ -109,6 +109,19 @@ ML_(handle_auxv_open)(SyscallStatus *status, const HChar *filename,
Mark Wielaard 71cdb7
 /* Helper function for generic mprotect and linux pkey_mprotect. */
Mark Wielaard 71cdb7
 extern void handle_sys_mprotect (ThreadId tid, SyscallStatus *status,
Mark Wielaard 71cdb7
                                  Addr *addr, SizeT *len, Int *prot);
Mark Wielaard 71cdb7
+/* Helper functions for preadv/preadv2. */
Mark Wielaard 71cdb7
+extern
Mark Wielaard 71cdb7
+void handle_pre_sys_preadv(ThreadId tid, SyscallStatus* status,
Mark Wielaard 71cdb7
+                           Int fd, Addr vector, Int count,
Mark Wielaard 71cdb7
+                           const char *str);
Mark Wielaard 71cdb7
+extern
Mark Wielaard 71cdb7
+void handle_post_sys_preadv(ThreadId tid, SyscallStatus* status, Addr vector, Int count);
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+/* Helper function for pwritev/pwritev2. */
Mark Wielaard 71cdb7
+extern
Mark Wielaard 71cdb7
+void handle_sys_pwritev(ThreadId tid, SyscallStatus* status,
Mark Wielaard 71cdb7
+                        Int fd, Addr vector, Int count,
Mark Wielaard 71cdb7
+                        const char *str);
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
 DECL_TEMPLATE(generic, sys_ni_syscall);            // * P -- unimplemented
Mark Wielaard 71cdb7
 DECL_TEMPLATE(generic, sys_exit);
Mark Wielaard 71cdb7
diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h
Mark Wielaard 71cdb7
index be2f9bdde..8ce8ef3d5 100644
Mark Wielaard 71cdb7
--- a/coregrind/m_syswrap/priv_syswrap-linux.h
Mark Wielaard 71cdb7
+++ b/coregrind/m_syswrap/priv_syswrap-linux.h
Mark Wielaard 71cdb7
@@ -46,7 +46,9 @@ DECL_TEMPLATE(linux, sys_oldumount);
Mark Wielaard 71cdb7
 DECL_TEMPLATE(linux, sys_umount);
Mark Wielaard 71cdb7
 DECL_TEMPLATE(linux, sys_perf_event_open);
Mark Wielaard 71cdb7
 DECL_TEMPLATE(linux, sys_preadv);
Mark Wielaard 71cdb7
+DECL_TEMPLATE(linux, sys_preadv2);
Mark Wielaard 71cdb7
 DECL_TEMPLATE(linux, sys_pwritev);
Mark Wielaard 71cdb7
+DECL_TEMPLATE(linux, sys_pwritev2);
Mark Wielaard 71cdb7
 DECL_TEMPLATE(linux, sys_sendmmsg);
Mark Wielaard 71cdb7
 DECL_TEMPLATE(linux, sys_recvmmsg);
Mark Wielaard 71cdb7
 DECL_TEMPLATE(linux, sys_dup3);
Mark Wielaard 71cdb7
diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c
Mark Wielaard 71cdb7
index 382dc65cf..9b8068d0f 100644
Mark Wielaard 71cdb7
--- a/coregrind/m_syswrap/syswrap-amd64-linux.c
Mark Wielaard 71cdb7
+++ b/coregrind/m_syswrap/syswrap-amd64-linux.c
Mark Wielaard 71cdb7
@@ -857,6 +857,8 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard 71cdb7
 //   LIN__(__NR_kexec_file_load,   sys_ni_syscall),       // 320
Mark Wielaard 71cdb7
    LINXY(__NR_bpf,               sys_bpf),              // 321
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
+   LINXY(__NR_preadv2,           sys_preadv2),           // 327
Mark Wielaard 71cdb7
+   LINX_(__NR_pwritev2,          sys_pwritev2),          // 328
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
    LINXY(__NR_statx,             sys_statx),             // 332
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
diff --git a/coregrind/m_syswrap/syswrap-arm64-linux.c b/coregrind/m_syswrap/syswrap-arm64-linux.c
Mark Wielaard 71cdb7
index c700e3dbe..d12d40632 100644
Mark Wielaard 71cdb7
--- a/coregrind/m_syswrap/syswrap-arm64-linux.c
Mark Wielaard 71cdb7
+++ b/coregrind/m_syswrap/syswrap-arm64-linux.c
Mark Wielaard 71cdb7
@@ -818,8 +818,8 @@ static SyscallTableEntry syscall_main_table[] = {
Mark Wielaard 71cdb7
    LINX_(__NR_membarrier,        sys_membarrier),        // 283
Mark Wielaard 71cdb7
    //   (__NR_mlock2,            sys_ni_syscall),        // 284
Mark Wielaard 71cdb7
    LINX_(__NR_copy_file_range,   sys_copy_file_range),   // 285
Mark Wielaard 71cdb7
-   //   (__NR_preadv2,           sys_ni_syscall),        // 286
Mark Wielaard 71cdb7
-   //   (__NR_pwritev2,          sys_ni_syscall),        // 287
Mark Wielaard 71cdb7
+   LINX_(__NR_preadv2,           sys_ni_syscall),        // 286
Mark Wielaard 71cdb7
+   LINX_(__NR_pwritev2,          sys_ni_syscall),        // 287
Mark Wielaard 71cdb7
    //   (__NR_pkey_mprotect,     sys_ni_syscall),        // 288
Mark Wielaard 71cdb7
    //   (__NR_pkey_alloc,        sys_ni_syscall),        // 289
Mark Wielaard 71cdb7
    //   (__NR_pkey_free,         sys_ni_syscall),        // 290
Mark Wielaard 71cdb7
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
Mark Wielaard 71cdb7
index 36d09d6e0..2fe15d97b 100644
Mark Wielaard 71cdb7
--- a/coregrind/m_syswrap/syswrap-linux.c
Mark Wielaard 71cdb7
+++ b/coregrind/m_syswrap/syswrap-linux.c
Mark Wielaard 71cdb7
@@ -5501,12 +5501,57 @@ POST(sys_open_by_handle_at)
Mark Wielaard 71cdb7
 /* ---------------------------------------------------------------------
Mark Wielaard 71cdb7
    p{read,write}v wrappers
Mark Wielaard 71cdb7
    ------------------------------------------------------------------ */
Mark Wielaard 71cdb7
+/* This handles the common part of the PRE macro for preadv and preadv2. */
Mark Wielaard 71cdb7
+void handle_pre_sys_preadv(ThreadId tid, SyscallStatus* status,
Mark Wielaard 71cdb7
+                           Int fd, Addr vector, Int count, const char *str)
Mark Wielaard 71cdb7
+{
Mark Wielaard 71cdb7
+   struct vki_iovec * vec;
Mark Wielaard 71cdb7
+   Int i;
Mark Wielaard 71cdb7
+   /* safe size for the "preadv/preadv2(vector[i])" string */
Mark Wielaard 71cdb7
+   char tmp[30];
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+   if (!ML_(fd_allowed)(fd, str, tid, False)) {
Mark Wielaard 71cdb7
+      SET_STATUS_Failure( VKI_EBADF );
Mark Wielaard 71cdb7
+   } else if (count > 0) {
Mark Wielaard 71cdb7
+      VG_(strcpy) (tmp, str);
Mark Wielaard 71cdb7
+      VG_(strcat) (tmp, "(vector)");
Mark Wielaard 71cdb7
+      PRE_MEM_READ( tmp, vector, count * sizeof(struct vki_iovec) );
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+      if (ML_(safe_to_deref) ((void *)(Addr)vector,
Mark Wielaard 71cdb7
+                              count * sizeof(struct vki_iovec))) {
Mark Wielaard 71cdb7
+         vec = (struct vki_iovec *)(Addr)vector;
Mark Wielaard 71cdb7
+         for (i = 0; i < count; i++) {
Mark Wielaard 71cdb7
+            VG_(snprintf) (tmp, 30, "%s(vector[%d])", str, i);
Mark Wielaard 71cdb7
+            PRE_MEM_WRITE( tmp, (Addr)vec[i].iov_base, vec[i].iov_len );
Mark Wielaard 71cdb7
+         }
Mark Wielaard 71cdb7
+      }
Mark Wielaard 71cdb7
+   }
Mark Wielaard 71cdb7
+}
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+/* This handles the common part of the POST macro for preadv and preadv2. */
Mark Wielaard 71cdb7
+void handle_post_sys_preadv(ThreadId tid, SyscallStatus* status, Addr vector, Int count)
Mark Wielaard 71cdb7
+{
Mark Wielaard 71cdb7
+    vg_assert(SUCCESS);
Mark Wielaard 71cdb7
+    if (RES > 0) {
Mark Wielaard 71cdb7
+        Int i;
Mark Wielaard 71cdb7
+        struct vki_iovec * vec = (struct vki_iovec *)(Addr)vector;
Mark Wielaard 71cdb7
+        Int remains = RES;
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+        /* RES holds the number of bytes read. */
Mark Wielaard 71cdb7
+        for (i = 0; i < count; i++) {
Mark Wielaard 71cdb7
+            Int nReadThisBuf = vec[i].iov_len;
Mark Wielaard 71cdb7
+            if (nReadThisBuf > remains) nReadThisBuf = remains;
Mark Wielaard 71cdb7
+            POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
Mark Wielaard 71cdb7
+            remains -= nReadThisBuf;
Mark Wielaard 71cdb7
+            if (remains < 0) VG_(core_panic)("preadv: remains < 0");
Mark Wielaard 71cdb7
+        }
Mark Wielaard 71cdb7
+    }
Mark Wielaard 71cdb7
+}
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
 PRE(sys_preadv)
Mark Wielaard 71cdb7
 {
Mark Wielaard 71cdb7
-   Int i;
Mark Wielaard 71cdb7
-   struct vki_iovec * vec;
Mark Wielaard 71cdb7
    *flags |= SfMayBlock;
Mark Wielaard 71cdb7
+   const char *str = "preadv";
Mark Wielaard 71cdb7
 #if VG_WORDSIZE == 4
Mark Wielaard 71cdb7
    /* Note that the offset argument here is in lo+hi order on both
Mark Wielaard 71cdb7
       big and little endian platforms... */
Mark Wielaard 71cdb7
@@ -5525,45 +5570,89 @@ PRE(sys_preadv)
Mark Wielaard 71cdb7
 #else
Mark Wielaard 71cdb7
 #  error Unexpected word size
Mark Wielaard 71cdb7
 #endif
Mark Wielaard 71cdb7
-   if (!ML_(fd_allowed)(ARG1, "preadv", tid, False)) {
Mark Wielaard 71cdb7
-      SET_STATUS_Failure( VKI_EBADF );
Mark Wielaard 71cdb7
-   } else {
Mark Wielaard 71cdb7
-      PRE_MEM_READ( "preadv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
Mark Wielaard 71cdb7
+   Int fd = ARG1;
Mark Wielaard 71cdb7
+   Addr vector = ARG2;
Mark Wielaard 71cdb7
+   Int count = ARG3;
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+   handle_pre_sys_preadv(tid, status, fd, vector, count, str);
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
-      if (ARG2 != 0) {
Mark Wielaard 71cdb7
-         /* ToDo: don't do any of the following if the vector is invalid */
Mark Wielaard 71cdb7
-         vec = (struct vki_iovec *)(Addr)ARG2;
Mark Wielaard 71cdb7
-         for (i = 0; i < (Int)ARG3; i++)
Mark Wielaard 71cdb7
-            PRE_MEM_WRITE( "preadv(vector[...])",
Mark Wielaard 71cdb7
-                           (Addr)vec[i].iov_base, vec[i].iov_len );
Mark Wielaard 71cdb7
-      }
Mark Wielaard 71cdb7
-   }
Mark Wielaard 71cdb7
 }
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
 POST(sys_preadv)
Mark Wielaard 71cdb7
 {
Mark Wielaard 71cdb7
-   vg_assert(SUCCESS);
Mark Wielaard 71cdb7
-   if (RES > 0) {
Mark Wielaard 71cdb7
-      Int i;
Mark Wielaard 71cdb7
-      struct vki_iovec * vec = (struct vki_iovec *)(Addr)ARG2;
Mark Wielaard 71cdb7
-      Int remains = RES;
Mark Wielaard 71cdb7
+   Addr vector = ARG2;
Mark Wielaard 71cdb7
+   Int count = ARG3;
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
-      /* RES holds the number of bytes read. */
Mark Wielaard 71cdb7
-      for (i = 0; i < (Int)ARG3; i++) {
Mark Wielaard 71cdb7
-	 Int nReadThisBuf = vec[i].iov_len;
Mark Wielaard 71cdb7
-	 if (nReadThisBuf > remains) nReadThisBuf = remains;
Mark Wielaard 71cdb7
-	 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
Mark Wielaard 71cdb7
-	 remains -= nReadThisBuf;
Mark Wielaard 71cdb7
-	 if (remains < 0) VG_(core_panic)("preadv: remains < 0");
Mark Wielaard 71cdb7
+   handle_post_sys_preadv(tid, status, vector, count);
Mark Wielaard 71cdb7
+}
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+PRE(sys_preadv2)
Mark Wielaard 71cdb7
+{
Mark Wielaard 71cdb7
+   *flags |= SfMayBlock;
Mark Wielaard 71cdb7
+   const char *str = "preadv2";
Mark Wielaard 71cdb7
+#if VG_WORDSIZE == 4
Mark Wielaard 71cdb7
+   /* Note that the offset argument here is in lo+hi order on both
Mark Wielaard 71cdb7
+      big and little endian platforms... */
Mark Wielaard 71cdb7
+   PRINT("sys_preadv2 ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD
Mark Wielaard 71cdb7
+         "u, %lld, %" FMT_REGWORD "u )",
Mark Wielaard 71cdb7
+         ARG1, ARG2, ARG3, (Long)LOHI64(ARG4,ARG5), ARG6);
Mark Wielaard 71cdb7
+   PRE_REG_READ6(ssize_t, "preadv2",
Mark Wielaard 71cdb7
+                 unsigned long, fd, const struct iovec *, vector,
Mark Wielaard 71cdb7
+                 unsigned long, count, vki_u32, offset_low,
Mark Wielaard 71cdb7
+                 vki_u32, offset_high, unsigned long, flags);
Mark Wielaard 71cdb7
+#elif VG_WORDSIZE == 8
Mark Wielaard 71cdb7
+   PRINT("sys_preadv2 ( %lu, %#lx, %lu, %ld, %lu )", ARG1, ARG2, ARG3, SARG4, ARG5);
Mark Wielaard 71cdb7
+   PRE_REG_READ5(ssize_t, "preadv2",
Mark Wielaard 71cdb7
+                 unsigned long, fd, const struct iovec *, vector,
Mark Wielaard 71cdb7
+                 unsigned long, count, Word, offset, unsigned long, flags);
Mark Wielaard 71cdb7
+#else
Mark Wielaard 71cdb7
+#  error Unexpected word size
Mark Wielaard 71cdb7
+#endif
Mark Wielaard 71cdb7
+   Int fd = ARG1;
Mark Wielaard 71cdb7
+   Addr vector = ARG2;
Mark Wielaard 71cdb7
+   Int count = ARG3;
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+   handle_pre_sys_preadv(tid, status, fd, vector, count, str);
Mark Wielaard 71cdb7
+}
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+POST(sys_preadv2)
Mark Wielaard 71cdb7
+{
Mark Wielaard 71cdb7
+   Addr vector = ARG2;
Mark Wielaard 71cdb7
+   Int count = ARG3;
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+   handle_post_sys_preadv(tid, status, vector, count);
Mark Wielaard 71cdb7
+}
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+/* This handles the common part of the PRE macro for pwritev and pwritev2. */
Mark Wielaard 71cdb7
+void handle_sys_pwritev(ThreadId tid, SyscallStatus* status,
Mark Wielaard 71cdb7
+                        Int fd, Addr vector, Int count, const char *str)
Mark Wielaard 71cdb7
+{
Mark Wielaard 71cdb7
+   Int i;
Mark Wielaard 71cdb7
+   struct vki_iovec * vec;
Mark Wielaard 71cdb7
+   /* safe size for the "preadv/preadv2(vector[i])" string */
Mark Wielaard 71cdb7
+   char tmp[30];
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+   if (!ML_(fd_allowed)(fd, str, tid, False)) {
Mark Wielaard 71cdb7
+      SET_STATUS_Failure( VKI_EBADF );
Mark Wielaard 71cdb7
+   } else if (count > 0) {
Mark Wielaard 71cdb7
+      VG_(strcpy) (tmp, str);
Mark Wielaard 71cdb7
+      VG_(strcat) (tmp, "(vector)");
Mark Wielaard 71cdb7
+      PRE_MEM_READ( tmp, vector, count * sizeof(struct vki_iovec) );
Mark Wielaard 71cdb7
+      if (ML_(safe_to_deref) ((void *)(Addr)vector,
Mark Wielaard 71cdb7
+                              count * sizeof(struct vki_iovec))) {
Mark Wielaard 71cdb7
+         vec = (struct vki_iovec *)(Addr)vector;
Mark Wielaard 71cdb7
+         for (i = 0; i < count; i++) {
Mark Wielaard 71cdb7
+            VG_(snprintf) (tmp, 30, "%s(vector[%d])", str, i);
Mark Wielaard 71cdb7
+            PRE_MEM_READ( tmp, (Addr)vec[i].iov_base, vec[i].iov_len );
Mark Wielaard 71cdb7
+         }
Mark Wielaard 71cdb7
       }
Mark Wielaard 71cdb7
    }
Mark Wielaard 71cdb7
 }
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
 PRE(sys_pwritev)
Mark Wielaard 71cdb7
 {
Mark Wielaard 71cdb7
-   Int i;
Mark Wielaard 71cdb7
-   struct vki_iovec * vec;
Mark Wielaard 71cdb7
    *flags |= SfMayBlock;
Mark Wielaard 71cdb7
+   const char *str = "pwritev";
Mark Wielaard 71cdb7
 #if VG_WORDSIZE == 4
Mark Wielaard 71cdb7
    /* Note that the offset argument here is in lo+hi order on both
Mark Wielaard 71cdb7
       big and little endian platforms... */
Mark Wielaard 71cdb7
@@ -5581,19 +5670,41 @@ PRE(sys_pwritev)
Mark Wielaard 71cdb7
 #else
Mark Wielaard 71cdb7
 #  error Unexpected word size
Mark Wielaard 71cdb7
 #endif
Mark Wielaard 71cdb7
-   if (!ML_(fd_allowed)(ARG1, "pwritev", tid, False)) {
Mark Wielaard 71cdb7
-      SET_STATUS_Failure( VKI_EBADF );
Mark Wielaard 71cdb7
-   } else {
Mark Wielaard 71cdb7
-      PRE_MEM_READ( "pwritev(vector)", 
Mark Wielaard 71cdb7
-		     ARG2, ARG3 * sizeof(struct vki_iovec) );
Mark Wielaard 71cdb7
-      if (ARG2 != 0) {
Mark Wielaard 71cdb7
-         /* ToDo: don't do any of the following if the vector is invalid */
Mark Wielaard 71cdb7
-         vec = (struct vki_iovec *)(Addr)ARG2;
Mark Wielaard 71cdb7
-         for (i = 0; i < (Int)ARG3; i++)
Mark Wielaard 71cdb7
-            PRE_MEM_READ( "pwritev(vector[...])",
Mark Wielaard 71cdb7
-                           (Addr)vec[i].iov_base, vec[i].iov_len );
Mark Wielaard 71cdb7
-      }
Mark Wielaard 71cdb7
-   }
Mark Wielaard 71cdb7
+   Int fd = ARG1;
Mark Wielaard 71cdb7
+   Addr vector = ARG2;
Mark Wielaard 71cdb7
+   Int count = ARG3;
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+   handle_sys_pwritev(tid, status, fd, vector, count, str);
Mark Wielaard 71cdb7
+}
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+PRE(sys_pwritev2)
Mark Wielaard 71cdb7
+{
Mark Wielaard 71cdb7
+   *flags |= SfMayBlock;
Mark Wielaard 71cdb7
+   const char *str = "pwritev2";
Mark Wielaard 71cdb7
+#if VG_WORDSIZE == 4
Mark Wielaard 71cdb7
+   /* Note that the offset argument here is in lo+hi order on both
Mark Wielaard 71cdb7
+      big and little endian platforms... */
Mark Wielaard 71cdb7
+   PRINT("sys_pwritev2 ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD
Mark Wielaard 71cdb7
+         "u, %lld, %" FMT_REGWORD "u )",
Mark Wielaard 71cdb7
+         ARG1, ARG2, ARG3, (Long)LOHI64(ARG4,ARG5), ARG6);
Mark Wielaard 71cdb7
+   PRE_REG_READ6(ssize_t, "pwritev2",
Mark Wielaard 71cdb7
+                 unsigned long, fd, const struct iovec *, vector,
Mark Wielaard 71cdb7
+                 unsigned long, count, vki_u32, offset_low,
Mark Wielaard 71cdb7
+                 vki_u32, offset_high, unsigned long, flags);
Mark Wielaard 71cdb7
+#elif VG_WORDSIZE == 8
Mark Wielaard 71cdb7
+   /* Note offset_high isn't actually used?  */
Mark Wielaard 71cdb7
+   PRE_REG_READ6(ssize_t, "pwritev2",
Mark Wielaard 71cdb7
+                 unsigned long, fd, const struct iovec *, vector,
Mark Wielaard 71cdb7
+                 unsigned long, count, Word, offset,
Mark Wielaard 71cdb7
+		 Word, offset_high, unsigned long, flags);
Mark Wielaard 71cdb7
+#else
Mark Wielaard 71cdb7
+#  error Unexpected word size
Mark Wielaard 71cdb7
+#endif
Mark Wielaard 71cdb7
+   Int fd = ARG1;
Mark Wielaard 71cdb7
+   Addr vector = ARG2;
Mark Wielaard 71cdb7
+   Int count = ARG3;
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+   handle_sys_pwritev(tid, status, fd, vector, count, str);
Mark Wielaard 71cdb7
 }
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
 /* ---------------------------------------------------------------------
Mark Wielaard 71cdb7
diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c
Mark Wielaard 71cdb7
index baa2934ab..d65a664dd 100644
Mark Wielaard 71cdb7
--- a/coregrind/m_syswrap/syswrap-ppc64-linux.c
Mark Wielaard 71cdb7
+++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c
Mark Wielaard 71cdb7
@@ -1006,6 +1006,8 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard 71cdb7
    LINX_(__NR_membarrier,        sys_membarrier),       // 365
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
    LINX_(__NR_copy_file_range,   sys_copy_file_range),  // 379
Mark Wielaard 71cdb7
+   LINX_(__NR_preadv2,           sys_preadv2),          // 380
Mark Wielaard 71cdb7
+   LINX_(__NR_pwritev2,          sys_pwritev2),         // 381
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
    LINXY(__NR_statx,             sys_statx),            // 383
Mark Wielaard 71cdb7
 };
Mark Wielaard 71cdb7
diff --git a/coregrind/m_syswrap/syswrap-s390x-linux.c b/coregrind/m_syswrap/syswrap-s390x-linux.c
Mark Wielaard 71cdb7
index 1481e768b..3354d41c0 100644
Mark Wielaard 71cdb7
--- a/coregrind/m_syswrap/syswrap-s390x-linux.c
Mark Wielaard 71cdb7
+++ b/coregrind/m_syswrap/syswrap-s390x-linux.c
Mark Wielaard 71cdb7
@@ -853,6 +853,8 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard 71cdb7
    LINX_(__NR_shutdown, sys_shutdown),                                // 373
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
    LINX_(__NR_copy_file_range, sys_copy_file_range),                  // 375
Mark Wielaard 71cdb7
+   LINXY(__NR_preadv2, sys_preadv2),                                  // 376
Mark Wielaard 71cdb7
+   LINX_(__NR_pwritev2, sys_pwritev2),                                // 377
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
    LINXY(__NR_statx, sys_statx),                                      // 379
Mark Wielaard 71cdb7
 };
Mark Wielaard 71cdb7
diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c
Mark Wielaard 71cdb7
index 9ff53a92a..33d1213a3 100644
Mark Wielaard 71cdb7
--- a/coregrind/m_syswrap/syswrap-x86-linux.c
Mark Wielaard 71cdb7
+++ b/coregrind/m_syswrap/syswrap-x86-linux.c
Mark Wielaard 71cdb7
@@ -1607,6 +1607,8 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard 71cdb7
    LINX_(__NR_membarrier,        sys_membarrier),       // 375
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
    LINX_(__NR_copy_file_range,   sys_copy_file_range),   // 377
Mark Wielaard 71cdb7
+   LINXY(__NR_preadv2,           sys_preadv2),           // 378
Mark Wielaard 71cdb7
+   LINX_(__NR_pwritev2,          sys_pwritev2),          // 379
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
    LINXY(__NR_pkey_mprotect,     sys_pkey_mprotect),    // 380
Mark Wielaard 71cdb7
    LINX_(__NR_pkey_alloc,        sys_pkey_alloc),       // 381
Mark Wielaard 71cdb7
diff --git a/memcheck/tests/linux/Makefile.am b/memcheck/tests/linux/Makefile.am
Mark Wielaard 71cdb7
index 00e99a52a..e13325869 100644
Mark Wielaard 71cdb7
--- a/memcheck/tests/linux/Makefile.am
Mark Wielaard 71cdb7
+++ b/memcheck/tests/linux/Makefile.am
Mark Wielaard 71cdb7
@@ -26,7 +26,9 @@ EXTRA_DIST = \
Mark Wielaard 71cdb7
 	timerfd-syscall.vgtest timerfd-syscall.stderr.exp \
Mark Wielaard 71cdb7
 	with-space.stderr.exp with-space.stdout.exp with-space.vgtest \
Mark Wielaard 71cdb7
 	proc-auxv.vgtest proc-auxv.stderr.exp getregset.vgtest \
Mark Wielaard 71cdb7
-	getregset.stderr.exp getregset.stdout.exp
Mark Wielaard 71cdb7
+	getregset.stderr.exp getregset.stdout.exp \
Mark Wielaard 71cdb7
+	sys-preadv_pwritev.vgtest sys-preadv_pwritev.stderr.exp \
Mark Wielaard 71cdb7
+	sys-preadv2_pwritev2.vgtest sys-preadv2_pwritev2.stderr.exp
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
 check_PROGRAMS = \
Mark Wielaard 71cdb7
 	brk \
Mark Wielaard 71cdb7
@@ -54,6 +56,14 @@ if HAVE_COPY_FILE_RANGE
Mark Wielaard 71cdb7
         check_PROGRAMS += sys-copy_file_range
Mark Wielaard 71cdb7
 endif
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
+if HAVE_PREADV_PWRITEV
Mark Wielaard 71cdb7
+        check_PROGRAMS += sys-preadv_pwritev
Mark Wielaard 71cdb7
+endif
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+if HAVE_PREADV2_PWRITEV2
Mark Wielaard 71cdb7
+        check_PROGRAMS += sys-preadv2_pwritev2
Mark Wielaard 71cdb7
+endif
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
 AM_CFLAGS   += $(AM_FLAG_M3264_PRI)
Mark Wielaard 71cdb7
 AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
Mark Wielaard 71cdb7
 
Mark Wielaard 71cdb7
diff --git a/memcheck/tests/linux/sys-preadv2_pwritev2.c b/memcheck/tests/linux/sys-preadv2_pwritev2.c
Mark Wielaard 71cdb7
new file mode 100644
Mark Wielaard 71cdb7
index 000000000..942eab68b
Mark Wielaard 71cdb7
--- /dev/null
Mark Wielaard 71cdb7
+++ b/memcheck/tests/linux/sys-preadv2_pwritev2.c
Mark Wielaard 71cdb7
@@ -0,0 +1,79 @@
Mark Wielaard 71cdb7
+#define _GNU_SOURCE
Mark Wielaard 71cdb7
+#include <fcntl.h>
Mark Wielaard 71cdb7
+#include <stdio.h>
Mark Wielaard 71cdb7
+#include <stdlib.h>
Mark Wielaard 71cdb7
+#include <sys/stat.h>
Mark Wielaard 71cdb7
+#include <unistd.h>
Mark Wielaard 71cdb7
+#include <sys/syscall.h>
Mark Wielaard 71cdb7
+#include <sys/uio.h>
Mark Wielaard 71cdb7
+#include <string.h>
Mark Wielaard 71cdb7
+#include "../../memcheck.h"
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+#include <errno.h>
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+int main(int argc, char **argv)
Mark Wielaard 71cdb7
+{
Mark Wielaard 71cdb7
+    char str0[] = "hello ";
Mark Wielaard 71cdb7
+    char str1[] = "world\n";
Mark Wielaard 71cdb7
+    struct iovec iov[2];
Mark Wielaard 71cdb7
+    int fd;
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    fd = open("prwv2_source", O_CREAT | O_RDWR, 0644);
Mark Wielaard 71cdb7
+    if (fd == -1) {
Mark Wielaard 71cdb7
+        perror("prwv2_source");
Mark Wielaard 71cdb7
+        exit(EXIT_FAILURE);
Mark Wielaard 71cdb7
+    }
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    iov[0].iov_base = str0;
Mark Wielaard 71cdb7
+    iov[0].iov_len = strlen(str0);
Mark Wielaard 71cdb7
+    iov[1].iov_base = str1;
Mark Wielaard 71cdb7
+    iov[1].iov_len = strlen(str1);
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    /* Check pwritev2 and preadv2 called with the correct arguments works. */
Mark Wielaard 71cdb7
+    if (pwritev2(fd, iov, 2, 0, 0) == -1) {
Mark Wielaard 71cdb7
+        perror("pwritev2");
Mark Wielaard 71cdb7
+        exit(EXIT_FAILURE);
Mark Wielaard 71cdb7
+    }
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    if (preadv2(fd, iov, 2, 0, 0) == -1) {
Mark Wielaard 71cdb7
+        perror("preadv2");
Mark Wielaard 71cdb7
+        printf("errno: %d\n", errno);
Mark Wielaard 71cdb7
+        exit(EXIT_FAILURE);
Mark Wielaard 71cdb7
+    }
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    /* Check valgrind will produce expected warnings for the
Mark Wielaard 71cdb7
+       various wrong arguments. */
Mark Wielaard 71cdb7
+    do {
Mark Wielaard 71cdb7
+        /* always allocate 16 bytes to not to have different .exps for different reg sizes */
Mark Wielaard 71cdb7
+        char *mem = malloc(16);
Mark Wielaard 71cdb7
+        void *t = (void *) &mem[0];
Mark Wielaard 71cdb7
+        void *z = (void *) -1;
Mark Wielaard 71cdb7
+	int c = *((int *) &mem[4]);
Mark Wielaard 71cdb7
+        int flag = *((int *) &mem[8]);
Mark Wielaard 71cdb7
+        pwritev2(fd, NULL, 2, 0, 0);
Mark Wielaard 71cdb7
+        pwritev2(fd, z, 2, 0, 0);
Mark Wielaard 71cdb7
+        pwritev2(fd, t, 2, 0, 0);
Mark Wielaard 71cdb7
+        pwritev2(fd, iov, -1, 0, 0);
Mark Wielaard 71cdb7
+        pwritev2(fd, iov, c, 0, 0);
Mark Wielaard 71cdb7
+        pwritev2(fd, iov, 2, -5, 0);
Mark Wielaard 71cdb7
+        pwritev2(-1, iov, 2, -5, 0);
Mark Wielaard 71cdb7
+        pwritev2(fd, iov, 2, -5, flag);
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+        preadv2(fd, NULL, 2, 0, 0);
Mark Wielaard 71cdb7
+        preadv2(fd, z, 2, 0, 0);
Mark Wielaard 71cdb7
+        preadv2(fd, t, 2, 0, 0);
Mark Wielaard 71cdb7
+        preadv2(fd, iov, -1, 0, 0);
Mark Wielaard 71cdb7
+        preadv2(fd, iov, c, 0, 0);
Mark Wielaard 71cdb7
+        preadv2(fd, iov, 2, -5, 0);
Mark Wielaard 71cdb7
+        preadv2(-1, iov, 2, -5, 0);
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+        iov[1].iov_base = (void *) -1;
Mark Wielaard 71cdb7
+        pwritev2(fd, iov, 2, 0, 0);
Mark Wielaard 71cdb7
+        preadv2(fd, iov, 2, 0, 0);
Mark Wielaard 71cdb7
+        free(mem);
Mark Wielaard 71cdb7
+    } while (0);
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    close(fd);
Mark Wielaard 71cdb7
+    unlink("prwv2_source");
Mark Wielaard 71cdb7
+    exit(EXIT_SUCCESS);
Mark Wielaard 71cdb7
+}
Mark Wielaard 71cdb7
diff --git a/memcheck/tests/linux/sys-preadv2_pwritev2.stderr.exp b/memcheck/tests/linux/sys-preadv2_pwritev2.stderr.exp
Mark Wielaard 71cdb7
new file mode 100644
Mark Wielaard 71cdb7
index 000000000..e11f2a51d
Mark Wielaard 71cdb7
--- /dev/null
Mark Wielaard 71cdb7
+++ b/memcheck/tests/linux/sys-preadv2_pwritev2.stderr.exp
Mark Wielaard 71cdb7
@@ -0,0 +1,56 @@
Mark Wielaard 71cdb7
+Syscall param pwritev2(vector) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:53)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param pwritev2(vector) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:54)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param pwritev2(vector) points to uninitialised byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:55)
Mark Wielaard 71cdb7
+ Address 0x........ is 0 bytes inside a block of size 16 alloc'd
Mark Wielaard 71cdb7
+   at 0x........: malloc (vg_replace_malloc.c:...)
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:48)
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param pwritev2(count) contains uninitialised byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:57)
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param pwritev2(flags) contains uninitialised byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:60)
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv2(vector) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:62)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv2(vector) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:63)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv2(vector) points to uninitialised byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:64)
Mark Wielaard 71cdb7
+ Address 0x........ is 0 bytes inside a block of size 16 alloc'd
Mark Wielaard 71cdb7
+   at 0x........: malloc (vg_replace_malloc.c:...)
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:48)
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv2(count) contains uninitialised byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:66)
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param pwritev2(vector[1]) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:71)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv2(vector[1]) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv2_pwritev2.c:72)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
diff --git a/memcheck/tests/linux/sys-preadv2_pwritev2.vgtest b/memcheck/tests/linux/sys-preadv2_pwritev2.vgtest
Mark Wielaard 71cdb7
new file mode 100644
Mark Wielaard 71cdb7
index 000000000..5cd23aacd
Mark Wielaard 71cdb7
--- /dev/null
Mark Wielaard 71cdb7
+++ b/memcheck/tests/linux/sys-preadv2_pwritev2.vgtest
Mark Wielaard 71cdb7
@@ -0,0 +1,3 @@
Mark Wielaard 71cdb7
+prereq: test -e sys-preadv2_pwritev2
Mark Wielaard 71cdb7
+prog: sys-preadv2_pwritev2
Mark Wielaard 71cdb7
+vgopts: -q
Mark Wielaard 71cdb7
diff --git a/memcheck/tests/linux/sys-preadv_pwritev.c b/memcheck/tests/linux/sys-preadv_pwritev.c
Mark Wielaard 71cdb7
new file mode 100644
Mark Wielaard 71cdb7
index 000000000..f5087dddc
Mark Wielaard 71cdb7
--- /dev/null
Mark Wielaard 71cdb7
+++ b/memcheck/tests/linux/sys-preadv_pwritev.c
Mark Wielaard 71cdb7
@@ -0,0 +1,77 @@
Mark Wielaard 71cdb7
+#define _GNU_SOURCE
Mark Wielaard 71cdb7
+#include <fcntl.h>
Mark Wielaard 71cdb7
+#include <stdio.h>
Mark Wielaard 71cdb7
+#include <stdlib.h>
Mark Wielaard 71cdb7
+#include <sys/stat.h>
Mark Wielaard 71cdb7
+#include <unistd.h>
Mark Wielaard 71cdb7
+#include <sys/syscall.h>
Mark Wielaard 71cdb7
+#include <sys/uio.h>
Mark Wielaard 71cdb7
+#include <string.h>
Mark Wielaard 71cdb7
+#include "../../memcheck.h"
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+#include <errno.h>
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+int main(int argc, char **argv)
Mark Wielaard 71cdb7
+{
Mark Wielaard 71cdb7
+    char str0[] = "hello ";
Mark Wielaard 71cdb7
+    char str1[] = "world\n";
Mark Wielaard 71cdb7
+    struct iovec iov[2];
Mark Wielaard 71cdb7
+    int fd;
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    fd = open("prwv_source", O_CREAT | O_RDWR, 0644);
Mark Wielaard 71cdb7
+    if (fd == -1) {
Mark Wielaard 71cdb7
+        perror("prwv2_source");
Mark Wielaard 71cdb7
+        exit(EXIT_FAILURE);
Mark Wielaard 71cdb7
+    }
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    iov[0].iov_base = str0;
Mark Wielaard 71cdb7
+    iov[0].iov_len = strlen(str0);
Mark Wielaard 71cdb7
+    iov[1].iov_base = str1;
Mark Wielaard 71cdb7
+    iov[1].iov_len = strlen(str1);
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    /* Check pwritev and preadv called with the correct arguments works. */
Mark Wielaard 71cdb7
+    if (pwritev(fd, iov, 2, 0) == -1) {
Mark Wielaard 71cdb7
+        perror("pwritev");
Mark Wielaard 71cdb7
+        exit(EXIT_FAILURE);
Mark Wielaard 71cdb7
+    }
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    if (preadv(fd, iov, 2, 0) == -1) {
Mark Wielaard 71cdb7
+        perror("preadv");
Mark Wielaard 71cdb7
+        printf("errno: %d\n", errno);
Mark Wielaard 71cdb7
+        exit(EXIT_FAILURE);
Mark Wielaard 71cdb7
+    }
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    /* Check valgrind will produce expected warnings for the
Mark Wielaard 71cdb7
+       various wrong arguments. */
Mark Wielaard 71cdb7
+    do {
Mark Wielaard 71cdb7
+        /* always allocate 16 bytes to not to have different .exps for different reg sizes */
Mark Wielaard 71cdb7
+        char *mem = malloc(16);
Mark Wielaard 71cdb7
+        void *t = (void *) &mem[0];
Mark Wielaard 71cdb7
+        void *z = (void *) -1;
Mark Wielaard 71cdb7
+        int c = *((int *) &mem[4]);
Mark Wielaard 71cdb7
+        pwritev(fd, NULL, 2, 0);
Mark Wielaard 71cdb7
+        pwritev(fd, z, 2, 0);
Mark Wielaard 71cdb7
+        pwritev(fd, t, 2, 0);
Mark Wielaard 71cdb7
+        pwritev(fd, iov, -1, 0);
Mark Wielaard 71cdb7
+        pwritev(fd, iov, c, 0);
Mark Wielaard 71cdb7
+        pwritev(fd, iov, 2, -5);
Mark Wielaard 71cdb7
+        pwritev(-1, iov, 2, -5);
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+        preadv(fd, NULL, 2, 0);
Mark Wielaard 71cdb7
+        preadv(fd, z, 2, 0);
Mark Wielaard 71cdb7
+        preadv(fd, t, 2, 0);
Mark Wielaard 71cdb7
+        preadv(fd, iov, -1, 0);
Mark Wielaard 71cdb7
+        preadv(fd, iov, c, 0);
Mark Wielaard 71cdb7
+        preadv(fd, iov, 2, -5);
Mark Wielaard 71cdb7
+        preadv(-1, iov, 2, -5);
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+        iov[1].iov_base = (void *) -1;
Mark Wielaard 71cdb7
+        pwritev(fd, iov, 2, 0);
Mark Wielaard 71cdb7
+        preadv(fd, iov, 2, 0);
Mark Wielaard 71cdb7
+        free(mem);
Mark Wielaard 71cdb7
+    } while (0);
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+    close(fd);
Mark Wielaard 71cdb7
+    unlink("prwv_source");
Mark Wielaard 71cdb7
+    exit(EXIT_SUCCESS);
Mark Wielaard 71cdb7
+}
Mark Wielaard 71cdb7
diff --git a/memcheck/tests/linux/sys-preadv_pwritev.stderr.exp b/memcheck/tests/linux/sys-preadv_pwritev.stderr.exp
Mark Wielaard 71cdb7
new file mode 100644
Mark Wielaard 71cdb7
index 000000000..4fede44d8
Mark Wielaard 71cdb7
--- /dev/null
Mark Wielaard 71cdb7
+++ b/memcheck/tests/linux/sys-preadv_pwritev.stderr.exp
Mark Wielaard 71cdb7
@@ -0,0 +1,52 @@
Mark Wielaard 71cdb7
+Syscall param pwritev(vector) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:52)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param pwritev(vector) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:53)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param pwritev(vector) points to uninitialised byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:54)
Mark Wielaard 71cdb7
+ Address 0x........ is 0 bytes inside a block of size 16 alloc'd
Mark Wielaard 71cdb7
+   at 0x........: malloc (vg_replace_malloc.c:...)
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:48)
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param pwritev(count) contains uninitialised byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:56)
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv(vector) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:60)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv(vector) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:61)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv(vector) points to uninitialised byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:62)
Mark Wielaard 71cdb7
+ Address 0x........ is 0 bytes inside a block of size 16 alloc'd
Mark Wielaard 71cdb7
+   at 0x........: malloc (vg_replace_malloc.c:...)
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:48)
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv(count) contains uninitialised byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:64)
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param pwritev(vector[1]) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:69)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
+Syscall param preadv(vector[1]) points to unaddressable byte(s)
Mark Wielaard 71cdb7
+   ...
Mark Wielaard 71cdb7
+   by 0x........: main (sys-preadv_pwritev.c:70)
Mark Wielaard 71cdb7
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
Mark Wielaard 71cdb7
+
Mark Wielaard 71cdb7
diff --git a/memcheck/tests/linux/sys-preadv_pwritev.vgtest b/memcheck/tests/linux/sys-preadv_pwritev.vgtest
Mark Wielaard 71cdb7
new file mode 100644
Mark Wielaard 71cdb7
index 000000000..f07dc2935
Mark Wielaard 71cdb7
--- /dev/null
Mark Wielaard 71cdb7
+++ b/memcheck/tests/linux/sys-preadv_pwritev.vgtest
Mark Wielaard 71cdb7
@@ -0,0 +1,3 @@
Mark Wielaard 71cdb7
+prereq: test -e sys-preadv_pwritev
Mark Wielaard 71cdb7
+prog: sys-preadv_pwritev
Mark Wielaard 71cdb7
+vgopts: -q
Mark Wielaard 71cdb7
Mark Wielaard 71cdb7
commit 514f899388e05142513ff3f679a9e0131145e34e
Mark Wielaard 71cdb7
Author: Mark Wielaard <mark@klomp.org>
Mark Wielaard 71cdb7
Date:   Wed Jul 3 10:27:17 2019 +0200
Mark Wielaard 71cdb7
Mark Wielaard 71cdb7
    Hook up preadv2 and pwritev2 correctly for arm64.
Mark Wielaard 71cdb7
    
Mark Wielaard 71cdb7
    Use the correct generic linux sys wrapper.
Mark Wielaard 71cdb7
    
Mark Wielaard 71cdb7
    Followup for https://bugs.kde.org/408414
Mark Wielaard 71cdb7
Mark Wielaard 71cdb7
diff --git a/coregrind/m_syswrap/syswrap-arm64-linux.c b/coregrind/m_syswrap/syswrap-arm64-linux.c
Mark Wielaard 71cdb7
index d12d40632..91329b682 100644
Mark Wielaard 71cdb7
--- a/coregrind/m_syswrap/syswrap-arm64-linux.c
Mark Wielaard 71cdb7
+++ b/coregrind/m_syswrap/syswrap-arm64-linux.c
Mark Wielaard 71cdb7
@@ -818,8 +818,8 @@ static SyscallTableEntry syscall_main_table[] = {
Mark Wielaard 71cdb7
    LINX_(__NR_membarrier,        sys_membarrier),        // 283
Mark Wielaard 71cdb7
    //   (__NR_mlock2,            sys_ni_syscall),        // 284
Mark Wielaard 71cdb7
    LINX_(__NR_copy_file_range,   sys_copy_file_range),   // 285
Mark Wielaard 71cdb7
-   LINX_(__NR_preadv2,           sys_ni_syscall),        // 286
Mark Wielaard 71cdb7
-   LINX_(__NR_pwritev2,          sys_ni_syscall),        // 287
Mark Wielaard 71cdb7
+   LINXY(__NR_preadv2,           sys_preadv2),           // 286
Mark Wielaard 71cdb7
+   LINX_(__NR_pwritev2,          sys_pwritev2),          // 287
Mark Wielaard 71cdb7
    //   (__NR_pkey_mprotect,     sys_ni_syscall),        // 288
Mark Wielaard 71cdb7
    //   (__NR_pkey_alloc,        sys_ni_syscall),        // 289
Mark Wielaard 71cdb7
    //   (__NR_pkey_free,         sys_ni_syscall),        // 290