]> granicus.if.org Git - strace/commitdiff
Mpersify fetchers of struct msghdr and struct mmsghdr
authorDmitry V. Levin <ldv@altlinux.org>
Mon, 27 Jun 2016 00:02:50 +0000 (00:02 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 27 Jun 2016 00:10:58 +0000 (00:10 +0000)
* fetch_struct_msghdr.c: New file.
* fetch_struct_mmsghdr.c: Likewise.
* Makefile.am (strace_SOURCES): Add them.
* net.c (struct msghdr32, struct mmsghdr32, copy_from_msghdr32,
fetch_msghdr, fetch_mmsghdr): Remove.
(decode_msghdr, dumpiov_in_msghdr): Use fetch_struct_msghdr instead
of fetch_msghdr.
(decode_mmsghdr): Change msg_len argument to use_msg_len.
Use fetch_struct_mmsghdr instead of fetch_mmsghdr.
Return fetch_struct_mmsghdr's return code.
(decode_mmsg): Rename to decode_mmsgvec.  Take addr and len arguments.
Do not print vlen and flags.  Check decode_mmsghdr's return code.
Print mmsghdr array using square brackets.
(dumpiov_in_mmsghdr): Use fetch_struct_mmsghdr instead of fetch_mmsghdr.
(SYS_FUNC(sendmmsg), SYS_FUNC(recvmmsg)): Use decode_mmsgvec instead
of decode_mmsg.  Print vlen and flags.
* tests/mmsg.c (main): Update expected output.

Makefile.am
fetch_struct_mmsghdr.c [new file with mode: 0644]
fetch_struct_msghdr.c [new file with mode: 0644]
net.c
tests/mmsg.c

index 1a578376b0a5d76d6a867c204109c7801cb41111..b310ec9a6788b8412a66538f9c2852df0539e751 100644 (file)
@@ -108,6 +108,8 @@ strace_SOURCES =    \
        fcntl.c         \
        fetch_seccomp_fprog.c \
        fetch_struct_flock.c \
+       fetch_struct_mmsghdr.c \
+       fetch_struct_msghdr.c \
        fetch_struct_statfs.c \
        file.c          \
        file_handle.c   \
diff --git a/fetch_struct_mmsghdr.c b/fetch_struct_mmsghdr.c
new file mode 100644 (file)
index 0000000..932de69
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "defs.h"
+
+#include DEF_MPERS_TYPE(struct_mmsghdr)
+
+#include "msghdr.h"
+typedef struct mmsghdr struct_mmsghdr;
+
+#include MPERS_DEFS
+
+/*
+ * On success, return the number of fetched bytes.
+ * On error, return 0;
+ *
+ * This function cannot use umove_or_printaddr because
+ * it is called by dumpio and therefore cannot print anything.
+ */
+
+MPERS_PRINTER_DECL(int, fetch_struct_mmsghdr,
+                  struct tcb *tcp, const unsigned long addr, void *p)
+{
+       struct mmsghdr *p_native = p;
+       struct_mmsghdr v_compat;
+
+       if (sizeof(*p_native) == sizeof(v_compat))
+               return umove(tcp, addr, p_native) ? 0 : sizeof(*p_native);
+
+       if (umove(tcp, addr, &v_compat))
+               return 0;
+
+       p_native->msg_hdr.msg_name = (void *) (unsigned long)
+        v_compat.msg_hdr.msg_name;
+
+       p_native->msg_hdr.msg_namelen =
+        v_compat.msg_hdr.msg_namelen;
+
+       p_native->msg_hdr.msg_iov = (void *) (unsigned long)
+        v_compat.msg_hdr.msg_iov;
+
+       p_native->msg_hdr.msg_iovlen =
+        v_compat.msg_hdr.msg_iovlen;
+
+       p_native->msg_hdr.msg_control = (void *) (unsigned long)
+        v_compat.msg_hdr.msg_control;
+
+       p_native->msg_hdr.msg_controllen =
+        v_compat.msg_hdr.msg_controllen;
+
+       p_native->msg_hdr.msg_flags =
+        v_compat.msg_hdr.msg_flags;
+
+       p_native->msg_len =
+        v_compat.msg_len;
+
+       return sizeof(v_compat);
+}
diff --git a/fetch_struct_msghdr.c b/fetch_struct_msghdr.c
new file mode 100644 (file)
index 0000000..78b505b
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "defs.h"
+
+#include DEF_MPERS_TYPE(struct_msghdr)
+
+#include "msghdr.h"
+typedef struct msghdr struct_msghdr;
+
+#include MPERS_DEFS
+
+/*
+ * On success, return the number of fetched bytes.
+ * On error, return 0;
+ *
+ * This function cannot use umove_or_printaddr because
+ * it is called by dumpio and therefore cannot print anything.
+ */
+
+MPERS_PRINTER_DECL(int, fetch_struct_msghdr,
+                  struct tcb *tcp, const unsigned long addr, void *p)
+{
+       struct msghdr *p_native = p;
+       struct_msghdr v_compat;
+
+       if (sizeof(*p_native) == sizeof(v_compat))
+               return umove(tcp, addr, p_native) ? 0 : sizeof(*p_native);
+
+       if (umove(tcp, addr, &v_compat))
+               return 0;
+
+       p_native->msg_name = (void *) (unsigned long)
+        v_compat.msg_name;
+
+       p_native->msg_namelen =
+        v_compat.msg_namelen;
+
+       p_native->msg_iov = (void *) (unsigned long)
+        v_compat.msg_iov;
+
+       p_native->msg_iovlen =
+        v_compat.msg_iovlen;
+
+       p_native->msg_control = (void *) (unsigned long)
+        v_compat.msg_control;
+
+       p_native->msg_controllen =
+        v_compat.msg_controllen;
+
+       p_native->msg_flags =
+        v_compat.msg_flags;
+
+       return sizeof(v_compat);
+}
diff --git a/net.c b/net.c
index 3a7f94036bb2f74379c0e1c3890fe0015a66f917..7616a5b93a8ee7d6ad16578b6701310460de869c 100644 (file)
--- a/net.c
+++ b/net.c
@@ -427,80 +427,12 @@ print_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size)
        tprints("}");
 }
 
