From: Dmitry V. Levin Date: Tue, 15 Sep 2015 02:17:32 +0000 (+0000) Subject: Add a new helper function umove_ulong_array_or_printaddr X-Git-Tag: v4.11~202 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b172a94d0263f163d33e0f2a0395267719916576;p=strace Add a new helper function umove_ulong_array_or_printaddr * 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. --- diff --git a/defs.h b/defs.h index 8833dfc8..cad250a4 100644 --- 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 91b2be93..ea9f3bd5 100644 --- 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 dcc38599..0cdc469f 100644 --- 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 e7ce07a0..2cfe1381 100644 --- a/kexec.c +++ b/kexec.c @@ -11,48 +11,21 @@ #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 afd298ec..c3e3fdaf 100644 --- 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.