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.
This commit is contained in:
Дмитрий Левин 2016-06-27 00:02:50 +00:00
parent 4b38ce956c
commit 9a8216ea7b
5 changed files with 212 additions and 104 deletions

View 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 \

82
fetch_struct_mmsghdr.c Normal file
View File

@ -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);
}

79
fetch_struct_msghdr.c Normal file
View File

@ -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);
}

145
net.c
View File

@ -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);

View 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"