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 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
     45 		tprintf(", %lu", 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 	printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
     55 	tprintf(", %lu", tcp->u_arg[2]);
     56 
     57 	return RVAL_DECODED;
     58 }
     59 
     60 /*
     61  * data_size limits the cumulative size of printed data.
     62  * Example: recvmsg returing a short read.
     63  */
     64 void
     65 tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov, unsigned long data_size)
     66 {
     67 	unsigned long iov[2];
     68 	unsigned long size, cur, end, abbrev_end;
     69 	const unsigned long sizeof_iov = current_wordsize * 2;
     70 
     71 	if (!len) {
     72 		tprints("[]");
     73 		return;
     74 	}
     75 	size = len * sizeof_iov;
     76 	end = addr + size;
     77 	if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
     78 	    !addr || size / sizeof_iov != len || end < addr) {
     79 		printaddr(addr);
     80 		return;
     81 	}
     82 	if (abbrev(tcp)) {
     83 		abbrev_end = addr + max_strlen * sizeof_iov;
     84 		if (abbrev_end < addr)
     85 			abbrev_end = end;
     86 	} else {
     87 		abbrev_end = end;
     88 	}
     89 	tprints("[");
     90 	for (cur = addr; cur < end; cur += sizeof_iov) {
     91 		if (cur > addr)
     92 			tprints(", ");
     93 		if (cur >= abbrev_end) {
     94 			tprints("...");
     95 			break;
     96 		}
     97 		if (umove_ulong_array_or_printaddr(tcp, cur, iov,
     98 						   ARRAY_SIZE(iov)))
     99 			break;
    100 		tprints("{");
    101 		if (decode_iov) {
    102 			unsigned long len = iov[1];
    103 			if (len > data_size)
    104 				len = data_size;
    105 			data_size -= len;
    106 			printstr(tcp, iov[0], len);
    107 		} else
    108 			printaddr(iov[0]);
    109 		tprintf(", %lu}", iov[1]);
    110 	}
    111 	tprints("]");
    112 }
    113 
    114 void
    115 tprint_iov(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov)
    116 {
    117 	tprint_iov_upto(tcp, len, addr, decode_iov, (unsigned long) -1L);
    118 }
    119 
    120 SYS_FUNC(readv)
    121 {
    122 	if (entering(tcp)) {
    123 		printfd(tcp, tcp->u_arg[0]);
    124 		tprints(", ");
    125 	} else {
    126 		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    127 		tprintf(", %lu", tcp->u_arg[2]);
    128 	}
    129 	return 0;
    130 }
    131 
    132 SYS_FUNC(writev)
    133 {
    134 	printfd(tcp, tcp->u_arg[0]);
    135 	tprints(", ");
    136 	tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    137 	tprintf(", %lu", tcp->u_arg[2]);
    138 
    139 	return RVAL_DECODED;
    140 }
    141 
    142 /* The SH4 ABI does allow long longs in odd-numbered registers, but
    143    does not allow them to be split between registers and memory - and
    144    there are only four argument registers for normal functions.  As a
    145    result pread takes an extra padding argument before the offset.  This
    146    was changed late in the 2.4 series (around 2.4.20).  */
    147 #if defined(SH)
    148 #define PREAD_OFFSET_ARG 4
    149 #else
    150 #define PREAD_OFFSET_ARG 3
    151 #endif
    152 
    153 SYS_FUNC(pread)
    154 {
    155 	if (entering(tcp)) {
    156 		printfd(tcp, tcp->u_arg[0]);
    157 		tprints(", ");
    158 	} else {
    159 		if (syserror(tcp))
    160 			printaddr(tcp->u_arg[1]);
    161 		else
    162 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
    163 		tprintf(", %lu, ", tcp->u_arg[2]);
    164 		printllval(tcp, "%llu", PREAD_OFFSET_ARG);
    165 	}
    166 	return 0;
    167 }
    168 
    169 SYS_FUNC(pwrite)
    170 {
    171 	printfd(tcp, tcp->u_arg[0]);
    172 	tprints(", ");
    173 	printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    174 	tprintf(", %lu, ", tcp->u_arg[2]);
    175 	printllval(tcp, "%llu", PREAD_OFFSET_ARG);
    176 
    177 	return RVAL_DECODED;
    178 }
    179 
    180 static void
    181 print_llu_from_low_high_val(struct tcb *tcp, int arg)
    182 {
    183 #if SIZEOF_LONG == SIZEOF_LONG_LONG
    184 # if SUPPORTED_PERSONALITIES > 1
    185 #  ifdef X86_64
    186 	if (current_personality != 1)
    187 #  else
    188 	if (current_wordsize == sizeof(long))
    189 #  endif
    190 # endif
    191 		tprintf("%lu", (unsigned long) tcp->u_arg[arg]);
    192 # if SUPPORTED_PERSONALITIES > 1
    193 	else
    194 		tprintf("%lu",
    195 			((unsigned long) tcp->u_arg[arg + 1] << current_wordsize * 8)
    196 			| (unsigned long) tcp->u_arg[arg]);
    197 # endif
    198 #else
    199 # ifdef X32
    200 	if (current_personality == 0)
    201 		tprintf("%llu", (unsigned long long) tcp->ext_arg[arg]);
    202 	else
    203 # endif
    204 	tprintf("%llu",
    205 		((unsigned long long) (unsigned long) tcp->u_arg[arg + 1] << sizeof(long) * 8)
    206 		| (unsigned long long) (unsigned long) tcp->u_arg[arg]);
    207 #endif
    208 }
    209 
    210 SYS_FUNC(preadv)
    211 {
    212 	if (entering(tcp)) {
    213 		printfd(tcp, tcp->u_arg[0]);
    214 		tprints(", ");
    215 	} else {
    216 		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    217 		tprintf(", %lu, ", tcp->u_arg[2]);
    218 		print_llu_from_low_high_val(tcp, 3);
    219 	}
    220 	return 0;
    221 }
    222 
    223 SYS_FUNC(pwritev)
    224 {
    225 	printfd(tcp, tcp->u_arg[0]);
    226 	tprints(", ");
    227 	tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    228 	tprintf(", %lu, ", tcp->u_arg[2]);
    229 	print_llu_from_low_high_val(tcp, 3);
    230 
    231 	return RVAL_DECODED;
    232 }
    233 
    234 #include "xlat/splice_flags.h"
    235 
    236 SYS_FUNC(tee)
    237 {
    238 	/* int fd_in */
    239 	printfd(tcp, tcp->u_arg[0]);
    240 	tprints(", ");
    241 	/* int fd_out */
    242 	printfd(tcp, tcp->u_arg[1]);
    243 	tprints(", ");
    244 	/* size_t len */
    245 	tprintf("%lu, ", tcp->u_arg[2]);
    246 	/* unsigned int flags */
    247 	printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
    248 
    249 	return RVAL_DECODED;
    250 }
    251 
    252 SYS_FUNC(splice)
    253 {
    254 	/* int fd_in */
    255 	printfd(tcp, tcp->u_arg[0]);
    256 	tprints(", ");
    257 	/* loff_t *off_in */
    258 	printnum_int64(tcp, tcp->u_arg[1], "%" PRIu64);
    259 	tprints(", ");
    260 	/* int fd_out */
    261 	printfd(tcp, tcp->u_arg[2]);
    262 	tprints(", ");
    263 	/* loff_t *off_out */
    264 	printnum_int64(tcp, tcp->u_arg[3], "%" PRIu64);
    265 	tprints(", ");
    266 	/* size_t len */
    267 	tprintf("%lu, ", tcp->u_arg[4]);
    268 	/* unsigned int flags */
    269 	printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???");
    270 
    271 	return RVAL_DECODED;
    272 }
    273 
    274 SYS_FUNC(vmsplice)
    275 {
    276 	/* int fd */
    277 	printfd(tcp, tcp->u_arg[0]);
    278 	tprints(", ");
    279 	/* const struct iovec *iov, unsigned long nr_segs */
    280 	tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    281 	tprintf(", %lu, ", tcp->u_arg[2]);
    282 	/* unsigned int flags */
    283 	printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
    284 
    285 	return RVAL_DECODED;
    286 }
    287