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