-struct msghdr32 {
-       uint32_t /* void* */    msg_name;
-       uint32_t /* socklen_t */msg_namelen;
-       uint32_t /* iovec* */   msg_iov;
-       uint32_t /* size_t */   msg_iovlen;
-       uint32_t /* void* */    msg_control;
-       uint32_t /* size_t */   msg_controllen;
-       uint32_t /* int */      msg_flags;
-};
-struct mmsghdr32 {
-       struct msghdr32         msg_hdr;
-       uint32_t /* unsigned */ msg_len;
-};
-
-#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
-static void
-copy_from_msghdr32(struct msghdr *to_msg, struct msghdr32 *from_msg32)
-{
-       to_msg->msg_name       = (void*)(long)from_msg32->msg_name;
-       to_msg->msg_namelen    =              from_msg32->msg_namelen;
-       to_msg->msg_iov        = (void*)(long)from_msg32->msg_iov;
-       to_msg->msg_iovlen     =              from_msg32->msg_iovlen;
-       to_msg->msg_control    = (void*)(long)from_msg32->msg_control;
-       to_msg->msg_controllen =              from_msg32->msg_controllen;
-       to_msg->msg_flags      =              from_msg32->msg_flags;
-}
-#endif
-
-static bool
-fetch_msghdr(struct tcb *tcp, long addr, struct msghdr *msg)
-{
-#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
-       if (current_wordsize == 4) {
-               struct msghdr32 msg32;
-
-               if (umove(tcp, addr, &msg32) < 0)
-                       return false;
-               copy_from_msghdr32(msg, &msg32);
-       } else
-#endif
-       if (umove(tcp, addr, msg) < 0)
-               return false;
-       return true;
-}
-
-static bool
-fetch_mmsghdr(struct tcb *tcp, long addr, unsigned int idx, struct mmsghdr *mmsg)
-{
-#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
-       if (current_wordsize == 4) {
-               struct mmsghdr32 mmsg32;
-
-               addr += sizeof(struct mmsghdr32) * idx;
-               if (umove(tcp, addr, &mmsg32) < 0)
-                       return false;
-
-               copy_from_msghdr32(&mmsg->msg_hdr, &mmsg32.msg_hdr);
-               mmsg->msg_len = mmsg32.msg_len;
-       } else
-#endif
-       {
-               addr += sizeof(*mmsg) * idx;
-               if (umove(tcp, addr, mmsg) < 0)
-                       return false;
-       }
-       return true;
-}
-
 static void
 decode_msghdr(struct tcb *tcp, long addr, unsigned long data_size)
 {
        struct msghdr msg;
 
-       if (verbose(tcp) && fetch_msghdr(tcp, addr, &msg))
+       if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg))
                print_msghdr(tcp, &msg, data_size);
        else
                printaddr(addr);
