Mpersify fetchers of struct msghdr and struct mmsghdr
* 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.
diff --git a/Makefile.am b/Makefile.am
index 1a57837..b310ec9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -108,6 +108,8 @@
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
index 0000000..932de69
--- /dev/null
+++ b/fetch_struct_mmsghdr.c
@@ -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
index 0000000..78b505b
--- /dev/null
+++ b/fetch_struct_msghdr.c
@@ -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 3a7f940..7616a5b 100644
--- a/net.c
+++ b/net.c
@@ -427,80 +427,12 @@
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 @@
{
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 @@
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 @@
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 @@
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);
diff --git a/tests/mmsg.c b/tests/mmsg.c
index 00e1ef3..d82b7cd 100644
--- a/tests/mmsg.c
+++ b/tests/mmsg.c
@@ -139,12 +139,12 @@
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 @@
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"