]> granicus.if.org Git - strace/commitdiff
Add a new helper function umove_ulong_array_or_printaddr
authorDmitry V. Levin <ldv@altlinux.org>
Tue, 15 Sep 2015 02:17:32 +0000 (02:17 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Tue, 15 Sep 2015 11:23:27 +0000 (11:23 +0000)
* defs.h (umove_ulong_array_or_printaddr): New prototype.
* util.c (umove_ulong_array_or_printaddr): New function.
* desc.c (sys_pselect6): Use it instead of open-coding
a proxy struct parser for different personalities.
* io.c (tprint_iov_upto): Use it instead of open-coding
a struct iovec parser for different personalities.
* kexec.c (print_kexec_segments): Use it instead of open-coding
a struct kexec_segment parser for different personalities.
(print_seg): Pass arguments using an array.

defs.h
desc.c
io.c
kexec.c
util.c

diff --git a/defs.h b/defs.h
index 8833dfc88c10af853b9023c0a5cc336695b415b4..cad250a4d4cb257d74a333d1e3bfbf95c7a70d3f 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -542,6 +542,7 @@ extern int umoven_or_printaddr(struct tcb *, long, unsigned int, void *);
 #define umove_or_printaddr(pid, addr, objp)    \
        umoven_or_printaddr((pid), (addr), sizeof(*(objp)), (void *) (objp))
 extern int umove_ulong_or_printaddr(struct tcb *, long, unsigned long *);
+extern int umove_ulong_array_or_printaddr(struct tcb *, long, unsigned long *, size_t);
 extern int umovestr(struct tcb *, long, unsigned int, char *);
 extern int upeek(int pid, long, long *);
 
diff --git a/desc.c b/desc.c
index 91b2be93c14f283d4604e1ed0e1fc4e04f270d58..ea9f3bd598029f4672c068d5b3195e604c956ca8 100644 (file)
--- a/desc.c
+++ b/desc.c
@@ -441,30 +441,15 @@ SYS_FUNC(pselect6)
 {
        int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
        if (entering(tcp)) {
-               long r;
-               struct {
-                       unsigned long ptr;
-                       unsigned long len;
-               } data;
+               unsigned long data[2];
 
                tprints(", ");
-#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
-               if (current_wordsize == 4) {
-                       struct {
-                               uint32_t ptr;
-                               uint32_t len;
-                       } data32;
-                       r = umove_or_printaddr(tcp, tcp->u_arg[5], &data32);
-                       data.ptr = data32.ptr;
-                       data.len = data32.len;
-               } else
-#endif
-                       r = umove_or_printaddr(tcp, tcp->u_arg[5], &data);
-               if (r == 0) {
+               if (!umove_ulong_array_or_printaddr(tcp, tcp->u_arg[5], data,
+                                                   ARRAY_SIZE(data))) {
                        tprints("{");
-                       /* NB: kernel requires data.len == NSIG / 8 */
-                       print_sigset_addr_len(tcp, data.ptr, data.len);
-                       tprintf(", %lu}", data.len);
+                       /* NB: kernel requires data[1] == NSIG / 8 */
+                       print_sigset_addr_len(tcp, data[0], data[1]);
+                       tprintf(", %lu}", data[1]);
                }
        }
        return rc;
diff --git a/io.c b/io.c
index dcc38599b249b1e4359d73b4290747b8a4ded2af..0cdc469fc30b1ca5018cde7422a13c54477efc5f 100644 (file)
--- a/io.c
+++ b/io.c
@@ -64,24 +64,9 @@ SYS_FUNC(write)
 void
 tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov, unsigned long data_size)
 {
-#if SUPPORTED_PERSONALITIES > 1
-       union {
-               struct { u_int32_t base; u_int32_t len; } iov32;
-               struct { u_int64_t base; u_int64_t len; } iov64;
-       } iov;
-#define sizeof_iov \
-       (current_wordsize == 4 ? sizeof(iov.iov32) : sizeof(iov.iov64))
-#define iov_iov_base \
-       (current_wordsize == 4 ? (uint64_t) iov.iov32.base : iov.iov64.base)
-#define iov_iov_len \
-       (current_wordsize == 4 ? (uint64_t) iov.iov32.len : iov.iov64.len)
-#else
-       struct iovec iov;
-#define sizeof_iov sizeof(iov)
-#define iov_iov_base iov.iov_base
-#define iov_iov_len iov.iov_len
-#endif
+       unsigned long iov[2];
        unsigned long size, cur, end, abbrev_end;
+       const unsigned long sizeof_iov = current_wordsize * 2;
 
        if (!len) {
                tprints("[]");
@@ -109,23 +94,21 @@ tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int deco
                        tprints("...");
                        break;
                }
-               if (umoven_or_printaddr(tcp, cur, sizeof_iov, &iov))
+               if (umove_ulong_array_or_printaddr(tcp, cur, iov,
+                                                  ARRAY_SIZE(iov)))
                        break;
                tprints("{");
                if (decode_iov) {
-                       unsigned long len = iov_iov_len;
+                       unsigned long len = iov[1];
                        if (len > data_size)
                                len = data_size;
                        data_size -= len;
-                       printstr(tcp, (long) iov_iov_base, len);
+                       printstr(tcp, iov[0], len);
                } else
-                       printaddr((long) iov_iov_base);
-               tprintf(", %lu}", (unsigned long)iov_iov_len);
+                       printaddr(iov[0]);
+               tprintf(", %lu}", iov[1]);
        }
        tprints("]");
-#undef sizeof_iov
-#undef iov_iov_base
-#undef iov_iov_len
 }
 
 void
diff --git a/kexec.c b/kexec.c
index e7ce07a056887a8be1066d553d5a940ce5ef20e6..2cfe1381ca92f0f75544fe8631dc29a6c6d173c3 100644 (file)
--- a/kexec.c
+++ b/kexec.c
 #endif
 
 static void
-print_seg(const long seg_buf, const unsigned long seg_bufsz,
-         const long seg_mem, const unsigned long seg_memsz)
+print_seg(const unsigned long *seg)
 {
        tprints("{");
-       printaddr(seg_buf);
-       tprintf(", %lu, ", seg_bufsz);
-       printaddr(seg_mem);
-       tprintf(", %lu}", seg_memsz);
+       printaddr(seg[0]);
+       tprintf(", %lu, ", seg[1]);
+       printaddr(seg[2]);
+       tprintf(", %lu}", seg[3]);
 }
 
 static void
 print_kexec_segments(struct tcb *tcp, const unsigned long addr,
                     const unsigned long len)
 {
-#if SUPPORTED_PERSONALITIES > 1
-       union {
-               struct { u_int32_t buf, bufsz, mem, memsz; } seg32;
-               struct { u_int64_t buf, bufsz, mem, memsz; } seg64;
-       } seg;
-# define sizeof_seg \
-       (current_wordsize == 4 ? sizeof(seg.seg32) : sizeof(seg.seg64))
-# define seg_buf \
-       (current_wordsize == 4 ? (uint64_t) seg.seg32.buf : seg.seg64.buf)
-# define seg_bufsz \
-       (current_wordsize == 4 ? (uint64_t) seg.seg32.bufsz : seg.seg64.bufsz)
-# define seg_mem \
-       (current_wordsize == 4 ? (uint64_t) seg.seg32.mem : seg.seg64.mem)
-# define seg_memsz \
-       (current_wordsize == 4 ? (uint64_t) seg.seg32.memsz : seg.seg64.memsz)
-#else
-       struct {
-               void *buf;
-               size_t bufsz;
-               void *mem;
-               size_t memsz;
-       } seg;
-# define sizeof_seg sizeof(seg)
-# define seg_buf seg.buf
-# define seg_bufsz seg.bufsz
-# define seg_mem seg.mem
-# define seg_memsz seg.memsz
-#endif
+       unsigned long seg[4];
+       const size_t sizeof_seg = ARRAY_SIZE(seg) * current_wordsize;
        unsigned int i;
 
        if (!len) {
@@ -65,20 +38,19 @@ print_kexec_segments(struct tcb *tcp, const unsigned long addr,
                return;
        }
 
-       if (umoven_or_printaddr(tcp, addr, sizeof_seg, &seg))
+       if (umove_ulong_array_or_printaddr(tcp, addr, seg, ARRAY_SIZE(seg)))
                return;
 
        tprints("[");
-       print_seg((unsigned long) seg_buf, seg_bufsz,
-                 (unsigned long) seg_mem, seg_memsz);
+       print_seg(seg);
 
        for (i = 1; i < len; ++i) {
                tprints(", ");
-               if (umoven_or_printaddr(tcp, addr + i * sizeof_seg,
-                                       sizeof_seg, &seg))
+               if (umove_ulong_array_or_printaddr(tcp,
+                                                  addr + i * sizeof_seg,
+                                                  seg, ARRAY_SIZE(seg)))
                        break;
-               print_seg((unsigned long) seg_buf, seg_bufsz,
-                         (unsigned long) seg_mem, seg_memsz);
+               print_seg(seg);
        }
 
        tprints("]");
diff --git a/util.c b/util.c
index afd298ec433c5734b450f6732729b13a6740ee93..c3e3fdaf9a2180699123af4ad2241f59850b9825 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1145,6 +1145,24 @@ umove_ulong_or_printaddr(struct tcb *tcp, const long addr, unsigned long *ptr)
        return umove_or_printaddr(tcp, addr, ptr);
 }
 
+int
+umove_ulong_array_or_printaddr(struct tcb *tcp, const long addr,
+                              unsigned long *ptr, size_t n)
+{
+       if (current_wordsize < sizeof(*ptr)) {
+               uint32_t ptr32[n];
+               int r = umove_or_printaddr(tcp, addr, &ptr32);
+               if (!r) {
+                       size_t i;
+
+                       for (i = 0; i < n; ++i)
+                               ptr[i] = (unsigned long) ptr32[i];
+               }
+               return r;
+       }
+       return umoven_or_printaddr(tcp, addr, n * sizeof(*ptr), ptr);
+}
+
 /*
  * Like `umove' but make the additional effort of looking
  * for a terminating zero byte.