X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=io.c;h=cd803057b32131931eab75decbcb7ae9809f2a61;hb=217eccfba5224fc47be2bd7b5b8b9b28b4fedf98;hp=dbef2e65b83eb2f9bb28ed6d789f032136c92070;hpb=a1e94e9c7af845c06cd447ca12eec2641ceb4e7c;p=strace diff --git a/io.c b/io.c index dbef2e65..cd803057 100644 --- a/io.c +++ b/io.c @@ -3,6 +3,7 @@ * Copyright (c) 1993 Branko Lankester * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey * Copyright (c) 1996-1999 Wichert Akkerman + * Copyright (c) 1999-2018 The strace developers. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,7 +70,7 @@ print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) kernel_ulong_t iov_buf[2], len; struct print_iovec_config *c = data; - if (elem_size < sizeof(iov_buf)) { + if (elem_size < sizeof(iov_buf)) { iov_buf[0] = ((unsigned int *) elem_buf)[0]; iov_buf[1] = ((unsigned int *) elem_buf)[1]; iov = iov_buf; @@ -94,7 +95,8 @@ print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) len = c->data_size; if (c->data_size != (kernel_ulong_t) -1) c->data_size -= len; - decode_netlink(tcp, iov[0], iov[1]); + /* assume that the descriptor is 1st syscall argument */ + decode_netlink(tcp, tcp->u_arg[0], iov[0], len); break; default: printaddr(iov[0]); @@ -116,11 +118,12 @@ tprint_iov_upto(struct tcb *const tcp, const kernel_ulong_t len, const kernel_ulong_t data_size) { kernel_ulong_t iov[2]; - struct print_iovec_config config = - { .decode_iov = decode_iov, .data_size = data_size }; + struct print_iovec_config config = { + .decode_iov = decode_iov, .data_size = data_size + }; print_array(tcp, addr, len, iov, current_wordsize * 2, - umoven_or_printaddr_ignore_syserror, print_iovec, &config); + tfetch_mem_ignore_syserror, print_iovec, &config); } SYS_FUNC(readv) @@ -177,33 +180,20 @@ SYS_FUNC(pwrite) static void print_lld_from_low_high_val(struct tcb *tcp, int arg) { -#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG +#if SIZEOF_KERNEL_LONG_T > 4 # ifndef current_klongsize - if (current_klongsize < SIZEOF_LONG) { - tprintf("%" PRI_kld, (tcp->u_arg[arg + 1] << current_wordsize * 8) + if (current_klongsize < SIZEOF_KERNEL_LONG_T) { + tprintf("%" PRI_kld, (tcp->u_arg[arg + 1] << 32) | tcp->u_arg[arg]); } else # endif /* !current_klongsize */ { tprintf("%" PRI_kld, tcp->u_arg[arg]); } -#elif SIZEOF_LONG > 4 -# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG -#elif SIZEOF_KERNEL_LONG_T > SIZEOF_LONG -# ifndef current_klongsize - if (current_klongsize < SIZEOF_LONG_LONG) { - tprintf("%lld", - (zero_extend_signed_to_ull(tcp->u_arg[arg + 1]) << sizeof(long) * 8) - | zero_extend_signed_to_ull(tcp->u_arg[arg])); - } else -# endif /* !current_klongsize */ - { - tprintf("%" PRI_kld, tcp->u_arg[arg]); - } -#else /* SIZEOF_LONG_LONG > SIZEOF_LONG && SIZEOF_KERNEL_LONG_T == SIZEOF_LONG */ +#else /* SIZEOF_KERNEL_LONG_T == 4 */ tprintf("%lld", - (zero_extend_signed_to_ull(tcp->u_arg[arg + 1]) << sizeof(long) * 8) - | zero_extend_signed_to_ull(tcp->u_arg[arg])); + ((long long) tcp->u_arg[arg + 1] << 32) + | ((long long) tcp->u_arg[arg])); #endif } @@ -216,12 +206,13 @@ do_preadv(struct tcb *tcp, const int flags_arg) printfd(tcp, tcp->u_arg[0]); tprints(", "); } else { - unsigned long len = widen_to_ulong(tcp->u_arg[2]); + kernel_ulong_t len = + truncate_kulong_to_current_wordsize(tcp->u_arg[2]); tprint_iov_upto(tcp, len, tcp->u_arg[1], syserror(tcp) ? IOV_DECODE_ADDR : IOV_DECODE_STR, tcp->u_rval); - tprintf(", %lu, ", len); + tprintf(", %" PRI_klu ", ", len); print_lld_from_low_high_val(tcp, 3); if (flags_arg >= 0) { tprints(", "); @@ -236,20 +227,16 @@ SYS_FUNC(preadv) return do_preadv(tcp, -1); } -SYS_FUNC(preadv2) -{ - return do_preadv(tcp, 5); -} - static int do_pwritev(struct tcb *tcp, const int flags_arg) { - unsigned long len = widen_to_ulong(tcp->u_arg[2]); + kernel_ulong_t len = + truncate_kulong_to_current_wordsize(tcp->u_arg[2]); printfd(tcp, tcp->u_arg[0]); tprints(", "); tprint_iov(tcp, len, tcp->u_arg[1], IOV_DECODE_STR); - tprintf(", %lu, ", len); + tprintf(", %" PRI_klu ", ", len); print_lld_from_low_high_val(tcp, 3); if (flags_arg >= 0) { tprints(", "); @@ -264,9 +251,29 @@ SYS_FUNC(pwritev) return do_pwritev(tcp, -1); } +/* + * x32 is the only architecture where preadv2 takes 5 arguments + * instead of 6, see preadv64v2 in kernel sources. + * Likewise, x32 is the only architecture where pwritev2 takes 5 arguments + * instead of 6, see pwritev64v2 in kernel sources. + */ + +#if defined X86_64 +# define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 2 ? 4 : 5) +#elif defined X32 +# define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 0 ? 4 : 5) +#else +# define PREADV2_PWRITEV2_FLAGS_ARG_NO 5 +#endif + +SYS_FUNC(preadv2) +{ + return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO); +} + SYS_FUNC(pwritev2) { - return do_pwritev(tcp, 5); + return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO); } #include "xlat/splice_flags.h"