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  *	$Id: io.c,v 1.20 2005/06/01 19:22:08 roland Exp $
     31  */
     32 
     33 #include "defs.h"
     34 
     35 #include <fcntl.h>
     36 #if HAVE_SYS_UIO_H
     37 #include <sys/uio.h>
     38 #endif
     39 
     40 #ifdef HAVE_LONG_LONG_OFF_T
     41 /*
     42  * Hacks for systems that have a long long off_t
     43  */
     44 
     45 #define sys_pread64	sys_pread
     46 #define sys_pwrite64	sys_pwrite
     47 #endif
     48 
     49 int
     50 sys_read(tcp)
     51 struct tcb *tcp;
     52 {
     53 	if (entering(tcp)) {
     54 		tprintf("%ld, ", tcp->u_arg[0]);
     55 	} else {
     56 		if (syserror(tcp))
     57 			tprintf("%#lx", tcp->u_arg[1]);
     58 		else
     59 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
     60 		tprintf(", %lu", tcp->u_arg[2]);
     61 	}
     62 	return 0;
     63 }
     64 
     65 int
     66 sys_write(tcp)
     67 struct tcb *tcp;
     68 {
     69 	if (entering(tcp)) {
     70 		tprintf("%ld, ", tcp->u_arg[0]);
     71 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
     72 		tprintf(", %lu", tcp->u_arg[2]);
     73 	}
     74 	return 0;
     75 }
     76 
     77 #if HAVE_SYS_UIO_H
     78 void
     79 tprint_iov(tcp, len, addr)
     80 struct tcb * tcp;
     81 unsigned long len;
     82 unsigned long addr;
     83 {
     84 	struct iovec iov;
     85 	unsigned long size, cur, end, abbrev_end;
     86 	int failed = 0;
     87 
     88 	if (!len) {
     89 		tprintf("[]");
     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 	tprintf("[");
    106 	for (cur = addr; cur < end; cur += sizeof(iov)) {
    107 		if (cur > addr)
    108 			tprintf(", ");
    109 		if (cur >= abbrev_end) {
    110 			tprintf("...");
    111 			break;
    112 		}
    113 		if (umoven(tcp, cur, sizeof iov, (char *) &iov) < 0) {
    114 			tprintf("?");
    115 			failed = 1;
    116 			break;
    117 		}
    118 		tprintf("{");
    119 		printstr(tcp, (long) iov.iov_base, iov.iov_len);
    120 		tprintf(", %lu}", (unsigned long)iov.iov_len);
    121 	}
    122 	tprintf("]");
    123 	if (failed)
    124 		tprintf(" %#lx", addr);
    125 }
    126 
    127 int
    128 sys_readv(tcp)
    129 struct tcb *tcp;
    130 {
    131 	if (entering(tcp)) {
    132 		tprintf("%ld, ", tcp->u_arg[0]);
    133 	} else {
    134 		if (syserror(tcp)) {
    135 			tprintf("%#lx, %lu",
    136 					tcp->u_arg[1], tcp->u_arg[2]);
    137 			return 0;
    138 		}
    139 		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
    140 		tprintf(", %lu", tcp->u_arg[2]);
    141 	}
    142 	return 0;
    143 }
    144 
    145 int
    146 sys_writev(tcp)
    147 struct tcb *tcp;
    148 {
    149 	if (entering(tcp)) {
    150 		tprintf("%ld, ", tcp->u_arg[0]);
    151 		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
    152 		tprintf(", %lu", tcp->u_arg[2]);
    153 	}
    154 	return 0;
    155 }
    156 #endif
    157 
    158 #if defined(SVR4)
    159 
    160 int
    161 sys_pread(tcp)
    162 struct tcb *tcp;
    163 {
    164 	if (entering(tcp)) {
    165 		tprintf("%ld, ", tcp->u_arg[0]);
    166 	} else {
    167 		if (syserror(tcp))
    168 			tprintf("%#lx", tcp->u_arg[1]);
    169 		else
    170 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
    171 #if UNIXWARE
    172 		/* off_t is signed int */
    173 		tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]);
    174 #else
    175 		tprintf(", %lu, %llu", tcp->u_arg[2],
    176 			LONG_LONG(tcp->u_arg[3], tcp->u_arg[4]));
    177 #endif
    178 	}
    179 	return 0;
    180 }
    181 
    182 int
    183 sys_pwrite(tcp)
    184 struct tcb *tcp;
    185 {
    186 	if (entering(tcp)) {
    187 		tprintf("%ld, ", tcp->u_arg[0]);
    188 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    189 #if UNIXWARE
    190 		/* off_t is signed int */
    191 		tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]);
    192 #else
    193 		tprintf(", %lu, %llu", tcp->u_arg[2],
    194 			LONG_LONG(tcp->u_arg[3], tcp->u_arg[4]));
    195 #endif
    196 	}
    197 	return 0;
    198 }
    199 #endif /* SVR4 */
    200 
    201 #ifdef FREEBSD
    202 #include <sys/types.h>
    203 #include <sys/socket.h>
    204 
    205 int
    206 sys_sendfile(tcp)
    207 struct tcb *tcp;
    208 {
    209 	if (entering(tcp)) {
    210 		tprintf("%ld, %ld, %llu, %lu", tcp->u_arg[0], tcp->u_arg[1],
    211 			LONG_LONG(tcp->u_arg[2], tcp->u_arg[3]),
    212 			tcp->u_arg[4]);
    213 	} else {
    214 		off_t offset;
    215 
    216 		if (!tcp->u_arg[5])
    217 			tprintf(", NULL");
    218 		else {
    219 			struct sf_hdtr hdtr;
    220 
    221 			if (umove(tcp, tcp->u_arg[5], &hdtr) < 0)
    222 				tprintf(", %#lx", tcp->u_arg[5]);
    223 			else {
    224 				tprintf(", { ");
    225 				tprint_iov(tcp, hdtr.hdr_cnt, hdtr.headers);
    226 				tprintf(", %u, ", hdtr.hdr_cnt);
    227 				tprint_iov(tcp, hdtr.trl_cnt, hdtr.trailers);
    228 				tprintf(", %u }", hdtr.hdr_cnt);
    229 			}
    230 		}
    231 		if (!tcp->u_arg[6])
    232 			tprintf(", NULL");
    233 		else if (umove(tcp, tcp->u_arg[6], &offset) < 0)
    234 			tprintf(", %#lx", tcp->u_arg[6]);
    235 		else
    236 			tprintf(", [%llu]", offset);
    237 		tprintf(", %lu", tcp->u_arg[7]);
    238 	}
    239 	return 0;
    240 }
    241 #endif /* FREEBSD */
    242 
    243 #ifdef LINUX
    244 
    245 /* The SH4 ABI does allow long longs in odd-numbered registers, but
    246    does not allow them to be split between registers and memory - and
    247    there are only four argument registers for normal functions.  As a
    248    result pread takes an extra padding argument before the offset.  This
    249    was changed late in the 2.4 series (around 2.4.20).  */
    250 #if defined(SH)
    251 #define PREAD_OFFSET_ARG 4
    252 #else
    253 #define PREAD_OFFSET_ARG 3
    254 #endif
    255 
    256 int
    257 sys_pread(tcp)
    258 struct tcb *tcp;
    259 {
    260 	if (entering(tcp)) {
    261 		tprintf("%ld, ", tcp->u_arg[0]);
    262 	} else {
    263 		if (syserror(tcp))
    264 			tprintf("%#lx", tcp->u_arg[1]);
    265 		else
    266 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
    267 		ALIGN64 (tcp, PREAD_OFFSET_ARG); /* PowerPC alignment restriction */
    268 		tprintf(", %lu, %llu", tcp->u_arg[2],
    269 			*(unsigned long long *)&tcp->u_arg[PREAD_OFFSET_ARG]);
    270 	}
    271 	return 0;
    272 }
    273 
    274 int
    275 sys_pwrite(tcp)
    276 struct tcb *tcp;
    277 {
    278 	if (entering(tcp)) {
    279 		tprintf("%ld, ", tcp->u_arg[0]);
    280 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    281 		ALIGN64 (tcp, PREAD_OFFSET_ARG); /* PowerPC alignment restriction */
    282 		tprintf(", %lu, %llu", tcp->u_arg[2],
    283 			*(unsigned long long *)&tcp->u_arg[PREAD_OFFSET_ARG]);
    284 	}
    285 	return 0;
    286 }
    287 
    288 int
    289 sys_sendfile(tcp)
    290 struct tcb *tcp;
    291 {
    292 	if (entering(tcp)) {
    293 		off_t offset;
    294 
    295 		tprintf("%ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1]);
    296 		if (!tcp->u_arg[2])
    297 			tprintf("NULL");
    298 		else if (umove(tcp, tcp->u_arg[2], &offset) < 0)
    299 			tprintf("%#lx", tcp->u_arg[2]);
    300 		else
    301 			tprintf("[%lu]", offset);
    302 		tprintf(", %lu", tcp->u_arg[3]);
    303 	}
    304 	return 0;
    305 }
    306 
    307 int
    308 sys_sendfile64(tcp)
    309 struct tcb *tcp;
    310 {
    311 	if (entering(tcp)) {
    312 		loff_t offset;
    313 
    314 		tprintf("%ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1]);
    315 		if (!tcp->u_arg[2])
    316 			tprintf("NULL");
    317 		else if (umove(tcp, tcp->u_arg[2], &offset) < 0)
    318 			tprintf("%#lx", tcp->u_arg[2]);
    319 		else
    320 			tprintf("[%llu]", (unsigned long long int) offset);
    321 		tprintf(", %lu", tcp->u_arg[3]);
    322 	}
    323 	return 0;
    324 }
    325 
    326 #endif /* LINUX */
    327 
    328 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
    329 int
    330 sys_pread64(tcp)
    331 struct tcb *tcp;
    332 {
    333 	if (entering(tcp)) {
    334 		tprintf("%ld, ", tcp->u_arg[0]);
    335 	} else {
    336 		ALIGN64 (tcp, 3);
    337 		if (syserror(tcp))
    338 			tprintf("%#lx", tcp->u_arg[1]);
    339 		else
    340 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
    341 		tprintf(", %lu, %#llx", tcp->u_arg[2],
    342 			LONG_LONG(tcp->u_arg[3], tcp->u_arg[4]));
    343 	}
    344 	return 0;
    345 }
    346 
    347 int
    348 sys_pwrite64(tcp)
    349 struct tcb *tcp;
    350 {
    351 	if (entering(tcp)) {
    352 		ALIGN64 (tcp, 3);
    353 		tprintf("%ld, ", tcp->u_arg[0]);
    354 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    355 		tprintf(", %lu, %#llx", tcp->u_arg[2],
    356 			LONG_LONG(tcp->u_arg[3], tcp->u_arg[4]));
    357 	}
    358 	return 0;
    359 }
    360 #endif
    361 
    362 int
    363 sys_ioctl(tcp)
    364 struct tcb *tcp;
    365 {
    366 	const struct ioctlent *iop;
    367 
    368 	if (entering(tcp)) {
    369 		tprintf("%ld, ", tcp->u_arg[0]);
    370 		iop = ioctl_lookup(tcp->u_arg[1]);
    371 		if (iop) {
    372 			tprintf("%s", iop->symbol);
    373 			while ((iop = ioctl_next_match(iop)))
    374 				tprintf(" or %s", iop->symbol);
    375 		} else
    376 			tprintf("%#lx", tcp->u_arg[1]);
    377 		ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    378 	}
    379 	else {
    380 		int ret;
    381 		if (!(ret = ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2])))
    382 			tprintf(", %#lx", tcp->u_arg[2]);
    383 		else
    384 			return ret - 1;
    385 	}
    386 	return 0;
    387 }
    388