]> granicus.if.org Git - strace/blobdiff - mmsghdr.c
Introduce generic STRINGIFY and STRINGIFY_VAL macros
[strace] / mmsghdr.c
index 2364fef2638521eab17a4076fa0f346ea9b0c595..c9e6cf0b15f24d6019fd923bd0630c3334f739aa 100644 (file)
--- a/mmsghdr.c
+++ b/mmsghdr.c
@@ -33,7 +33,8 @@
 #include <limits.h>
 
 static int
-fetch_struct_mmsghdr_or_printaddr(struct tcb *tcp, const long addr,
+fetch_struct_mmsghdr_or_printaddr(struct tcb *const tcp,
+                                 const kernel_ulong_t addr,
                                  const unsigned int len, void *const mh)
 {
        if ((entering(tcp) || !syserror(tcp))
@@ -47,6 +48,7 @@ fetch_struct_mmsghdr_or_printaddr(struct tcb *tcp, const long addr,
 
 struct print_struct_mmsghdr_config {
        const int *p_user_msg_namelen;
+       unsigned int msg_len_vlen;
        unsigned int count;
        bool use_msg_len;
 };
@@ -66,29 +68,88 @@ print_struct_mmsghdr(struct tcb *tcp, void *elem_buf,
 
        tprints("{msg_hdr=");
        print_struct_msghdr(tcp, &mmsg->msg_hdr, c->p_user_msg_namelen,
-                           c->use_msg_len ? mmsg->msg_len : -1UL);
-       tprintf(", msg_len=%u}", mmsg->msg_len);
+                           c->use_msg_len ? mmsg->msg_len : (kernel_ulong_t) -1);
+       if (c->msg_len_vlen) {
+               tprintf(", msg_len=%u", mmsg->msg_len);
+               --c->msg_len_vlen;
+       }
+       tprints("}");
+
+       if (c->p_user_msg_namelen)
+               ++c->p_user_msg_namelen;
 
        return true;
 }
 
 static void
-decode_mmsgvec(struct tcb *tcp, const unsigned long addr,
-              const unsigned int len, const bool use_msg_len)
+free_mmsgvec_data(void *ptr)
+{
+       char **pstr = ptr;
+       free(*pstr);
+       *pstr = 0;
+
+       free(ptr);
+}
+
+struct mmsgvec_data {
+       char *timeout;
+       unsigned int count;
+       int namelen[IOV_MAX];
+};
+
+static void
+save_mmsgvec_namelen(struct tcb *const tcp, kernel_ulong_t addr,
+                    unsigned int len, const char *const timeout)
+{
+       if (len > IOV_MAX)
+               len = IOV_MAX;
+
+       const size_t data_size = offsetof(struct mmsgvec_data, namelen)
+                                + sizeof(int) * len;
+       struct mmsgvec_data *const data = xmalloc(data_size);
+       data->timeout = xstrdup(timeout);
+
+       unsigned int i, fetched;
+
+       for (i = 0; i < len; ++i, addr += fetched) {
+               struct mmsghdr mh;
+
+               fetched = fetch_struct_mmsghdr(tcp, addr, &mh);
+               if (!fetched)
+                       break;
+               data->namelen[i] = mh.msg_hdr.msg_namelen;
+       }
+       data->count = i;
+
+       set_tcb_priv_data(tcp, data, free_mmsgvec_data);
+}
+
+static void
+decode_mmsgvec(struct tcb *const tcp, const kernel_ulong_t addr,
+              const unsigned int vlen, const unsigned int msg_len_vlen,
+              const bool use_msg_len)
 {
        struct mmsghdr mmsg;
        struct print_struct_mmsghdr_config c = {
+               .msg_len_vlen = msg_len_vlen,
                .count = IOV_MAX,
                .use_msg_len = use_msg_len
        };
+       const struct mmsgvec_data *const data = get_tcb_priv_data(tcp);
+
+       if (data) {
+               if (data->count < c.count)
+                       c.count = data->count;
+               c.p_user_msg_namelen = data->namelen;
+       }
 
-       print_array(tcp, addr, len, &mmsg, sizeof_struct_mmsghdr(),
+       print_array(tcp, addr, vlen, &mmsg, sizeof_struct_mmsghdr(),
                    fetch_struct_mmsghdr_or_printaddr,
                    print_struct_mmsghdr, &c);
 }
 
 void
-dumpiov_in_mmsghdr(struct tcb *tcp, long addr)
+dumpiov_in_mmsghdr(struct tcb *const tcp, kernel_ulong_t addr)
 {
        unsigned int len = tcp->u_rval;
        unsigned int i, fetched;
@@ -98,10 +159,11 @@ dumpiov_in_mmsghdr(struct tcb *tcp, long addr)
                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);
+               tprintf(" = %" PRI_klu " buffers in vector %u\n",
+                       (kernel_ulong_t) mmsg.msg_hdr.msg_iovlen, i);
                dumpiov_upto(tcp, mmsg.msg_hdr.msg_iovlen,
-                       (long) mmsg.msg_hdr.msg_iov, mmsg.msg_len);
+                            ptr_to_kulong(mmsg.msg_hdr.msg_iov),
+                            mmsg.msg_len);
        }
 }
 
@@ -112,6 +174,7 @@ SYS_FUNC(sendmmsg)
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
                if (!verbose(tcp)) {
+                       /* msgvec */
                        printaddr(tcp->u_arg[1]);
                        /* vlen */
                        tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
@@ -120,7 +183,13 @@ SYS_FUNC(sendmmsg)
                        return RVAL_DECODED;
                }
        } else {
-               decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval, false);
+               const unsigned int msg_len_vlen =
+                       syserror(tcp) ? 0 : tcp->u_rval;
+               /* msgvec */
+               temporarily_clear_syserror(tcp);
+               decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_arg[2],
+                              msg_len_vlen, false);
+               restore_cleared_syserror(tcp);
                /* vlen */
                tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
                /* flags */
@@ -135,9 +204,10 @@ SYS_FUNC(recvmmsg)
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
                if (verbose(tcp)) {
-                       char *sts = xstrdup(sprint_timespec(tcp, tcp->u_arg[4]));
-                       set_tcb_priv_data(tcp, sts, free);
+                       save_mmsgvec_namelen(tcp, tcp->u_arg[1], tcp->u_arg[2],
+                                            sprint_timespec(tcp, tcp->u_arg[4]));
                } else {
+                       /* msgvec */
                        printaddr(tcp->u_arg[1]);
                        /* vlen */
                        tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
@@ -149,14 +219,16 @@ SYS_FUNC(recvmmsg)
                return 0;
        } else {
                if (verbose(tcp)) {
-                       decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval, true);
+                       /* msgvec */
+                       decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval,
+                                      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(get_tcb_priv_data(tcp));
+                       tprints(*(const char **) get_tcb_priv_data(tcp));
                }
                if (syserror(tcp))
                        return 0;