]> granicus.if.org Git - strace/blob - io.c
evdev: decode struct input_absinfo regardless of in-kernel definitions
[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  * Copyright (c) 1999-2018 The strace developers.
7  * All rights reserved.
8  *
9  * SPDX-License-Identifier: LGPL-2.1-or-later
10  */
11
12 #include "defs.h"
13 #include <fcntl.h>
14 #include <sys/uio.h>
15
16 SYS_FUNC(read)
17 {
18         if (entering(tcp)) {
19                 printfd(tcp, tcp->u_arg[0]);
20                 tprints(", ");
21         } else {
22                 if (syserror(tcp))
23                         printaddr(tcp->u_arg[1]);
24                 else
25                         printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
26                 tprintf(", %" PRI_klu, tcp->u_arg[2]);
27         }
28         return 0;
29 }
30
31 SYS_FUNC(write)
32 {
33         printfd(tcp, tcp->u_arg[0]);
34         tprints(", ");
35         printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
36         tprintf(", %" PRI_klu, tcp->u_arg[2]);
37
38         return RVAL_DECODED;
39 }
40
41 struct print_iovec_config {
42         enum iov_decode decode_iov;
43         kernel_ulong_t data_size;
44 };
45
46 static bool
47 print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
48 {
49         const kernel_ulong_t *iov;
50         kernel_ulong_t iov_buf[2], len;
51         struct print_iovec_config *c = data;
52
53         if (elem_size < sizeof(iov_buf)) {
54                 iov_buf[0] = ((unsigned int *) elem_buf)[0];
55                 iov_buf[1] = ((unsigned int *) elem_buf)[1];
56                 iov = iov_buf;
57         } else {
58                 iov = elem_buf;
59         }
60
61         tprints("{iov_base=");
62
63         len = iov[1];
64
65         switch (c->decode_iov) {
66                 case IOV_DECODE_STR:
67                         if (len > c->data_size)
68                                 len = c->data_size;
69                         if (c->data_size != (kernel_ulong_t) -1)
70                                 c->data_size -= len;
71                         printstrn(tcp, iov[0], len);
72                         break;
73                 case IOV_DECODE_NETLINK:
74                         if (len > c->data_size)
75                                 len = c->data_size;
76                         if (c->data_size != (kernel_ulong_t) -1)
77                                 c->data_size -= len;
78                         /* assume that the descriptor is 1st syscall argument */
79                         decode_netlink(tcp, tcp->u_arg[0], iov[0], len);
80                         break;
81                 default:
82                         printaddr(iov[0]);
83                         break;
84         }
85
86         tprintf(", iov_len=%" PRI_klu "}", iov[1]);
87
88         return true;
89 }
90
91 /*
92  * data_size limits the cumulative size of printed data.
93  * Example: recvmsg returing a short read.
94  */
95 void
96 tprint_iov_upto(struct tcb *const tcp, const kernel_ulong_t len,
97                 const kernel_ulong_t addr, const enum iov_decode decode_iov,
98                 const kernel_ulong_t data_size)
99 {
100         kernel_ulong_t iov[2];
101         struct print_iovec_config config = {
102                 .decode_iov = decode_iov, .data_size = data_size
103         };
104
105         print_array(tcp, addr, len, iov, current_wordsize * 2,
106                     tfetch_mem_ignore_syserror, print_iovec, &config);
107 }
108
109 SYS_FUNC(readv)
110 {
111         if (entering(tcp)) {
112                 printfd(tcp, tcp->u_arg[0]);
113                 tprints(", ");
114         } else {
115                 tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1],
116                                 syserror(tcp) ? IOV_DECODE_ADDR :
117                                 IOV_DECODE_STR, tcp->u_rval);
118                 tprintf(", %" PRI_klu, tcp->u_arg[2]);
119         }
120         return 0;
121 }
122
123 SYS_FUNC(writev)
124 {
125         printfd(tcp, tcp->u_arg[0]);
126         tprints(", ");
127         tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR);
128         tprintf(", %" PRI_klu, tcp->u_arg[2]);
129
130         return RVAL_DECODED;
131 }
132
133 SYS_FUNC(pread)
134 {
135         if (entering(tcp)) {
136                 printfd(tcp, tcp->u_arg[0]);
137                 tprints(", ");
138         } else {
139                 if (syserror(tcp))
140                         printaddr(tcp->u_arg[1]);
141                 else
142                         printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
143                 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
144                 printllval(tcp, "%lld", 3);
145         }
146         return 0;
147 }
148
149 SYS_FUNC(pwrite)
150 {
151         printfd(tcp, tcp->u_arg[0]);
152         tprints(", ");
153         printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
154         tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
155         printllval(tcp, "%lld", 3);
156
157         return RVAL_DECODED;
158 }
159
160 static void
161 print_lld_from_low_high_val(struct tcb *tcp, int arg)
162 {
163 #if SIZEOF_KERNEL_LONG_T > 4
164 # ifndef current_klongsize
165         if (current_klongsize < SIZEOF_KERNEL_LONG_T) {
166                 tprintf("%" PRI_kld, (tcp->u_arg[arg + 1] << 32)
167                                | tcp->u_arg[arg]);
168         } else
169 # endif /* !current_klongsize */
170         {
171                 tprintf("%" PRI_kld, tcp->u_arg[arg]);
172         }
173 #else /* SIZEOF_KERNEL_LONG_T == 4 */
174         tprintf("%lld",
175                   ((long long) tcp->u_arg[arg + 1] << 32)
176                 | ((long long) tcp->u_arg[arg]));
177 #endif
178 }
179
180 #include "xlat/rwf_flags.h"
181
182 static int
183 do_preadv(struct tcb *tcp, const int flags_arg)
184 {
185         if (entering(tcp)) {
186                 printfd(tcp, tcp->u_arg[0]);
187                 tprints(", ");
188         } else {
189                 kernel_ulong_t len =
190                         truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
191
192                 tprint_iov_upto(tcp, len, tcp->u_arg[1],
193                                 syserror(tcp) ? IOV_DECODE_ADDR :
194                                 IOV_DECODE_STR, tcp->u_rval);
195                 tprintf(", %" PRI_klu ", ", len);
196                 print_lld_from_low_high_val(tcp, 3);
197                 if (flags_arg >= 0) {
198                         tprints(", ");
199                         printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
200                 }
201         }
202         return 0;
203 }
204
205 SYS_FUNC(preadv)
206 {
207         return do_preadv(tcp, -1);
208 }
209
210 static int
211 do_pwritev(struct tcb *tcp, const int flags_arg)
212 {
213         kernel_ulong_t len =
214                 truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
215
216         printfd(tcp, tcp->u_arg[0]);
217         tprints(", ");
218         tprint_iov(tcp, len, tcp->u_arg[1], IOV_DECODE_STR);
219         tprintf(", %" PRI_klu ", ", len);
220         print_lld_from_low_high_val(tcp, 3);
221         if (flags_arg >= 0) {
222                 tprints(", ");
223                 printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
224         }
225
226         return RVAL_DECODED;
227 }
228
229 SYS_FUNC(pwritev)
230 {
231         return do_pwritev(tcp, -1);
232 }
233
234 /*
235  * x32 is the only architecture where preadv2 takes 5 arguments
236  * instead of 6, see preadv64v2 in kernel sources.
237  * Likewise, x32 is the only architecture where pwritev2 takes 5 arguments
238  * instead of 6, see pwritev64v2 in kernel sources.
239  */
240
241 #if defined X86_64
242 # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 2 ? 4 : 5)
243 #elif defined X32
244 # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 0 ? 4 : 5)
245 #else
246 # define PREADV2_PWRITEV2_FLAGS_ARG_NO 5
247 #endif
248
249 SYS_FUNC(preadv2)
250 {
251         return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
252 }
253
254 SYS_FUNC(pwritev2)
255 {
256         return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
257 }
258
259 #include "xlat/splice_flags.h"
260
261 SYS_FUNC(tee)
262 {
263         /* int fd_in */
264         printfd(tcp, tcp->u_arg[0]);
265         tprints(", ");
266         /* int fd_out */
267         printfd(tcp, tcp->u_arg[1]);
268         tprints(", ");
269         /* size_t len */
270         tprintf("%" PRI_klu ", ", tcp->u_arg[2]);
271         /* unsigned int flags */
272         printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
273
274         return RVAL_DECODED;
275 }
276
277 SYS_FUNC(splice)
278 {
279         /* int fd_in */
280         printfd(tcp, tcp->u_arg[0]);
281         tprints(", ");
282         /* loff_t *off_in */
283         printnum_int64(tcp, tcp->u_arg[1], "%" PRId64);
284         tprints(", ");
285         /* int fd_out */
286         printfd(tcp, tcp->u_arg[2]);
287         tprints(", ");
288         /* loff_t *off_out */
289         printnum_int64(tcp, tcp->u_arg[3], "%" PRId64);
290         tprints(", ");
291         /* size_t len */
292         tprintf("%" PRI_klu ", ", tcp->u_arg[4]);
293         /* unsigned int flags */
294         printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???");
295
296         return RVAL_DECODED;
297 }
298
299 SYS_FUNC(vmsplice)
300 {
301         /* int fd */
302         printfd(tcp, tcp->u_arg[0]);
303         tprints(", ");
304         /* const struct iovec *iov, unsigned long nr_segs */
305         tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR);
306         tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
307         /* unsigned int flags */
308         printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
309
310         return RVAL_DECODED;
311 }