]> granicus.if.org Git - strace/commitdiff
Make umoven report success as 0, not >=0, stop returning success on partial reads
authorBen Noordhuis <info@bnoordhuis.nl>
Tue, 26 Feb 2013 11:24:25 +0000 (12:24 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 26 Feb 2013 11:24:25 +0000 (12:24 +0100)
umoven() uses process_vm_readv() when available but it returns the
return value of that syscall, which is the number of bytes copied,
while its callers expect it to simply return zero on success.

It was causing syscalls that take a user-space argument to print
the abbreviated version, e.g.:

  epoll_ctl(5, EPOLL_CTL_ADD, 10, {...})

Instead of:

  epoll_ctl(5, EPOLL_CTL_ADD, 10, {EPOLLIN, {u32=10, u64=10}})

* util.c (umoven): Make umove[n] report success as 0, not >=0,
stop returning "success" on partial reads.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
util.c

diff --git a/util.c b/util.c
index 405670e60ef9a2a85f876a7e5d1ee5e1cd0a6ccf..88798c0a1cfc484022bb312da1fb901e8faa5571 100644 (file)
--- a/util.c
+++ b/util.c
@@ -777,7 +777,7 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
 {
        int pid = tcp->pid;
        int n, m;
-       int started;
+       //int started;
        union {
                long val;
                char x[sizeof(long)];
@@ -800,6 +800,8 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
                                remote, 1,
                                /*flags:*/ 0
                );
+               if (r == len)
+                       return 0;
                if (r < 0) {
                        if (errno == ENOSYS)
                                process_vm_readv_not_supported = 1;
@@ -807,13 +809,12 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
                                /* EINVAL or ESRCH could be seen if process is gone,
                                 * all the rest is strange and should be reported. */
                                perror_msg("%s", "process_vm_readv");
-                       goto vm_readv_didnt_work;
+               } else {
+                       perror_msg("process_vm_readv: short read (%d < %d)", r, len);
                }
-               return r;
        }
- vm_readv_didnt_work:
 
-       started = 0;
+       //started = 0;
        if (addr & (sizeof(long) - 1)) {
                /* addr not a multiple of sizeof(long) */
                n = addr - (addr & -sizeof(long)); /* residue */
@@ -826,7 +827,7 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
                                perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
                        return -1;
                }
-               started = 1;
+               //started = 1;
                m = MIN(sizeof(long) - n, len);
                memcpy(laddr, &u.x[n], m);
                addr += sizeof(long), laddr += m, len -= m;
@@ -835,15 +836,19 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
                errno = 0;
                u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
                if (errno) {
+#if 0
+//FIXME: wrong. printpath doesn't use this routine. Callers expect full copies.
+//Ok to remove?
                        if (started && (errno==EPERM || errno==EIO)) {
                                /* Ran into 'end of memory' - stupid "printpath" */
                                return 0;
                        }
+#endif
                        if (addr != 0 && errno != EIO && errno != ESRCH)
                                perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
                        return -1;
                }
-               started = 1;
+               //started = 1;
                m = MIN(sizeof(long), len);
                memcpy(laddr, u.x, m);
                addr += sizeof(long), laddr += m, len -= m;