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