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 #if HAVE_SYS_UIO_H
     34 # include <sys/uio.h>
     35 #endif
     36 
     37 int
     38 sys_read(struct tcb *tcp)
     39 {
     40 	if (entering(tcp)) {
     41 		printfd(tcp, tcp->u_arg[0]);
     42 		tprints(", ");
     43 	} else {
     44 		if (syserror(tcp))
     45 			tprintf("%#lx", tcp->u_arg[1]);
     46 		else
     47 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
     48 		tprintf(", %lu", tcp->u_arg[2]);
     49 	}
     50 	return 0;
     51 }
     52 
     53 int
     54 sys_write(struct tcb *tcp)
     55 {
     56 	if (entering(tcp)) {
     57 		printfd(tcp, tcp->u_arg[0]);
     58 		tprints(", ");
     59 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
     60 		tprintf(", %lu", tcp->u_arg[2]);
     61 	}
     62 	return 0;
     63 }
     64 
     65 #if HAVE_SYS_UIO_H
     66 /*
     67  * data_size limits the cumulative size of printed data.
     68  * Example: recvmsg returing a short read.
     69  */
     70 void
     71 tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov, unsigned long data_size)
     72 {
     73 #if SUPPORTED_PERSONALITIES > 1
     74 	union {
     75 		struct { u_int32_t base; u_int32_t len; } iov32;
     76 		struct { u_int64_t base; u_int64_t len; } iov64;
     77 	} iov;
     78 #define sizeof_iov \
     79 	(current_wordsize == 4 ? sizeof(iov.iov32) : sizeof(iov.iov64))
     80 #define iov_iov_base \
     81 	(current_wordsize == 4 ? (uint64_t) iov.iov32.base : iov.iov64.base)
     82 #define iov_iov_len \
     83 	(current_wordsize == 4 ? (uint64_t) iov.iov32.len : iov.iov64.len)
     84 #else
     85 	struct iovec iov;
     86 #define sizeof_iov sizeof(iov)
     87 #define iov_iov_base iov.iov_base
     88 #define iov_iov_len iov.iov_len
     89 #endif
     90 	unsigned long size, cur, end, abbrev_end;
     91 	int failed = 0;
     92 
     93 	if (!len) {
     94 		tprints("[]");
     95 		return;
     96 	}
     97 	size = len * sizeof_iov;
     98 	end = addr + size;
     99 	if (!verbose(tcp) || size / sizeof_iov != len || end < addr) {
    100 		tprintf("%#lx", addr);
    101 		return;
    102 	}
    103 	if (abbrev(tcp)) {
    104 		abbrev_end = addr + max_strlen * sizeof_iov;
    105 		if (abbrev_end < addr)
    106 			abbrev_end = end;
    107 	} else {
    108 		abbrev_end = end;
    109 	}
    110 	tprints("[");
    111 	for (cur = addr; cur < end; cur += sizeof_iov) {
    112 		if (cur > addr)
    113 			tprints(", ");
    114 		if (cur >= abbrev_end) {
    115 			tprints("...");
    116 			break;
    117 		}
    118 		if (umoven(tcp, cur, sizeof_iov, (char *) &iov) < 0) {
    119 			tprints("?");
    120 			failed = 1;
    121 			break;
    122 		}
    123 		tprints("{");
    124 		if (decode_iov) {
    125 			unsigned long len = iov_iov_len;
    126 			if (len > data_size)
    127 				len = data_size;
    128 			data_size -= len;
    129 			printstr(tcp, (long) iov_iov_base, len);
    130 		} else
    131 			tprintf("%#lx", (long) iov_iov_base);
    132 		tprintf(", %lu}", (unsigned long)iov_iov_len);
    133 	}
    134 	tprints("]");
    135 	if (failed)
    136 		tprintf(" %#lx", addr);
    137 #undef sizeof_iov
    138 #undef iov_iov_base
    139 #undef iov_iov_len
    140 }
    141 
    142 void
    143 tprint_iov(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov)
    144 {
    145 	tprint_iov_upto(tcp, len, addr, decode_iov, (unsigned long) -1L);
    146 }
    147 
    148 int
    149 sys_readv(struct tcb *tcp)
    150 {
    151 	if (entering(tcp)) {
    152 		printfd(tcp, tcp->u_arg[0]);
    153 		tprints(", ");
    154 	} else {
    155 		if (syserror(tcp)) {
    156 			tprintf("%#lx, %lu",
    157 					tcp->u_arg[1], tcp->u_arg[2]);
    158 			return 0;
    159 		}
    160 		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    161 		tprintf(", %lu", tcp->u_arg[2]);
    162 	}
    163 	return 0;
    164 }
    165 
    166 int
    167 sys_writev(struct tcb *tcp)
    168 {
    169 	if (entering(tcp)) {
    170 		printfd(tcp, tcp->u_arg[0]);
    171 		tprints(", ");
    172 		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    173 		tprintf(", %lu", tcp->u_arg[2]);
    174 	}
    175 	return 0;
    176 }
    177 #endif
    178 
    179 /* The SH4 ABI does allow long longs in odd-numbered registers, but
    180    does not allow them to be split between registers and memory - and
    181    there are only four argument registers for normal functions.  As a
    182    result pread takes an extra padding argument before the offset.  This
    183    was changed late in the 2.4 series (around 2.4.20).  */
    184 #if defined(SH)
    185 #define PREAD_OFFSET_ARG 4
    186 #else
    187 #define PREAD_OFFSET_ARG 3
    188 #endif
    189 
    190 int
    191 sys_pread(struct tcb *tcp)
    192 {
    193 	if (entering(tcp)) {
    194 		printfd(tcp, tcp->u_arg[0]);
    195 		tprints(", ");
    196 	} else {
    197 		if (syserror(tcp))
    198 			tprintf("%#lx", tcp->u_arg[1]);
    199 		else
    200 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
    201 		tprintf(", %lu, ", tcp->u_arg[2]);
    202 		printllval_aligned(tcp, "%llu", PREAD_OFFSET_ARG);
    203 	}
    204 	return 0;
    205 }
    206 
    207 int
    208 sys_pwrite(struct tcb *tcp)
    209 {
    210 	if (entering(tcp)) {
    211 		printfd(tcp, tcp->u_arg[0]);
    212 		tprints(", ");
    213 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    214 		tprintf(", %lu, ", tcp->u_arg[2]);
    215 		printllval_aligned(tcp, "%llu", PREAD_OFFSET_ARG);
    216 	}
    217 	return 0;
    218 }
    219 
    220 #if HAVE_SYS_UIO_H
    221 int
    222 sys_preadv(struct tcb *tcp)
    223 {
    224 	if (entering(tcp)) {
    225 		printfd(tcp, tcp->u_arg[0]);
    226 		tprints(", ");
    227 	} else {
    228 		if (syserror(tcp)) {
    229 			tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
    230 			return 0;
    231 		}
    232 		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    233 		tprintf(", %lu, ", tcp->u_arg[2]);
    234 		printllval_unaligned(tcp, "%llu", 3);
    235 	}
    236 	return 0;
    237 }
    238 
    239 int
    240 sys_pwritev(struct tcb *tcp)
    241 {
    242 	if (entering(tcp)) {
    243 		printfd(tcp, tcp->u_arg[0]);
    244 		tprints(", ");
    245 		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    246 		tprintf(", %lu, ", tcp->u_arg[2]);
    247 		printllval_unaligned(tcp, "%llu", 3);
    248 	}
    249 	return 0;
    250 }
    251 #endif /* HAVE_SYS_UIO_H */
    252 
    253 static void
    254 print_off_t(struct tcb *tcp, long addr)
    255 {
    256 	unsigned long offset;
    257 
    258 	if (!addr) {
    259 		tprints("NULL");
    260 		return;
    261 	}
    262 
    263 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    264 	if (current_wordsize == 4) {
    265 		uint32_t off;
    266 
    267 		if (umove(tcp, addr, &off) < 0)
    268 			tprintf("%#lx", addr);
    269 		else
    270 			tprintf("[%u]", off);
    271 	} else
    272 #endif
    273 	if (umove(tcp, addr, &offset) < 0)
    274 		tprintf("%#lx", addr);
    275 	else
    276 		tprintf("[%lu]", offset);
    277 }
    278 
    279 int
    280 sys_sendfile(struct tcb *tcp)
    281 {
    282 	if (entering(tcp)) {
    283 		printfd(tcp, tcp->u_arg[0]);
    284 		tprints(", ");
    285 		printfd(tcp, tcp->u_arg[1]);
    286 		tprints(", ");
    287 		print_off_t(tcp, tcp->u_arg[2]);
    288 		tprintf(", %lu", tcp->u_arg[3]);
    289 	}
    290 	return 0;
    291 }
    292 
    293 void
    294 print_loff_t(struct tcb *tcp, long addr)
    295 {
    296 	loff_t offset;
    297 
    298 	if (!addr)
    299 		tprints("NULL");
    300 	else if (umove(tcp, addr, &offset) < 0)
    301 		tprintf("%#lx", addr);
    302 	else
    303 		tprintf("[%llu]", (unsigned long long int) offset);
    304 }
    305 
    306 int
    307 sys_sendfile64(struct tcb *tcp)
    308 {
    309 	if (entering(tcp)) {
    310 		printfd(tcp, tcp->u_arg[0]);
    311 		tprints(", ");
    312 		printfd(tcp, tcp->u_arg[1]);
    313 		tprints(", ");
    314 		print_loff_t(tcp, tcp->u_arg[2]);
    315 		tprintf(", %lu", tcp->u_arg[3]);
    316 	}
    317 	return 0;
    318 }
    319 
    320 #include "xlat/splice_flags.h"
    321 
    322 int
    323 sys_tee(struct tcb *tcp)
    324 {
    325 	if (entering(tcp)) {
    326 		/* int fd_in */
    327 		printfd(tcp, tcp->u_arg[0]);
    328 		tprints(", ");
    329 		/* int fd_out */
    330 		printfd(tcp, tcp->u_arg[1]);
    331 		tprints(", ");
    332 		/* size_t len */
    333 		tprintf("%lu, ", tcp->u_arg[2]);
    334 		/* unsigned int flags */
    335 		printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
    336 	}
    337 	return 0;
    338 }
    339 
    340 int
    341 sys_splice(struct tcb *tcp)
    342 {
    343 	if (entering(tcp)) {
    344 		/* int fd_in */
    345 		printfd(tcp, tcp->u_arg[0]);
    346 		tprints(", ");
    347 		/* loff_t *off_in */
    348 		print_loff_t(tcp, tcp->u_arg[1]);
    349 		tprints(", ");
    350 		/* int fd_out */
    351 		printfd(tcp, tcp->u_arg[2]);
    352 		tprints(", ");
    353 		/* loff_t *off_out */
    354 		print_loff_t(tcp, tcp->u_arg[3]);
    355 		tprints(", ");
    356 		/* size_t len */
    357 		tprintf("%lu, ", tcp->u_arg[4]);
    358 		/* unsigned int flags */
    359 		printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???");
    360 	}
    361 	return 0;
    362 }
    363 
    364 int
    365 sys_vmsplice(struct tcb *tcp)
    366 {
    367 	if (entering(tcp)) {
    368 		/* int fd */
    369 		printfd(tcp, tcp->u_arg[0]);
    370 		tprints(", ");
    371 		/* const struct iovec *iov, unsigned long nr_segs */
    372 		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
    373 		tprintf(", %lu, ", tcp->u_arg[2]);
    374 		/* unsigned int flags */
    375 		printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
    376 	}
    377 	return 0;
    378 }
    379 
    380 int
    381 sys_ioctl(struct tcb *tcp)
    382 {
    383 	const struct_ioctlent *iop;
    384 
    385 	if (entering(tcp)) {
    386 		printfd(tcp, tcp->u_arg[0]);
    387 		tprints(", ");
    388 		iop = ioctl_lookup(tcp->u_arg[1]);
    389 		if (iop) {
    390 			tprints(iop->symbol);
    391 			while ((iop = ioctl_next_match(iop)))
    392 				tprintf(" or %s", iop->symbol);
    393 		} else
    394 			tprintf("%#lx", tcp->u_arg[1]);
    395 		ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    396 	}
    397 	else {
    398 		int ret = ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    399 		if (!ret)
    400 			tprintf(", %#lx", tcp->u_arg[2]);
    401 		else
    402 			return ret - 1;
    403 	}
    404 	return 0;
    405 }
    406