]> granicus.if.org Git - strace/blob - io.c
Fix printing of unreadable struct iovec
[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 <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                         printaddr(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         printfd(tcp, tcp->u_arg[0]);
53         tprints(", ");
54         printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
55         tprintf(", %lu", tcp->u_arg[2]);
56
57         return RVAL_DECODED;
58 }
59
60 /*
61  * data_size limits the cumulative size of printed data.
62  * Example: recvmsg returing a short read.
63  */
64 void
65 tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov, unsigned long data_size)
66 {
67         unsigned long iov[2];
68         unsigned long size, cur, end, abbrev_end;
69         const unsigned long sizeof_iov = current_wordsize * 2;
70
71         if (!len) {
72                 tprints("[]");
73                 return;
74         }
75         size = len * sizeof_iov;
76         end = addr + size;
77         if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
78             !addr || size / sizeof_iov != len || end < addr) {
79                 printaddr(addr);
80                 return;
81         }
82         if (abbrev(tcp)) {
83                 abbrev_end = addr + max_strlen * sizeof_iov;
84                 if (abbrev_end < addr)
85                         abbrev_end = end;
86         } else {
87                 abbrev_end = end;
88         }
89         if (addr >= abbrev_end) {
90                 tprints("[...]");
91                 return;
92         }
93         for (cur = addr; cur < end; cur += sizeof_iov) {
94                 if (cur > addr) {
95                         tprints(", ");
96                         if (cur >= abbrev_end) {
97                                 tprints("...");
98                                 break;
99                         }
100                 }
101                 if (umove_ulong_array_or_printaddr(tcp, cur, iov,
102                                                    ARRAY_SIZE(iov)))
103                         break;
104                 if (cur <= addr)
105                         tprints("[");
106                 tprints("{");
107                 if (decode_iov) {
108                         unsigned long len = iov[1];
109                         if (len > data_size)
110                                 len = data_size;
111                         data_size -= len;
112                         printstr(tcp, iov[0], len);
113                 } else
114                         printaddr(iov[0]);
115                 tprintf(", %lu}", iov[1]);
116         }
117         if (cur > addr)
118                 tprints("]");
119 }
120
121 void
122 tprint_iov(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov)
123 {
124         tprint_iov_upto(tcp, len, addr, decode_iov, (unsigned long) -1L);
125 }
126
127 SYS_FUNC(readv)
128 {
129         if (entering(tcp)) {
130                 printfd(tcp, tcp->u_arg[0]);
131                 tprints(", ");
132         } else {
133                 tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1], 1,
134                                 tcp->u_rval);
135                 tprintf(", %lu", tcp->u_arg[2]);
136         }
137         return 0;
138 }
139
140 SYS_FUNC(writev)
141 {
142         printfd(tcp, tcp->u_arg[0]);
143         tprints(", ");
144         tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
145         tprintf(", %lu", tcp->u_arg[2]);
146
147         return RVAL_DECODED;
148 }
149
150 /* The SH4 ABI does allow long longs in odd-numbered registers, but
151    does not allow them to be split between registers and memory - and
152    there are only four argument registers for normal functions.  As a
153    result pread takes an extra padding argument before the offset.  This
154    was changed late in the 2.4 series (around 2.4.20).  */
155 #if defined(SH)
156 #define PREAD_OFFSET_ARG 4
157 #else
158 #define PREAD_OFFSET_ARG 3
159 #endif
160
161 SYS_FUNC(pread)
162 {
163         if (entering(tcp)) {
164                 printfd(tcp, tcp->u_arg[0]);
165                 tprints(", ");
166         } else {
167                 if (syserror(tcp))
168                         printaddr(tcp->u_arg[1]);
169                 else
170                         printstr(tcp, tcp->u_arg[1], tcp->u_rval);
171                 tprintf(", %lu, ", tcp->u_arg[2]);
172                 printllval(tcp, "%llu", PREAD_OFFSET_ARG);
173         }
174         return 0;
175 }
176
177 SYS_FUNC(pwrite)
178 {
179         printfd(tcp, tcp->u_arg[0]);
180         tprints(", ");
181         printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
182         tprintf(", %lu, ", tcp->u_arg[2]);
183         printllval(tcp, "%llu", PREAD_OFFSET_ARG);
184
185         return RVAL_DECODED;
186 }
187
188 static void
189 print_llu_from_low_high_val(struct tcb *tcp, int arg)
190 {
191 #if SIZEOF_LONG == SIZEOF_LONG_LONG
192 # if SUPPORTED_PERSONALITIES > 1
193 #  ifdef X86_64
194         if (current_personality != 1)
195 #  else
196         if (current_wordsize == sizeof(long))
197 #  endif
198 # endif
199                 tprintf("%lu", (unsigned long) tcp->u_arg[arg]);
200 # if SUPPORTED_PERSONALITIES > 1
201         else
202                 tprintf("%lu",
203                         ((unsigned long) tcp->u_arg[arg + 1] << current_wordsize * 8)
204                         | (unsigned long) tcp->u_arg[arg]);
205 # endif
206 #else
207 # ifdef X32
208         if (current_personality == 0)
209                 tprintf("%llu", (unsigned long long) tcp->ext_arg[arg]);
210         else
211 # endif
212         tprintf("%llu",
213                 ((unsigned long long) (unsigned long) tcp->u_arg[arg + 1] << sizeof(long) * 8)
214                 | (unsigned long long) (unsigned long) tcp->u_arg[arg]);
215 #endif
216 }
217
218 SYS_FUNC(preadv)
219 {
220         if (entering(tcp)) {
221                 printfd(tcp, tcp->u_arg[0]);
222                 tprints(", ");
223         } else {
224                 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
225                 tprintf(", %lu, ", tcp->u_arg[2]);
226                 print_llu_from_low_high_val(tcp, 3);
227         }
228         return 0;
229 }
230
231 SYS_FUNC(pwritev)
232 {
233         printfd(tcp, tcp->u_arg[0]);
234         tprints(", ");
235         tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
236         tprintf(", %lu, ", tcp->u_arg[2]);
237         print_llu_from_low_high_val(tcp, 3);
238
239         return RVAL_DECODED;
240 }
241
242 #include "xlat/splice_flags.h"
243
244 SYS_FUNC(tee)
245 {
246         /* int fd_in */
247         printfd(tcp, tcp->u_arg[0]);
248         tprints(", ");
249         /* int fd_out */
250         printfd(tcp, tcp->u_arg[1]);
251         tprints(", ");
252         /* size_t len */
253         tprintf("%lu, ", tcp->u_arg[2]);
254         /* unsigned int flags */
255         printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
256
257         return RVAL_DECODED;
258 }
259
260 SYS_FUNC(splice)
261 {
262         /* int fd_in */
263         printfd(tcp, tcp->u_arg[0]);
264         tprints(", ");
265         /* loff_t *off_in */
266         printnum_int64(tcp, tcp->u_arg[1], "%" PRId64);
267         tprints(", ");
268         /* int fd_out */
269         printfd(tcp, tcp->u_arg[2]);
270         tprints(", ");
271         /* loff_t *off_out */
272         printnum_int64(tcp, tcp->u_arg[3], "%" PRId64);
273         tprints(", ");
274         /* size_t len */
275         tprintf("%lu, ", tcp->u_arg[4]);
276         /* unsigned int flags */
277         printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???");
278
279         return RVAL_DECODED;
280 }
281
282 SYS_FUNC(vmsplice)
283 {
284         /* int fd */
285         printfd(tcp, tcp->u_arg[0]);
286         tprints(", ");
287         /* const struct iovec *iov, unsigned long nr_segs */
288         tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
289         tprintf(", %lu, ", tcp->u_arg[2]);
290         /* unsigned int flags */
291         printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
292
293         return RVAL_DECODED;
294 }