1/* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@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 33/* --- Copied from libaio-0.3.109/src/libaio.h --- 34 * Why keep a copy instead of using external libaio.h? 35 * Because we want to properly decode 32-bit aio calls 36 * by 64-bit strace. For that, we need more definitions than 37 * libaio.h provides. (TODO). 38 * Keeping our local 32-bit compat defs in sync with libaio.h 39 * _without seeing libaio structs_ is hard/more bug-prone. 40 * A smaller benefit is that we don't need libaio installed. 41 */ 42#define HAVE_LIBAIO_H 1 43typedef enum io_iocb_cmd { 44 IO_CMD_PREAD = 0, 45 IO_CMD_PWRITE = 1, 46 47 IO_CMD_FSYNC = 2, 48 IO_CMD_FDSYNC = 3, 49 50 IO_CMD_POLL = 5, /* Never implemented in mainline, see io_prep_poll */ 51 IO_CMD_NOOP = 6, 52 IO_CMD_PREADV = 7, 53 IO_CMD_PWRITEV = 8, 54} io_iocb_cmd_t; 55 56#if defined(__i386__) /* little endian, 32 bits */ 57#define PADDED(x, y) x; unsigned y 58#define PADDEDptr(x, y) x; unsigned y 59#define PADDEDul(x, y) unsigned long x; unsigned y 60#elif defined(__ia64__) || defined(__x86_64__) || defined(__alpha__) 61#define PADDED(x, y) x, y 62#define PADDEDptr(x, y) x 63#define PADDEDul(x, y) unsigned long x 64#elif defined(__powerpc64__) /* big endian, 64 bits */ 65#define PADDED(x, y) unsigned y; x 66#define PADDEDptr(x,y) x 67#define PADDEDul(x, y) unsigned long x 68#elif defined(__PPC__) /* big endian, 32 bits */ 69#define PADDED(x, y) unsigned y; x 70#define PADDEDptr(x, y) unsigned y; x 71#define PADDEDul(x, y) unsigned y; unsigned long x 72#elif defined(__s390x__) /* big endian, 64 bits */ 73#define PADDED(x, y) unsigned y; x 74#define PADDEDptr(x,y) x 75#define PADDEDul(x, y) unsigned long x 76#elif defined(__s390__) /* big endian, 32 bits */ 77#define PADDED(x, y) unsigned y; x 78#define PADDEDptr(x, y) unsigned y; x 79#define PADDEDul(x, y) unsigned y; unsigned long x 80#elif defined(__arm__) 81# if defined (__ARMEB__) /* big endian, 32 bits */ 82#define PADDED(x, y) unsigned y; x 83#define PADDEDptr(x, y) unsigned y; x 84#define PADDEDul(x, y) unsigned y; unsigned long x 85# else /* little endian, 32 bits */ 86#define PADDED(x, y) x; unsigned y 87#define PADDEDptr(x, y) x; unsigned y 88#define PADDEDul(x, y) unsigned long x; unsigned y 89# endif 90#else 91# warning No AIO definitions for this architecture => no io_submit decoding 92# undef HAVE_LIBAIO_H 93#endif 94 95#ifdef HAVE_LIBAIO_H 96struct io_iocb_poll { 97 PADDED(int events, __pad1); 98}; /* result code is the set of result flags or -'ve errno */ 99 100struct io_iocb_sockaddr { 101 struct sockaddr *addr; 102 int len; 103}; /* result code is the length of the sockaddr, or -'ve errno */ 104 105struct io_iocb_common { 106 PADDEDptr(void *buf, __pad1); 107 PADDEDul(nbytes, __pad2); 108 long long offset; 109 long long __pad3; 110 unsigned flags; 111 unsigned resfd; 112}; /* result code is the amount read or -'ve errno */ 113 114struct io_iocb_vector { 115 const struct iovec *vec; 116 int nr; 117 long long offset; 118}; /* result code is the amount read or -'ve errno */ 119 120struct iocb { 121 PADDEDptr(void *data, __pad1); /* Return in the io completion event */ 122 PADDED(unsigned key, __pad2); /* For use in identifying io requests */ 123 124 short aio_lio_opcode; 125 short aio_reqprio; 126 int aio_fildes; 127 128 union { 129 struct io_iocb_common c; 130 struct io_iocb_vector v; 131 struct io_iocb_poll poll; 132 struct io_iocb_sockaddr saddr; 133 } u; 134}; 135 136struct io_event { 137 PADDEDptr(void *data, __pad1); 138 PADDEDptr(struct iocb *obj, __pad2); 139 PADDEDul(res, __pad3); 140 PADDEDul(res2, __pad4); 141}; 142 143#undef PADDED 144#undef PADDEDptr 145#undef PADDEDul 146 147#endif /* HAVE_LIBAIO_H */ 148 149/* --- End of a chunk of libaio.h --- */ 150/* Not defined in libaio.h */ 151#ifndef IOCB_RESFD 152# define IOCB_RESFD (1 << 0) 153#endif 154 155int 156sys_io_setup(struct tcb *tcp) 157{ 158 if (entering(tcp)) 159 tprintf("%ld, ", tcp->u_arg[0]); 160 else { 161 if (syserror(tcp)) 162 tprintf("0x%0lx", tcp->u_arg[1]); 163 else { 164 unsigned long user_id; 165 if (umove(tcp, tcp->u_arg[1], &user_id) == 0) 166 tprintf("{%lu}", user_id); 167 else 168 tprints("{...}"); 169 } 170 } 171 return 0; 172} 173 174int 175sys_io_destroy(struct tcb *tcp) 176{ 177 if (entering(tcp)) 178 tprintf("%lu", tcp->u_arg[0]); 179 return 0; 180} 181 182#ifdef HAVE_LIBAIO_H 183 184enum iocb_sub { 185 SUB_NONE, SUB_COMMON, SUB_POLL, SUB_VECTOR 186}; 187 188static enum iocb_sub 189tprint_lio_opcode(unsigned cmd) 190{ 191 static const struct { 192 const char *name; 193 enum iocb_sub sub; 194 } cmds[] = { 195 { "pread", SUB_COMMON }, 196 { "pwrite", SUB_COMMON }, 197 { "fsync", SUB_NONE }, 198 { "fdsync", SUB_NONE }, 199 { "op4", SUB_NONE }, 200 { "poll", SUB_POLL }, 201 { "noop", SUB_NONE }, 202 { "preadv", SUB_VECTOR }, 203 { "pwritev", SUB_VECTOR }, 204 }; 205 206 if (cmd < ARRAY_SIZE(cmds)) { 207 tprints(cmds[cmd].name); 208 return cmds[cmd].sub; 209 } 210 tprintf("%u /* SUB_??? */", cmd); 211 return SUB_NONE; 212} 213 214static void 215print_common_flags(struct iocb *iocb) 216{ 217 if (iocb->u.c.flags & IOCB_RESFD) 218 tprintf(", resfd=%d", iocb->u.c.resfd); 219 if (iocb->u.c.flags & ~IOCB_RESFD) 220 tprintf(", flags=%x", iocb->u.c.flags); 221} 222 223#endif /* HAVE_LIBAIO_H */ 224 225int 226sys_io_submit(struct tcb *tcp) 227{ 228 if (entering(tcp)) { 229#ifdef HAVE_LIBAIO_H 230 long nr = tcp->u_arg[1]; 231 /* if nr <= 0, we end up printing just "{}" */ 232 tprintf("%lu, %ld, {", tcp->u_arg[0], tcp->u_arg[1]); 233 { 234 long i; 235 struct iocb **iocbs = (void *)tcp->u_arg[2]; 236//FIXME: decoding of 32-bit call by 64-bit strace 237 238 for (i = 0; i < nr; i++, iocbs++) { 239 enum iocb_sub sub; 240 struct iocb *iocbp; 241 struct iocb iocb; 242 if (i) 243 tprints(", "); 244 245 if (umove(tcp, (unsigned long)iocbs, &iocbp)) { 246 tprintf("%#lx", (unsigned long)iocbs); 247 /* No point in trying to read iocbs+1 etc */ 248 /* (nr can be ridiculously large): */ 249 break; 250 } 251 if (umove(tcp, (unsigned long)iocbp, &iocb)) { 252 tprintf("{%#lx}", (unsigned long)iocbp); 253 continue; 254 } 255 tprints("{"); 256 if (iocb.data) 257 tprintf("data:%p, ", iocb.data); 258 if (iocb.key) 259 tprintf("key:%u, ", iocb.key); 260 sub = tprint_lio_opcode(iocb.aio_lio_opcode); 261 if (iocb.aio_reqprio) 262 tprintf(", reqprio:%d", iocb.aio_reqprio); 263 tprintf(", filedes:%d", iocb.aio_fildes); 264 switch (sub) { 265 case SUB_COMMON: 266 if (iocb.aio_lio_opcode == IO_CMD_PWRITE) { 267 tprints(", str:"); 268 printstr(tcp, (unsigned long)iocb.u.c.buf, 269 iocb.u.c.nbytes); 270 } else 271 tprintf(", buf:%p", iocb.u.c.buf); 272 tprintf(", nbytes:%lu, offset:%lld", 273 iocb.u.c.nbytes, 274 iocb.u.c.offset); 275 print_common_flags(&iocb); 276 break; 277 case SUB_VECTOR: 278 tprintf(", %lld", iocb.u.v.offset); 279 print_common_flags(&iocb); 280 tprints(", "); 281 tprint_iov(tcp, iocb.u.v.nr, 282 (unsigned long)iocb.u.v.vec, 283 iocb.aio_lio_opcode == IO_CMD_PWRITEV 284 ); 285 break; 286 case SUB_POLL: 287 tprintf(", %x", iocb.u.poll.events); 288 break; 289 case SUB_NONE: 290 break; 291 } 292 tprints("}"); 293 } 294 } 295 tprints("}"); 296#else 297 tprintf("%lu, %ld, %#lx", tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]); 298#endif 299 } 300 return 0; 301} 302 303int 304sys_io_cancel(struct tcb *tcp) 305{ 306 if (entering(tcp)) { 307#ifdef HAVE_LIBAIO_H 308 struct iocb iocb; 309#endif 310 tprintf("%lu, ", tcp->u_arg[0]); 311#ifdef HAVE_LIBAIO_H 312 if (umove(tcp, tcp->u_arg[1], &iocb) == 0) { 313 tprintf("{%p, %u, %u, %u, %d}, ", 314 iocb.data, iocb.key, 315 (unsigned)iocb.aio_lio_opcode, 316 (unsigned)iocb.aio_reqprio, iocb.aio_fildes); 317 } else 318#endif 319 tprints("{...}, "); 320 } else { 321 if (tcp->u_rval < 0) 322 tprints("{...}"); 323 else { 324#ifdef HAVE_LIBAIO_H 325 struct io_event event; 326 if (umove(tcp, tcp->u_arg[2], &event) == 0) 327 tprintf("{%p, %p, %ld, %ld}", 328 event.data, event.obj, 329 event.res, event.res2); 330 else 331#endif 332 tprints("{...}"); 333 } 334 } 335 return 0; 336} 337 338int 339sys_io_getevents(struct tcb *tcp) 340{ 341 if (entering(tcp)) { 342 tprintf("%ld, %ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1], 343 tcp->u_arg[2]); 344 } else { 345 if (tcp->u_rval == 0) { 346 tprints("{}"); 347 } else { 348#ifdef HAVE_LIBAIO_H 349 struct io_event *events = (void *)tcp->u_arg[3]; 350 long i, nr = tcp->u_rval; 351 352 for (i = 0; i < nr; i++, events++) { 353 struct io_event event; 354 355 if (i == 0) 356 tprints("{"); 357 else 358 tprints(", "); 359 360 if (umove(tcp, (unsigned long)events, &event) != 0) { 361 tprints("{...}"); 362 continue; 363 } 364 tprintf("{%p, %p, %ld, %ld}", event.data, 365 event.obj, event.res, event.res2); 366 } 367 tprints("}, "); 368#else 369 tprints("{...}"); 370#endif 371 } 372 373 print_timespec(tcp, tcp->u_arg[4]); 374 } 375 return 0; 376} 377