@@ -511,62 +443,63 @@ dumpiov_in_msghdr(struct tcb *tcp, long addr, unsigned long data_size)
 {
        struct msghdr msg;
 
-       if (fetch_msghdr(tcp, addr, &msg))
+       if (fetch_struct_msghdr(tcp, addr, &msg))
                dumpiov_upto(tcp, msg.msg_iovlen, (long)msg.msg_iov, data_size);
 }
 
-static void
-decode_mmsghdr(struct tcb *tcp, long addr, unsigned int idx, unsigned long msg_len)
+static int
+decode_mmsghdr(struct tcb *tcp, long addr, bool use_msg_len)
 {
        struct mmsghdr mmsg;
+       int fetched = fetch_struct_mmsghdr(tcp, addr, &mmsg);
 
-       if (fetch_mmsghdr(tcp, addr, idx, &mmsg)) {
+       if (fetched) {
                tprints("{");
-               print_msghdr(tcp, &mmsg.msg_hdr, msg_len ? msg_len : mmsg.msg_len);
+               print_msghdr(tcp, &mmsg.msg_hdr, use_msg_len ? mmsg.msg_len : -1UL);
                tprintf(", %u}", mmsg.msg_len);
-       }
-       else
+       } else {
                printaddr(addr);
+       }
+
+       return fetched;
 }
 
 static void
-decode_mmsg(struct tcb *tcp, unsigned long msg_len)
+decode_mmsgvec(struct tcb *tcp, unsigned long addr, unsigned int len,
+              bool use_msg_len)
 {
-       /* mmsgvec */
        if (syserror(tcp)) {
-               printaddr(tcp->u_arg[1]);
+               printaddr(addr);
        } else {
-               unsigned int len = tcp->u_rval;
-               unsigned int i;
+               unsigned int i, fetched;
 
-               tprints("{");
-               for (i = 0; i < len; ++i) {
+               tprints("[");
+               for (i = 0; i < len; ++i, addr += fetched) {
                        if (i)
                                tprints(", ");
-                       decode_mmsghdr(tcp, tcp->u_arg[1], i, msg_len);
+                       fetched = decode_mmsghdr(tcp, addr, use_msg_len);
+                       if (!fetched)
+                               break;
                }
-               tprints("}");
+               tprints("]");
        }
-       /* vlen */
-       tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
-       /* flags */
-       printflags(msg_flags, tcp->u_arg[3], "MSG_???");
 }
 
 void
 dumpiov_in_mmsghdr(struct tcb *tcp, long addr)
 {
        unsigned int len = tcp->u_rval;
-       unsigned int i;
+       unsigned int i, fetched;
        struct mmsghdr mmsg;
 
-       for (i = 0; i < len; ++i) {
-               if (fetch_mmsghdr(tcp, addr, i, &mmsg)) {
-                       tprintf(" = %lu buffers in vector %u\n",
-                               (unsigned long)mmsg.msg_hdr.msg_iovlen, i);
-                       dumpiov_upto(tcp, mmsg.msg_hdr.msg_iovlen,
-                               (long)mmsg.msg_hdr.msg_iov, mmsg.msg_len);
-               }
+       for (i = 0; i < len; ++i, addr += fetched) {
+               fetched = fetch_struct_mmsghdr(tcp, addr, &mmsg);
+               if (!fetched)
+                       break;
+               tprintf(" = %lu buffers in vector %u\n",
+                       (unsigned long)mmsg.msg_hdr.msg_iovlen, i);
+               dumpiov_upto(tcp, mmsg.msg_hdr.msg_iovlen,
+                       (long)mmsg.msg_hdr.msg_iov, mmsg.msg_len);
        }
 }
 
@@ -727,12 +660,18 @@ SYS_FUNC(sendmmsg)
                tprints(", ");
                if (!verbose(tcp)) {
                        printaddr(tcp->u_arg[1]);
+                       /* vlen */
                        tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
+                       /* flags */
                        printflags(msg_flags, tcp->u_arg[3], "MSG_???");
+                       return RVAL_DECODED;
                }
        } else {
-               if (verbose(tcp))
-                       decode_mmsg(tcp, (unsigned long) -1L);
+               decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval, false);
+               /* vlen */
+               tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
+               /* flags */
+               printflags(msg_flags, tcp->u_arg[3], "MSG_???");
        }
        return 0;
 }
