Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl>
      3  * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl>
      4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com>
      5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl>
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "defs.h"
     32 #include <fcntl.h>
     33 #include <sys/uio.h>
     34 
     35 SYS_FUNC(read)
     36 {
     37 	if (entering(tcp)) {
     38 		printfd(tcp, tcp->u_arg[0]);
     39 		tprints(", ");
     40 	} else {
     41 		if (syserror(tcp))
     42 			printaddr(tcp->u_arg[1]);
     43 		else
     44 			printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
     45 		tprintf(", %" PRI_klu, tcp->u_arg[2]);
     46 	}
     47 	return 0;
     48 }
     49 
     50 SYS_FUNC(write)
     51 {
     52 	printfd(tcp, tcp->u_arg[0]);
     53 	tprints(", ");
     54 	printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
     55 	tprintf(", %" PRI_klu, tcp->u_arg[2]);
     56 
     57 	return RVAL_DECODED;
     58 }
     59 
     60 struct print_iovec_config {
     61 	enum iov_decode decode_iov;
     62 	kernel_ulong_t data_size;
     63 };
     64 
     65 static bool
     66 print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
     67 {
     68 	const kernel_ulong_t *iov;
     69 	kernel_ulong_t iov_buf[2], len;
     70 	struct print_iovec_config *c = data;
     71 
     72         if (elem_size < sizeof(iov_buf)) {
     73 		iov_buf[0] = ((unsigned int *) elem_buf)[0];
     74 		iov_buf[1] = ((unsigned int *) elem_buf)[1];
     75 		iov = iov_buf;
     76 	} else {
     77 		iov = elem_buf;
     78 	}
     79 
     80 	tprints("{iov_base=");
     81 
     82 	len = iov[1];
     83 
     84 	switch (c->decode_iov) {
     85 		case IOV_DECODE_STR:
     86 			if (len > c->data_size)
     87 				len = c->data_size;
     88 			if (c->data_size != (kernel_ulong_t) -1)
     89 				c->data_size -= len;
     90 			printstrn(tcp, iov[0], len);
     91 			break;
     92 		case IOV_DECODE_NETLINK:
     93 			if (len > c->data_size)
     94 				len = c->data_size;
     95 			if (c->data_size != (kernel_ulong_t) -1)
     96 				c->data_size -= len;
     97 			decode_netlink(tcp, iov[0], iov[1]);
     98 			break;
     99 		default:
    100 			printaddr(iov[0]);
    101 			break;
    102 	}
    103 
    104 	tprintf(", iov_len=%" PRI_klu "}", iov[1]);
    105 
    106 	return true;
    107 }
    108 
    109 /*
    110  * data_size limits the cumulative size of printed data.
    111  * Example: recvmsg returing a short read.
    112  */
    113 void
    114 tprint_iov_upto(struct tcb *const tcp, const kernel_ulong_t len,
    115 		const kernel_ulong_t addr, const enum iov_decode decode_iov,
    116 		const kernel_ulong_t data_size)
    117 {
    118 	kernel_ulong_t iov[2];
    119 	struct print_iovec_config config =
    120 		{ .decode_iov = decode_iov, .data_size = data_size };
    121 
    122 	print_array(tcp, addr, len, iov, current_wordsize * 2,
    123 		    umoven_or_printaddr_ignore_syserror, print_iovec, &config);
    124 }
    125 
    126 SYS_FUNC(readv)
    127 {
    128 	if (entering(tcp)) {
    129 		printfd(tcp, tcp->u_arg[0]);
    130 		tprints(", ");
    131 	} else {
    132 		tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1],
    133 				syserror(tcp) ? IOV_DECODE_ADDR :
    134 				IOV_DECODE_STR, tcp->u_rval);
    135 		tprintf(", %" PRI_klu, tcp->u_arg[2]);
    136 	}
    137 	return 0;
    138 }
    139 
    140 SYS_FUNC(writev)
    141 {
    142 	printfd(tcp, tcp->u_arg[0]);
    143 	tprints(", ");
    144 	tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR);
    145 	tprintf(", %" PRI_klu, tcp->u_arg[2]);
    146 
    147 	return RVAL_DECODED;
    148 }
    149 
    150 SYS_FUNC(pread)
    151 {
    152 	if (entering(tcp)) {
    153 		printfd(tcp, tcp->u_arg[0]);
    154 		tprints(", ");
    155 	} else {
    156 		if (syserror(tcp))
    157 			printaddr(tcp->u_arg[1]);
    158 		else
    159 			printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
    160 		tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
    161 		printllval(tcp, "%lld", 3);
    162 	}
    163 	return 0;
    164 }
    165 
    166 SYS_FUNC(pwrite)
    167 {
    168 	printfd(tcp, tcp->u_arg[0]);
    169 	tprints(", ");
    170 	printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    171 	tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
    172 	printllval(tcp, "%lld", 3);
    173 
    174 	return RVAL_DECODED;
    175 }
    176 
    177 static void
    178 print_lld_from_low_high_val(struct tcb *tcp, int arg)
    179 {
    180 #if SIZEOF_KERNEL_LONG_T > 4
    181 # ifndef current_klongsize
    182 	if (current_klongsize < SIZEOF_KERNEL_LONG_T) {
    183 		tprintf("%" PRI_kld, (tcp->u_arg[arg + 1] << 32)
    184 			       | tcp->u_arg[arg]);
    185 	} else
    186 # endif /* !current_klongsize */
    187 	{
    188 		tprintf("%" PRI_kld, tcp->u_arg[arg]);
    189 	}
    190 #else /* SIZEOF_KERNEL_LONG_T == 4 */
    191 	tprintf("%lld",
    192 		  ((long long) tcp->u_arg[arg + 1] << 32)
    193 		| ((long long) tcp->u_arg[arg]));
    194 #endif
    195 }
    196 
    197 #include "xlat/rwf_flags.h"
    198 
    199 static int
    200 do_preadv(struct tcb *tcp, const int flags_arg)
    201 {
    202 	if (entering(tcp)) {
    203 		printfd(tcp, tcp->u_arg[0]);
    204 		tprints(", ");
    205 	} else {
    206 		kernel_ulong_t len =
    207 			truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
    208 
    209 		tprint_iov_upto(tcp, len, tcp->u_arg[1],
    210 				syserror(tcp) ? IOV_DECODE_ADDR :
    211 				IOV_DECODE_STR, tcp->u_rval);
    212 		tprintf(", %" PRI_klu ", ", len);
    213 		print_lld_from_low_high_val(tcp, 3);
    214 		if (flags_arg >= 0) {
    215 			tprints(", ");
    216 			printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
    217 		}
    218 	}
    219 	return 0;
    220 }
    221 
    222 SYS_FUNC(preadv)
    223 {
    224 	return do_preadv(tcp, -1);
    225 }
    226 
    227 SYS_FUNC(preadv2)
    228 {
    229 	return do_preadv(tcp, 5);
    230 }
    231 
    232 static int
    233 do_pwritev(struct tcb *tcp, const int flags_arg)
    234 {
    235 	kernel_ulong_t len =
    236 		truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
    237 
    238 	printfd(tcp, tcp->u_arg[0]);
    239 	tprints(", ");
    240 	tprint_iov(tcp, len, tcp->u_arg[1], IOV_DECODE_STR);
    241 	tprintf(", %" PRI_klu ", ", len);
    242 	print_lld_from_low_high_val(tcp, 3);
    243 	if (flags_arg >= 0) {
    244 		tprints(", ");
    245 		printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
    246 	}
    247 
    248 	return RVAL_DECODED;
    249 }
    250 
    251 SYS_FUNC(pwritev)
    252 {
    253 	return do_pwritev(tcp, -1);
    254 }
    255 
    256 SYS_FUNC(pwritev2)
    257 {
    258 	return do_pwritev(tcp, 5);
    259 }
    260 
    261 #include "xlat/splice_flags.h"
    262 
    263 SYS_FUNC(tee)
    264 {
    265 	/* int fd_in */
    266 	printfd(tcp, tcp->u_arg[0]);
    267 	tprints(", ");
    268 	/* int fd_out */
    269 	printfd(tcp, tcp->u_arg[1]);
    270 	tprints(", ");
    271 	/* size_t len */
    272 	tprintf("%" PRI_klu ", ", tcp->u_arg[2]);
    273 	/* unsigned int flags */
    274 	printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
    275 
    276 	return RVAL_DECODED;
    277 }
    278 
    279 SYS_FUNC(splice)
    280 {
    281 	/* int fd_in */
    282 	printfd(tcp, tcp->u_arg[0]);
    283 	tprints(", ");
    284 	/* loff_t *off_in */
    285 	printnum_int64(tcp, tcp->u_arg[1], "%" PRId64);
    286 	tprints(", ");
    287 	/* int fd_out */
    288 	printfd(tcp, tcp->u_arg[2]);
    289 	tprints(", ");
    290 	/* loff_t *off_out */
    291 	printnum_int64(tcp, tcp->u_arg[3], "%" PRId64);
    292 	tprints(", ");
    293 	/* size_t len */
    294 	tprintf("%" PRI_klu ", ", tcp->u_arg[4]);
    295 	/* unsigned int flags */
    296 	printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???");
    297 
    298 	return RVAL_DECODED;
    299 }
    300 
    301 SYS_FUNC(vmsplice)
    302 {
    303 	/* int fd */
    304 	printfd(tcp, tcp->u_arg[0]);
    305 	tprints(", ");
    306 	/* const struct iovec *iov, unsigned long nr_segs */
    307 	tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR);
    308 	tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
    309 	/* unsigned int flags */
    310 	printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
    311 
    312 	return RVAL_DECODED;
    313 }
    314