]> granicus.if.org Git - strace/blob - aio.c
Fix multiple personalities support in parser of io_submit syscall
[strace] / aio.c
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 #ifdef HAVE_LIBAIO_H
33 # include <libaio.h>
34 #endif
35
36 /* Not defined in libaio.h */
37 #ifndef IOCB_RESFD
38 # define IOCB_RESFD (1 << 0)
39 #endif
40
41 SYS_FUNC(io_setup)
42 {
43         if (entering(tcp))
44                 tprintf("%u, ", (unsigned int) tcp->u_arg[0]);
45         else
46                 printnum_ulong(tcp, tcp->u_arg[1]);
47         return 0;
48 }
49
50 SYS_FUNC(io_destroy)
51 {
52         tprintf("%lu", tcp->u_arg[0]);
53
54         return RVAL_DECODED;
55 }
56
57 #ifdef HAVE_LIBAIO_H
58
59 enum iocb_sub {
60         SUB_NONE, SUB_COMMON, SUB_POLL, SUB_VECTOR
61 };
62
63 static enum iocb_sub
64 tprint_lio_opcode(unsigned cmd)
65 {
66         static const struct {
67                 const char *name;
68                 enum iocb_sub sub;
69         } cmds[] = {
70                 { "pread", SUB_COMMON },
71                 { "pwrite", SUB_COMMON },
72                 { "fsync", SUB_NONE },
73                 { "fdsync", SUB_NONE },
74                 { "op4", SUB_NONE },
75                 { "poll", SUB_POLL },
76                 { "noop", SUB_NONE },
77                 { "preadv", SUB_VECTOR },
78                 { "pwritev", SUB_VECTOR },
79         };
80
81         if (cmd < ARRAY_SIZE(cmds)) {
82                 tprints(cmds[cmd].name);
83                 return cmds[cmd].sub;
84         }
85         tprintf("%u /* SUB_??? */", cmd);
86         return SUB_NONE;
87 }
88
89 static void
90 print_common_flags(struct iocb *iocb)
91 {
92 #ifdef HAVE_STRUCT_IOCB_U_C_FLAGS
93         if (iocb->u.c.flags & IOCB_RESFD)
94                 tprintf(", resfd=%d", iocb->u.c.resfd);
95         if (iocb->u.c.flags & ~IOCB_RESFD)
96                 tprintf(", flags=%x", iocb->u.c.flags);
97 #else
98 # warning "libaio.h is too old => limited io_submit decoding"
99 #endif
100 }
101
102 #endif /* HAVE_LIBAIO_H */
103
104 SYS_FUNC(io_submit)
105 {
106 #ifdef HAVE_LIBAIO_H
107         long nr = tcp->u_arg[1];
108         /* if nr <= 0, we end up printing just "[]" */
109         tprintf("%lu, %ld, [", tcp->u_arg[0], tcp->u_arg[1]);
110         {
111                 long i;
112                 long iocbs = tcp->u_arg[2];
113
114                 for (i = 0; i < nr; ++i, iocbs += current_wordsize) {
115                         enum iocb_sub sub;
116                         long iocbp;
117                         struct iocb iocb;
118
119                         if (i)
120                                 tprints(", ");
121
122                         if (umove_long_or_printaddr(tcp, iocbs, &iocbp)) {
123                                 /*
124                                  * No point in trying to read the whole array
125                                  * because nr can be ridiculously large.
126                                  */
127                                 break;
128                         }
129
130                         tprints("{");
131                         if (umove_or_printaddr(tcp, iocbp, &iocb)) {
132                                 tprints("}");
133                                 continue;
134                         }
135
136                         if (iocb.data) {
137                                 tprints("data=");
138                                 printaddr((long) iocb.data);
139                                 tprints(", ");
140                         }
141                         if (iocb.key)
142                                 tprintf("key=%u, ", iocb.key);
143                         sub = tprint_lio_opcode(iocb.aio_lio_opcode);
144                         if (iocb.aio_reqprio)
145                                 tprintf(", reqprio=%d", iocb.aio_reqprio);
146                         tprintf(", filedes=%d", iocb.aio_fildes);
147                         switch (sub) {
148                         case SUB_COMMON:
149 #if HAVE_DECL_IO_CMD_PWRITE
150                                 if (iocb.aio_lio_opcode == IO_CMD_PWRITE) {
151                                         tprints(", str=");
152                                         printstr(tcp, (unsigned long)iocb.u.c.buf,
153                                                  iocb.u.c.nbytes);
154                                 } else
155 #endif
156                                 {
157                                         tprints(", buf=");
158                                         printaddr((long) iocb.u.c.buf);
159                                 }
160                                 tprintf(", nbytes=%lu, offset=%lld",
161                                         iocb.u.c.nbytes,
162                                         iocb.u.c.offset);
163                                 print_common_flags(&iocb);
164                                 break;
165                         case SUB_VECTOR:
166                                 tprintf(", %lld", iocb.u.v.offset);
167                                 print_common_flags(&iocb);
168                                 tprints(", ");
169                                 tprint_iov(tcp, iocb.u.v.nr,
170                                            (unsigned long)iocb.u.v.vec,
171 #if HAVE_DECL_IO_CMD_PWRITEV
172                                            iocb.aio_lio_opcode == IO_CMD_PWRITEV
173 #else
174                                            0
175 #endif
176                                           );
177                                 break;
178                         case SUB_POLL:
179                                 tprintf(", %x", iocb.u.poll.events);
180                                 break;
181                         case SUB_NONE:
182                                 break;
183                         }
184                         tprints("}");
185                 }
186         }
187         tprints("]");
188 #else
189 # warning "libaio.h is not available => no io_submit decoding"
190                 tprintf("%lu, %ld, %#lx", tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
191 #endif
192         return RVAL_DECODED;
193 }
194
195 static int
196 print_io_event(struct tcb *tcp, const long addr)
197 {
198 #ifdef HAVE_LIBAIO_H
199         struct io_event event;
200
201         if (umove_or_printaddr(tcp, addr, &event))
202                 return -1;
203         tprints("{data=");
204         printaddr((long) event.data);
205         tprints(", obj=");
206         printaddr((long) event.obj);
207         tprintf(", res=%ld, res2=%ld}", event.res, event.res2);
208 #else
209         printaddr(tcp->u_arg[2]);
210 #endif
211         return 0;
212 }
213
214 SYS_FUNC(io_cancel)
215 {
216         if (entering(tcp)) {
217                 tprintf("%lu, ", tcp->u_arg[0]);
218 #ifdef HAVE_LIBAIO_H
219                 struct iocb iocb;
220
221                 if (!umove_or_printaddr(tcp, tcp->u_arg[1], &iocb)) {
222                         tprintf("{%p, %u, %u, %u, %d}, ",
223                                 iocb.data, iocb.key,
224                                 (unsigned)iocb.aio_lio_opcode,
225                                 (unsigned)iocb.aio_reqprio, iocb.aio_fildes);
226                 }
227 #else
228                 printaddr(tcp->u_arg[1]);
229 #endif
230         } else {
231                 print_io_event(tcp, tcp->u_arg[2]);
232         }
233         return 0;
234 }
235
236 SYS_FUNC(io_getevents)
237 {
238         if (entering(tcp)) {
239                 tprintf("%lu, %ld, %ld, ",
240                         tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
241         } else {
242                 if (tcp->u_rval == 0) {
243                         tprints("[]");
244                 } else {
245 #ifdef HAVE_LIBAIO_H
246                         struct io_event *events = (void *)tcp->u_arg[3];
247                         long i, nr = tcp->u_rval;
248
249                         for (i = 0; i < nr; i++, events++) {
250                                 if (i == 0)
251                                         tprints("[");
252                                 else
253                                         tprints(", ");
254
255                                 if (print_io_event(tcp, (long)events))
256                                         break;
257                         }
258                         tprints("], ");
259 #else
260                         printaddr(tcp->u_arg[3]);
261 #endif
262                 }
263
264                 print_timespec(tcp, tcp->u_arg[4]);
265         }
266         return 0;
267 }