@@ -820,7 +759,9 @@ SYS_FUNC(recvmmsg)
                        tcp->auxstr = sprint_timespec(tcp, tcp->u_arg[4]);
                } else {
                        printaddr(tcp->u_arg[1]);
+                       /* vlen */
                        tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
+                       /* flags */
                        printflags(msg_flags, tcp->u_arg[3], "MSG_???");
                        tprints(", ");
                        print_timespec(tcp, tcp->u_arg[4]);
@@ -828,7 +769,11 @@ SYS_FUNC(recvmmsg)
                return 0;
        } else {
                if (verbose(tcp)) {
-                       decode_mmsg(tcp, 0);
+                       decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval, true);
+                       /* vlen */
+                       tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
+                       /* flags */
+                       printflags(msg_flags, tcp->u_arg[3], "MSG_???");
                        tprints(", ");
                        /* timeout on entrance */
                        tprints(tcp->auxstr);
index 00e1ef33ac4de2a85ce6027332b9070297cd63ae..d82b7cddf848a6f2a969ef7b7869ad477d909606 100644 (file)
@@ -139,12 +139,12 @@ main(void)
                perror_msg_and_skip("sendmmsg");
        assert(r == (int) n_w_mmh);
        assert(close(1) == 0);
-       tprintf("sendmmsg(1, {{{msg_name=NULL, msg_namelen=0"
+       tprintf("sendmmsg(1, [{{msg_name=NULL, msg_namelen=0"
                ", msg_iov=[{\"%s\", %u}, {\"%s\", %u}], msg_iovlen=%u"
                ", msg_controllen=0, msg_flags=0}, %u}"
                ", {{msg_name=NULL, msg_namelen=0"
                ", msg_iov=[{\"%s\", %u}], msg_iovlen=%u"
-               ", msg_controllen=0, msg_flags=0}, %u}}, %u"
+               ", msg_controllen=0, msg_flags=0}, %u}], %u"
                ", MSG_DONTROUTE|MSG_NOSIGNAL) = %d\n"
                " = %u buffers in vector 0\n"
                " * %u bytes in buffer 0\n"
@@ -213,12 +213,12 @@ main(void)
 
        assert(recv_mmsg(0, r_mmh, n_r_mmh, MSG_DONTWAIT, NULL) == (int) n_r_mmh);
        assert(close(0) == 0);
-       tprintf("recvmmsg(0, {{{msg_name=NULL, msg_namelen=0"
+       tprintf("recvmmsg(0, [{{msg_name=NULL, msg_namelen=0"
                ", msg_iov=[{\"%s\", %u}], msg_iovlen=%u"
                ", msg_controllen=0, msg_flags=0}, %u}"
                ", {{msg_name=NULL, msg_namelen=0"
                ", msg_iov=[{\"%s\", %u}, {\"\", %u}], msg_iovlen=%u"
-               ", msg_controllen=0, msg_flags=0}, %u}}, %u"
+               ", msg_controllen=0, msg_flags=0}, %u}], %u"
                ", MSG_DONTWAIT, NULL) = %d (left NULL)\n"
                " = %u buffers in vector 0\n"
                " * %u bytes in buffer 0\n"