]> granicus.if.org Git - strace/blob - io.c
Fix recvmsg decode: do not show more data than actually returned
[strace] / io.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 #include <fcntl.h>
33 #include <limits.h>
34 #if HAVE_SYS_UIO_H
35 # include <sys/uio.h>
36 #endif
37
38 int
39 sys_read(struct tcb *tcp)
40 {
41         if (entering(tcp)) {
42                 printfd(tcp, tcp->u_arg[0]);
43                 tprints(", ");
44         } else {
45                 if (syserror(tcp))
46                         tprintf("%#lx", tcp->u_arg[1]);
47                 else
48                         printstr(tcp, tcp->u_arg[1], tcp->u_rval);
49                 tprintf(", %lu", tcp->u_arg[2]);
50         }
51         return 0;
52 }
53
54 int
55 sys_write(struct tcb *tcp)
56 {
57         if (entering(tcp)) {
58                 printfd(tcp, tcp->u_arg[0]);
59                 tprints(", ");
60                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
61                 tprintf(", %lu", tcp->u_arg[2]);
62         }
63         return 0;
64 }
65
66 #if HAVE_SYS_UIO_H
67 /*
68  * data_size limits the cumulative size of printed data.
69  * Example: recvmsg returing a short read.
70  */
71 void
72 tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov, unsigned long data_size)
73 {
74 #if SUPPORTED_PERSONALITIES > 1
75         union {
76                 struct { u_int32_t base; u_int32_t len; } iov32;
77                 struct { u_int64_t base; u_int64_t len; } iov64;
78         } iov;
79 #define sizeof_iov \
80         (current_wordsize == 4 ? sizeof(iov.iov32) : sizeof(iov.iov64))
81 #define iov_iov_base \
82         (current_wordsize == 4 ? (uint64_t) iov.iov32.base : iov.iov64.base)
83 #define iov_iov_len \
84         (current_wordsize == 4 ? (uint64_t) iov.iov32.len : iov.iov64.len)
85 #else
86         struct iovec iov;
87 #define sizeof_iov sizeof(iov)
88 #define iov_iov_base iov.iov_base
89 #define iov_iov_len iov.iov_len
90 #endif
91         unsigned long size, cur, end, abbrev_end;
92         int failed = 0;
93
94         if (!len) {
95                 tprints("[]");
96                 return;
97         }
98         size = len * sizeof_iov;
99         end = addr + size;
100         if (!verbose(tcp) || size / sizeof_iov != len || end < addr) {
101                 tprintf("%#lx", addr);
102                 return;
103         }
104         if (abbrev(tcp)) {
105                 abbrev_end = addr + max_strlen * sizeof_iov;
106                 if (abbrev_end < addr)
107                         abbrev_end = end;
108         } else {
109                 abbrev_end = end;
110         }
111         tprints("[");
112         for (cur = addr; cur < end; cur += sizeof_iov) {
113                 if (cur > addr)
114                         tprints(", ");
115                 if (cur >= abbrev_end) {
116                         tprints("...");
117                         break;
118                 }
119                 if (umoven(tcp, cur, sizeof_iov, (char *) &iov) < 0) {
120                         tprints("?");
121                         failed = 1;
122                         break;
123                 }
124                 tprints("{");
125                 if (decode_iov) {
126                         unsigned long len = iov_iov_len;
127                         if (len > data_size)
128                                 len = data_size;
129                         data_size -= len;
130                         printstr(tcp, (long) iov_iov_base, len);
131                 } else
132                         tprintf("%#lx", (long) iov_iov_base);
133                 tprintf(", %lu}", (unsigned long)iov_iov_len);
134         }
135         tprints("]");
136         if (failed)
137                 tprintf(" %#lx", addr);
138 #undef sizeof_iov
139 #undef iov_iov_base
140 #undef iov_iov_len
141 }
142
143 void
144 tprint_iov(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov)
145 {
146         tprint_iov_upto(tcp, len, addr, decode_iov, ULONG_MAX);
147 }
148
149 int
150 sys_readv(struct tcb *tcp)
151 {
152         if (entering(tcp)) {
153                 printfd(tcp, tcp->u_arg[0]);
154                 tprints(", ");
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], 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                 tprints(", ");
173                 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
174                 tprintf(", %lu", tcp->u_arg[2]);
175         }
176         return 0;
177 }
178 #endif
179
180 /* The SH4 ABI does allow long longs in odd-numbered registers, but
181    does not allow them to be split between registers and memory - and
182    there are only four argument registers for normal functions.  As a
183    result pread takes an extra padding argument before the offset.  This
184    was changed late in the 2.4 series (around 2.4.20).  */
185 #if defined(SH)
186 #define PREAD_OFFSET_ARG 4
187 #else
188 #define PREAD_OFFSET_ARG 3
189 #endif
190
191 int
192 sys_pread(struct tcb *tcp)
193 {
194         if (entering(tcp)) {
195                 printfd(tcp, tcp->u_arg[0]);
196                 tprints(", ");
197         } else {
198                 if (syserror(tcp))
199                         tprintf("%#lx", tcp->u_arg[1]);
200                 else
201                         printstr(tcp, tcp->u_arg[1], tcp->u_rval);
202                 tprintf(", %lu, ", tcp->u_arg[2]);
203                 printllval(tcp, "%llu", PREAD_OFFSET_ARG);
204         }
205         return 0;
206 }
207
208 int
209 sys_pwrite(struct tcb *tcp)
210 {
211         if (entering(tcp)) {
212                 printfd(tcp, tcp->u_arg[0]);
213                 tprints(", ");
214                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
215                 tprintf(", %lu, ", tcp->u_arg[2]);
216                 printllval(tcp, "%llu", PREAD_OFFSET_ARG);
217         }
218         return 0;
219 }
220
221 #if HAVE_SYS_UIO_H
222 int
223 sys_preadv(struct tcb *tcp)
224 {
225         if (entering(tcp)) {
226                 printfd(tcp, tcp->u_arg[0]);
227                 tprints(", ");
228         } else {
229                 if (syserror(tcp)) {
230                         tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
231                         return 0;
232                 }
233                 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
234                 tprintf(", %lu, ", tcp->u_arg[2]);
235                 printllval(tcp, "%llu", PREAD_OFFSET_ARG);
236         }
237         return 0;
238 }
239
240 int
241 sys_pwritev(struct tcb *tcp)
242 {
243         if (entering(tcp)) {
244                 printfd(tcp, tcp->u_arg[0]);
245                 tprints(", ");
246                 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
247                 tprintf(", %lu, ", tcp->u_arg[2]);
248                 printllval(tcp, "%llu", PREAD_OFFSET_ARG);
249         }
250         return 0;
251 }
252 #endif /* HAVE_SYS_UIO_H */
253
254 int
255 sys_sendfile(struct tcb *tcp)
256 {
257         if (entering(tcp)) {
258                 off_t offset;
259
260                 printfd(tcp, tcp->u_arg[0]);
261                 tprints(", ");
262                 printfd(tcp, tcp->u_arg[1]);
263                 tprints(", ");
264                 if (!tcp->u_arg[2])
265                         tprints("NULL");
266                 else if (umove(tcp, tcp->u_arg[2], &offset) < 0)
267                         tprintf("%#lx", tcp->u_arg[2]);
268                 else
269 #ifdef HAVE_LONG_LONG_OFF_T
270                         tprintf("[%llu]", offset);
271 #else
272                         tprintf("[%lu]", offset);
273 #endif
274                 tprintf(", %lu", tcp->u_arg[3]);
275         }
276         return 0;
277 }
278
279 void
280 print_loff_t(struct tcb *tcp, long addr)
281 {
282         loff_t offset;
283
284         if (!addr)
285                 tprints("NULL");
286         else if (umove(tcp, addr, &offset) < 0)
287                 tprintf("%#lx", addr);
288         else
289                 tprintf("[%llu]", (unsigned long long int) offset);
290 }
291
292 int
293 sys_sendfile64(struct tcb *tcp)
294 {
295         if (entering(tcp)) {
296                 printfd(tcp, tcp->u_arg[0]);
297                 tprints(", ");
298                 printfd(tcp, tcp->u_arg[1]);
299                 tprints(", ");
300                 print_loff_t(tcp, tcp->u_arg[2]);
301                 tprintf(", %lu", tcp->u_arg[3]);
302         }
303         return 0;
304 }
305
306 static const struct xlat splice_flags[] = {
307 #ifdef SPLICE_F_MOVE
308         { SPLICE_F_MOVE,     "SPLICE_F_MOVE"     },
309 #endif
310 #ifdef SPLICE_F_NONBLOCK
311         { SPLICE_F_NONBLOCK, "SPLICE_F_NONBLOCK" },
312 #endif
313 #ifdef SPLICE_F_MORE
314         { SPLICE_F_MORE,     "SPLICE_F_MORE"     },
315 #endif
316 #ifdef SPLICE_F_GIFT
317         { SPLICE_F_GIFT,     "SPLICE_F_GIFT"     },
318 #endif
319         { 0,                 NULL                },
320 };
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 }