]> granicus.if.org Git - strace/commitdiff
io: use umoven_or_printaddr_ignore_syserror as umove function in tprint_iov_upto
authorEugene Syromyatnikov <evgsyr@gmail.com>
Fri, 14 Oct 2016 23:30:47 +0000 (02:30 +0300)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 28 Oct 2016 18:40:11 +0000 (18:40 +0000)
This enables printing of iovec arrays even in case of failed syscall
(failed syscall doesn't mean that iovec itself is inaccessible and
useless).  One caveat here is that we should explicitly provide proper
IOV_DECODE_* value based on syserror value in case printing is performed
on exiting; we can't simply override it to IOV_DECODE_ADDR on exiting
when syserror is up, since this may be called by code which tries to
print iovec containing local data, which should be perfectly accessible
(on the other hand, there are no cases of such behaviour at the moment).

Since iovecs themselves are printed even if syscall has failed now,
preadv test is updated to reflect this.  It is notable, though, that this
is the only place where this case is checked.

* io.c (tprint_iov_upto): Specify umoven_or_printaddr_ignore_syserror
instead of umoven_or_printaddr as umoven_func parameter.
(SYS_FUNC(readv), do_preadv): Specify decode_iov parameter value
based on syserror(tcp) value.
* scsi.c: (print_sg_io_v3_res, print_sg_io_v4_res): Likewise.
* tests/preadv.c: Update expected output for the case when preadv
with singe-item iovec failed.

io.c
scsi.c
tests/preadv.c

diff --git a/io.c b/io.c
index 8a93cb89c19b207da1aa26a73705f3e8bfa01375..fe865a5dfe12dc88a6c8d0d045628bb881220e3f 100644 (file)
--- a/io.c
+++ b/io.c
@@ -119,7 +119,7 @@ tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr,
                { .decode_iov = decode_iov, .data_size = data_size };
 
        print_array(tcp, addr, len, iov, current_wordsize * 2,
-                   umoven_or_printaddr, print_iovec, &config);
+                   umoven_or_printaddr_ignore_syserror, print_iovec, &config);
 }
 
 void
@@ -136,6 +136,7 @@ SYS_FUNC(readv)
                tprints(", ");
        } else {
                tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1],
+                               syserror(tcp) ? IOV_DECODE_ADDR :
                                IOV_DECODE_STR, tcp->u_rval);
                tprintf(", %lu", tcp->u_arg[2]);
        }
@@ -226,8 +227,9 @@ do_preadv(struct tcb *tcp, const int flags_arg)
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
        } else {
-               tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR,
-                               tcp->u_rval);
+               tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1],
+                               syserror(tcp) ? IOV_DECODE_ADDR :
+                               IOV_DECODE_STR, tcp->u_rval);
                tprintf(", %lu, ", tcp->u_arg[2]);
                print_lld_from_low_high_val(tcp, 3);
                if (flags_arg >= 0) {
diff --git a/scsi.c b/scsi.c
index 979c3428d442f7aace819491294b634b682c8ab2..b3c6245308b7e887cfba5cc4b5f2418dacfde3a9 100644 (file)
--- a/scsi.c
+++ b/scsi.c
@@ -114,8 +114,8 @@ print_sg_io_v3_res(struct tcb *tcp, const long arg)
                if (sg_io.iovec_count)
                        tprint_iov_upto(tcp, sg_io.iovec_count,
                                        (unsigned long) sg_io.dxferp,
-                                       IOV_DECODE_STR,
-                                       din_len);
+                                       syserror(tcp) ? IOV_DECODE_ADDR :
+                                       IOV_DECODE_STR, din_len);
                else
                        print_sg_io_buffer(tcp, (unsigned long) sg_io.dxferp,
                                           din_len);
@@ -190,6 +190,7 @@ print_sg_io_v4_res(struct tcb *tcp, const long arg)
        tprintf(", din[%u]=", din_len);
        if (sg_io.din_iovec_count)
                tprint_iov_upto(tcp, sg_io.din_iovec_count, sg_io.din_xferp,
+                               syserror(tcp) ? IOV_DECODE_ADDR :
                                IOV_DECODE_STR, din_len);
        else
                print_sg_io_buffer(tcp, sg_io.din_xferp, din_len);
index eb53a5e9782cf72cbab2ec8b97799a04cc2ed595..2243eb87ecd657bb4f0cedef053a5ba0cccf9380 100644 (file)
@@ -82,7 +82,8 @@ main(void)
 
        if (preadv(0, iov, 1, -1) != -1)
                perror_msg_and_fail("preadv");
-       printf("preadv(0, %p, 1, -1) = -1 EINVAL (%m)\n", iov);
+       printf("preadv(0, [{iov_base=%p, iov_len=%zu}], 1, -1) = "
+              "-1 EINVAL (%m)\n", iov->iov_base, iov->iov_len);
 
        if (preadv(0, NULL, 1, -2) != -1)
                perror_msg_and_fail("preadv");