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:
parent
4b38ce956c
commit
9a8216ea7b
@ -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
82
fetch_struct_mmsghdr.c
Normal 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
79
fetch_struct_msghdr.c
Normal 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
145
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);
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user