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$ 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(struct tcb *tcp) 51 { 52 if (entering(tcp)) { 53 printfd(tcp, tcp->u_arg[0]); 54 tprintf(", "); 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(struct tcb *tcp) 67 { 68 if (entering(tcp)) { 69 printfd(tcp, tcp->u_arg[0]); 70 tprintf(", "); 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 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1 85 union { 86 struct { u_int32_t base; u_int32_t len; } iov32; 87 struct { u_int64_t base; u_int64_t len; } iov64; 88 } iov; 89 #define sizeof_iov \ 90 (personality_wordsize[current_personality] == 4 \ 91 ? sizeof(iov.iov32) : sizeof(iov.iov64)) 92 #define iov_iov_base \ 93 (personality_wordsize[current_personality] == 4 \ 94 ? (u_int64_t) iov.iov32.base : iov.iov64.base) 95 #define iov_iov_len \ 96 (personality_wordsize[current_personality] == 4 \ 97 ? (u_int64_t) iov.iov32.len : iov.iov64.len) 98 #else 99 struct iovec iov; 100 #define sizeof_iov sizeof(iov) 101 #define iov_iov_base iov.iov_base 102 #define iov_iov_len iov.iov_len 103 #endif 104 unsigned long size, cur, end, abbrev_end; 105 int failed = 0; 106 107 if (!len) { 108 tprintf("[]"); 109 return; 110 } 111 size = len * sizeof_iov; 112 end = addr + size; 113 if (!verbose(tcp) || size / sizeof_iov != len || end < addr) { 114 tprintf("%#lx", addr); 115 return; 116 } 117 if (abbrev(tcp)) { 118 abbrev_end = addr + max_strlen * sizeof_iov; 119 if (abbrev_end < addr) 120 abbrev_end = end; 121 } else { 122 abbrev_end = end; 123 } 124 tprintf("["); 125 for (cur = addr; cur < end; cur += sizeof_iov) { 126 if (cur > addr) 127 tprintf(", "); 128 if (cur >= abbrev_end) { 129 tprintf("..."); 130 break; 131 } 132 if (umoven(tcp, cur, sizeof_iov, (char *) &iov) < 0) { 133 tprintf("?"); 134 failed = 1; 135 break; 136 } 137 tprintf("{"); 138 printstr(tcp, (long) iov_iov_base, iov_iov_len); 139 tprintf(", %lu}", (unsigned long)iov_iov_len); 140 } 141 tprintf("]"); 142 if (failed) 143 tprintf(" %#lx", addr); 144 #undef sizeof_iov 145 #undef iov_iov_base 146 #undef iov_iov_len 147 } 148 149 int 150 sys_readv(struct tcb *tcp) 151 { 152 if (entering(tcp)) { 153 printfd(tcp, tcp->u_arg[0]); 154 tprintf(", "); 155 } else { 156 if (syserror(tcp)) { 157 tprintf("%#lx, %lu", 158 tcp->u_arg[1], tcp->u_arg[2]); 159 return 0; 160 } 161 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1]); 162 tprintf(", %lu", tcp->u_arg[2]); 163 } 164 return 0; 165 } 166 167 int 168 sys_writev(struct tcb *tcp) 169 { 170 if (entering(tcp)) { 171 printfd(tcp, tcp->u_arg[0]); 172 tprintf(", "); 173 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1]); 174 tprintf(", %lu", tcp->u_arg[2]); 175 } 176 return 0; 177 } 178 #endif 179 180 #if defined(SVR4) 181 182 int 183 sys_pread(struct tcb *tcp) 184 { 185 if (entering(tcp)) { 186 printfd(tcp, tcp->u_arg[0]); 187 tprintf(", "); 188 } else { 189 if (syserror(tcp)) 190 tprintf("%#lx", tcp->u_arg[1]); 191 else 192 printstr(tcp, tcp->u_arg[1], tcp->u_rval); 193 #if UNIXWARE 194 /* off_t is signed int */ 195 tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]); 196 #else 197 tprintf(", %lu, %llu", tcp->u_arg[2], 198 LONG_LONG(tcp->u_arg[3], tcp->u_arg[4])); 199 #endif 200 } 201 return 0; 202 } 203 204 int 205 sys_pwrite(struct tcb *tcp) 206 { 207 if (entering(tcp)) { 208 printfd(tcp, tcp->u_arg[0]); 209 tprintf(", "); 210 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); 211 #if UNIXWARE 212 /* off_t is signed int */ 213 tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]); 214 #else 215 tprintf(", %lu, %llu", tcp->u_arg[2], 216 LONG_LONG(tcp->u_arg[3], tcp->u_arg[4])); 217 #endif 218 } 219 return 0; 220 } 221 #endif /* SVR4 */ 222 223 #ifdef FREEBSD 224 #include <sys/types.h> 225 #include <sys/socket.h> 226 227 int 228 sys_sendfile(struct tcb *tcp) 229 { 230 if (entering(tcp)) { 231 printfd(tcp, tcp->u_arg[0]); 232 tprintf(", "); 233 printfd(tcp, tcp->u_arg[1]); 234 tprintf(", %llu, %lu", 235 LONG_LONG(tcp->u_arg[2], tcp->u_arg[3]), 236 tcp->u_arg[4]); 237 } else { 238 off_t offset; 239 240 if (!tcp->u_arg[5]) 241 tprintf(", NULL"); 242 else { 243 struct sf_hdtr hdtr; 244 245 if (umove(tcp, tcp->u_arg[5], &hdtr) < 0) 246 tprintf(", %#lx", tcp->u_arg[5]); 247 else { 248 tprintf(", { "); 249 tprint_iov(tcp, hdtr.hdr_cnt, hdtr.headers); 250 tprintf(", %u, ", hdtr.hdr_cnt); 251 tprint_iov(tcp, hdtr.trl_cnt, hdtr.trailers); 252 tprintf(", %u }", hdtr.hdr_cnt); 253 } 254 } 255 if (!tcp->u_arg[6]) 256 tprintf(", NULL"); 257 else if (umove(tcp, tcp->u_arg[6], &offset) < 0) 258 tprintf(", %#lx", tcp->u_arg[6]); 259 else 260 tprintf(", [%llu]", offset); 261 tprintf(", %lu", tcp->u_arg[7]); 262 } 263 return 0; 264 } 265 #endif /* FREEBSD */ 266 267 #ifdef LINUX 268 269 /* The SH4 ABI does allow long longs in odd-numbered registers, but 270 does not allow them to be split between registers and memory - and 271 there are only four argument registers for normal functions. As a 272 result pread takes an extra padding argument before the offset. This 273 was changed late in the 2.4 series (around 2.4.20). */ 274 #if defined(SH) 275 #define PREAD_OFFSET_ARG 4 276 #else 277 #define PREAD_OFFSET_ARG 3 278 #endif 279 280 int 281 sys_pread(struct tcb *tcp) 282 { 283 if (entering(tcp)) { 284 printfd(tcp, tcp->u_arg[0]); 285 tprintf(", "); 286 } else { 287 if (syserror(tcp)) 288 tprintf("%#lx", tcp->u_arg[1]); 289 else 290 printstr(tcp, tcp->u_arg[1], tcp->u_rval); 291 tprintf(", %lu, ", tcp->u_arg[2]); 292 printllval(tcp, "%llu", PREAD_OFFSET_ARG); 293 } 294 return 0; 295 } 296 297 int 298 sys_pwrite(struct tcb *tcp) 299 { 300 if (entering(tcp)) { 301 printfd(tcp, tcp->u_arg[0]); 302 tprintf(", "); 303 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); 304 tprintf(", %lu, ", tcp->u_arg[2]); 305 printllval(tcp, "%llu", PREAD_OFFSET_ARG); 306 } 307 return 0; 308 } 309 310 int 311 sys_sendfile(struct tcb *tcp) 312 { 313 if (entering(tcp)) { 314 off_t offset; 315 316 printfd(tcp, tcp->u_arg[0]); 317 tprintf(", "); 318 printfd(tcp, tcp->u_arg[1]); 319 tprintf(", "); 320 if (!tcp->u_arg[2]) 321 tprintf("NULL"); 322 else if (umove(tcp, tcp->u_arg[2], &offset) < 0) 323 tprintf("%#lx", tcp->u_arg[2]); 324 else 325 tprintf("[%lu]", offset); 326 tprintf(", %lu", tcp->u_arg[3]); 327 } 328 return 0; 329 } 330 331 int 332 sys_sendfile64(struct tcb *tcp) 333 { 334 if (entering(tcp)) { 335 loff_t offset; 336 337 printfd(tcp, tcp->u_arg[0]); 338 tprintf(", "); 339 printfd(tcp, tcp->u_arg[1]); 340 tprintf(", "); 341 if (!tcp->u_arg[2]) 342 tprintf("NULL"); 343 else if (umove(tcp, tcp->u_arg[2], &offset) < 0) 344 tprintf("%#lx", tcp->u_arg[2]); 345 else 346 tprintf("[%llu]", (unsigned long long int) offset); 347 tprintf(", %lu", tcp->u_arg[3]); 348 } 349 return 0; 350 } 351 352 #endif /* LINUX */ 353 354 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T 355 int 356 sys_pread64(struct tcb *tcp) 357 { 358 if (entering(tcp)) { 359 printfd(tcp, tcp->u_arg[0]); 360 tprintf(", "); 361 } else { 362 if (syserror(tcp)) 363 tprintf("%#lx", tcp->u_arg[1]); 364 else 365 printstr(tcp, tcp->u_arg[1], tcp->u_rval); 366 tprintf(", %lu, ", tcp->u_arg[2]); 367 printllval(tcp, "%#llx", 3); 368 } 369 return 0; 370 } 371 372 int 373 sys_pwrite64(struct tcb *tcp) 374 { 375 if (entering(tcp)) { 376 printfd(tcp, tcp->u_arg[0]); 377 tprintf(", "); 378 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); 379 tprintf(", %lu, ", tcp->u_arg[2]); 380 printllval(tcp, "%#llx", 3); 381 } 382 return 0; 383 } 384 #endif 385 386 int 387 sys_ioctl(struct tcb *tcp) 388 { 389 const struct ioctlent *iop; 390 391 if (entering(tcp)) { 392 printfd(tcp, tcp->u_arg[0]); 393 tprintf(", "); 394 iop = ioctl_lookup(tcp->u_arg[1]); 395 if (iop) { 396 tprintf("%s", iop->symbol); 397 while ((iop = ioctl_next_match(iop))) 398 tprintf(" or %s", iop->symbol); 399 } else 400 tprintf("%#lx", tcp->u_arg[1]); 401 ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]); 402 } 403 else { 404 int ret; 405 if (!(ret = ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]))) 406 tprintf(", %#lx", tcp->u_arg[2]); 407 else 408 return ret - 1; 409 } 410 return 0; 411 } 412