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