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