blob: cd803057b32131931eab75decbcb7ae9809f2a61 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
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>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Elliott Hughes03a418e2018-06-15 13:11:40 -07006 * Copyright (c) 1999-2018 The strace developers.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00007 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000030 */
31
32#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000033#include <fcntl.h>
Dmitry V. Levinb2fa2be2014-11-21 20:46:16 +000034#include <sys/uio.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000035
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000036SYS_FUNC(read)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037{
38 if (entering(tcp)) {
Dmitry V. Levin31382132011-03-04 05:08:02 +030039 printfd(tcp, tcp->u_arg[0]);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +020040 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000041 } else {
42 if (syserror(tcp))
Dmitry V. Levin43b5a1f2015-07-20 11:06:54 +000043 printaddr(tcp->u_arg[1]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000044 else
Elliott Hughesd35df492017-02-15 15:19:05 -080045 printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
46 tprintf(", %" PRI_klu, tcp->u_arg[2]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000047 }
48 return 0;
49}
50
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000051SYS_FUNC(write)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000052{
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +000053 printfd(tcp, tcp->u_arg[0]);
54 tprints(", ");
Elliott Hughesd35df492017-02-15 15:19:05 -080055 printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
56 tprintf(", %" PRI_klu, tcp->u_arg[2]);
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +000057
58 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000059}
60
Dmitry V. Levin4ce30542016-05-07 22:54:04 +000061struct print_iovec_config {
Fabien Siron2a54d8b2016-06-22 13:27:03 +000062 enum iov_decode decode_iov;
Elliott Hughesd35df492017-02-15 15:19:05 -080063 kernel_ulong_t data_size;
Dmitry V. Levin4ce30542016-05-07 22:54:04 +000064};
65
66static bool
67print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
68{
Elliott Hughesd35df492017-02-15 15:19:05 -080069 const kernel_ulong_t *iov;
70 kernel_ulong_t iov_buf[2], len;
Dmitry V. Levin4ce30542016-05-07 22:54:04 +000071 struct print_iovec_config *c = data;
72
Elliott Hughesdc75b012017-07-05 13:54:44 -070073 if (elem_size < sizeof(iov_buf)) {
Dmitry V. Levin4ce30542016-05-07 22:54:04 +000074 iov_buf[0] = ((unsigned int *) elem_buf)[0];
75 iov_buf[1] = ((unsigned int *) elem_buf)[1];
76 iov = iov_buf;
77 } else {
78 iov = elem_buf;
79 }
80
Dmitry V. Levin4ddbfcf2016-07-13 22:54:55 +000081 tprints("{iov_base=");
Dmitry V. Levin4ce30542016-05-07 22:54:04 +000082
Fabien Siron2a54d8b2016-06-22 13:27:03 +000083 len = iov[1];
84
85 switch (c->decode_iov) {
86 case IOV_DECODE_STR:
87 if (len > c->data_size)
88 len = c->data_size;
Elliott Hughesd35df492017-02-15 15:19:05 -080089 if (c->data_size != (kernel_ulong_t) -1)
Eugene Syromyatnikovf3228d32016-09-29 15:57:55 +030090 c->data_size -= len;
Elliott Hughesd35df492017-02-15 15:19:05 -080091 printstrn(tcp, iov[0], len);
Fabien Siron2a54d8b2016-06-22 13:27:03 +000092 break;
Fabien Siron2850f742016-07-06 15:49:22 +000093 case IOV_DECODE_NETLINK:
94 if (len > c->data_size)
95 len = c->data_size;
Elliott Hughesd35df492017-02-15 15:19:05 -080096 if (c->data_size != (kernel_ulong_t) -1)
Eugene Syromyatnikovf3228d32016-09-29 15:57:55 +030097 c->data_size -= len;
Elliott Hughesdc75b012017-07-05 13:54:44 -070098 /* assume that the descriptor is 1st syscall argument */
99 decode_netlink(tcp, tcp->u_arg[0], iov[0], len);
Fabien Siron2850f742016-07-06 15:49:22 +0000100 break;
Fabien Siron2a54d8b2016-06-22 13:27:03 +0000101 default:
102 printaddr(iov[0]);
103 break;
Dmitry V. Levin4ce30542016-05-07 22:54:04 +0000104 }
105
Elliott Hughesd35df492017-02-15 15:19:05 -0800106 tprintf(", iov_len=%" PRI_klu "}", iov[1]);
Dmitry V. Levin4ce30542016-05-07 22:54:04 +0000107
108 return true;
109}
110
Denys Vlasenkoe0bc2222012-04-28 14:26:18 +0200111/*
112 * data_size limits the cumulative size of printed data.
113 * Example: recvmsg returing a short read.
114 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000115void
Elliott Hughesd35df492017-02-15 15:19:05 -0800116tprint_iov_upto(struct tcb *const tcp, const kernel_ulong_t len,
117 const kernel_ulong_t addr, const enum iov_decode decode_iov,
118 const kernel_ulong_t data_size)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000119{
Elliott Hughesd35df492017-02-15 15:19:05 -0800120 kernel_ulong_t iov[2];
Elliott Hughesdc75b012017-07-05 13:54:44 -0700121 struct print_iovec_config config = {
122 .decode_iov = decode_iov, .data_size = data_size
123 };
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000124
Dmitry V. Levin4ce30542016-05-07 22:54:04 +0000125 print_array(tcp, addr, len, iov, current_wordsize * 2,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700126 tfetch_mem_ignore_syserror, print_iovec, &config);
Denys Vlasenkoe0bc2222012-04-28 14:26:18 +0200127}
128
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000129SYS_FUNC(readv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131 if (entering(tcp)) {
Dmitry V. Levin31382132011-03-04 05:08:02 +0300132 printfd(tcp, tcp->u_arg[0]);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200133 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134 } else {
Fabien Siron2a54d8b2016-06-22 13:27:03 +0000135 tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1],
Elliott Hughesd35df492017-02-15 15:19:05 -0800136 syserror(tcp) ? IOV_DECODE_ADDR :
Fabien Siron2a54d8b2016-06-22 13:27:03 +0000137 IOV_DECODE_STR, tcp->u_rval);
Elliott Hughesd35df492017-02-15 15:19:05 -0800138 tprintf(", %" PRI_klu, tcp->u_arg[2]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000139 }
140 return 0;
141}
142
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000143SYS_FUNC(writev)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144{
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000145 printfd(tcp, tcp->u_arg[0]);
146 tprints(", ");
Fabien Siron2a54d8b2016-06-22 13:27:03 +0000147 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR);
Elliott Hughesd35df492017-02-15 15:19:05 -0800148 tprintf(", %" PRI_klu, tcp->u_arg[2]);
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000149
150 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151}
152
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000153SYS_FUNC(pread)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154{
155 if (entering(tcp)) {
Dmitry V. Levin31382132011-03-04 05:08:02 +0300156 printfd(tcp, tcp->u_arg[0]);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200157 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000158 } else {
159 if (syserror(tcp))
Dmitry V. Levin43b5a1f2015-07-20 11:06:54 +0000160 printaddr(tcp->u_arg[1]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000161 else
Elliott Hughesd35df492017-02-15 15:19:05 -0800162 printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
163 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
Eugene Syromyatnikov714a1622016-08-20 17:02:55 +0300164 printllval(tcp, "%lld", 3);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000165 }
166 return 0;
167}
168
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000169SYS_FUNC(pwrite)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170{
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000171 printfd(tcp, tcp->u_arg[0]);
172 tprints(", ");
Elliott Hughesd35df492017-02-15 15:19:05 -0800173 printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
174 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
Eugene Syromyatnikov714a1622016-08-20 17:02:55 +0300175 printllval(tcp, "%lld", 3);
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000176
177 return RVAL_DECODED;
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000178}
179
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000180static void
Dmitry V. Levind4611512016-03-30 03:54:21 +0000181print_lld_from_low_high_val(struct tcb *tcp, int arg)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000182{
Elliott Hughesd35df492017-02-15 15:19:05 -0800183#if SIZEOF_KERNEL_LONG_T > 4
184# ifndef current_klongsize
185 if (current_klongsize < SIZEOF_KERNEL_LONG_T) {
186 tprintf("%" PRI_kld, (tcp->u_arg[arg + 1] << 32)
187 | tcp->u_arg[arg]);
Dmitry V. Levinb0c51132016-06-17 16:12:13 +0000188 } else
Elliott Hughesd35df492017-02-15 15:19:05 -0800189# endif /* !current_klongsize */
Dmitry V. Levinb0c51132016-06-17 16:12:13 +0000190 {
Elliott Hughesd35df492017-02-15 15:19:05 -0800191 tprintf("%" PRI_kld, tcp->u_arg[arg]);
Dmitry V. Levinb0c51132016-06-17 16:12:13 +0000192 }
Elliott Hughesd35df492017-02-15 15:19:05 -0800193#else /* SIZEOF_KERNEL_LONG_T == 4 */
Dmitry V. Levind4611512016-03-30 03:54:21 +0000194 tprintf("%lld",
Elliott Hughesd35df492017-02-15 15:19:05 -0800195 ((long long) tcp->u_arg[arg + 1] << 32)
196 | ((long long) tcp->u_arg[arg]));
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000197#endif
198}
199
Dmitry V. Levina6dd0942016-05-11 00:42:10 +0000200#include "xlat/rwf_flags.h"
201
202static int
203do_preadv(struct tcb *tcp, const int flags_arg)
Damir Shayhutdinov3087dd62011-05-12 16:57:40 +0400204{
205 if (entering(tcp)) {
206 printfd(tcp, tcp->u_arg[0]);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200207 tprints(", ");
Damir Shayhutdinov3087dd62011-05-12 16:57:40 +0400208 } else {
Elliott Hughesd35df492017-02-15 15:19:05 -0800209 kernel_ulong_t len =
210 truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
211
212 tprint_iov_upto(tcp, len, tcp->u_arg[1],
213 syserror(tcp) ? IOV_DECODE_ADDR :
214 IOV_DECODE_STR, tcp->u_rval);
215 tprintf(", %" PRI_klu ", ", len);
Dmitry V. Levind4611512016-03-30 03:54:21 +0000216 print_lld_from_low_high_val(tcp, 3);
Dmitry V. Levina6dd0942016-05-11 00:42:10 +0000217 if (flags_arg >= 0) {
218 tprints(", ");
219 printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
220 }
Damir Shayhutdinov3087dd62011-05-12 16:57:40 +0400221 }
222 return 0;
223}
224
Dmitry V. Levina6dd0942016-05-11 00:42:10 +0000225SYS_FUNC(preadv)
226{
227 return do_preadv(tcp, -1);
228}
229
Dmitry V. Levina6dd0942016-05-11 00:42:10 +0000230static int
231do_pwritev(struct tcb *tcp, const int flags_arg)
Damir Shayhutdinov3087dd62011-05-12 16:57:40 +0400232{
Elliott Hughesd35df492017-02-15 15:19:05 -0800233 kernel_ulong_t len =
234 truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
235
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000236 printfd(tcp, tcp->u_arg[0]);
237 tprints(", ");
Elliott Hughesd35df492017-02-15 15:19:05 -0800238 tprint_iov(tcp, len, tcp->u_arg[1], IOV_DECODE_STR);
239 tprintf(", %" PRI_klu ", ", len);
Dmitry V. Levind4611512016-03-30 03:54:21 +0000240 print_lld_from_low_high_val(tcp, 3);
Dmitry V. Levina6dd0942016-05-11 00:42:10 +0000241 if (flags_arg >= 0) {
242 tprints(", ");
243 printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
244 }
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000245
246 return RVAL_DECODED;
Damir Shayhutdinov3087dd62011-05-12 16:57:40 +0400247}
Damir Shayhutdinov3087dd62011-05-12 16:57:40 +0400248
Dmitry V. Levina6dd0942016-05-11 00:42:10 +0000249SYS_FUNC(pwritev)
250{
251 return do_pwritev(tcp, -1);
252}
253
Elliott Hughes39bac052017-05-25 16:56:11 -0700254/*
255 * x32 is the only architecture where preadv2 takes 5 arguments
256 * instead of 6, see preadv64v2 in kernel sources.
257 * Likewise, x32 is the only architecture where pwritev2 takes 5 arguments
258 * instead of 6, see pwritev64v2 in kernel sources.
259 */
260
261#if defined X86_64
262# define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 2 ? 4 : 5)
263#elif defined X32
264# define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 0 ? 4 : 5)
265#else
266# define PREADV2_PWRITEV2_FLAGS_ARG_NO 5
267#endif
268
269SYS_FUNC(preadv2)
270{
271 return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
272}
273
Dmitry V. Levina6dd0942016-05-11 00:42:10 +0000274SYS_FUNC(pwritev2)
275{
Elliott Hughes39bac052017-05-25 16:56:11 -0700276 return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
Dmitry V. Levina6dd0942016-05-11 00:42:10 +0000277}
278
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +0000279#include "xlat/splice_flags.h"
Dmitry V. Levind99e48c2011-10-11 17:07:05 +0000280
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000281SYS_FUNC(tee)
Dmitry V. Levind99e48c2011-10-11 17:07:05 +0000282{
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000283 /* int fd_in */
284 printfd(tcp, tcp->u_arg[0]);
285 tprints(", ");
286 /* int fd_out */
287 printfd(tcp, tcp->u_arg[1]);
288 tprints(", ");
289 /* size_t len */
Elliott Hughesd35df492017-02-15 15:19:05 -0800290 tprintf("%" PRI_klu ", ", tcp->u_arg[2]);
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000291 /* unsigned int flags */
292 printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
293
294 return RVAL_DECODED;
Dmitry V. Levind99e48c2011-10-11 17:07:05 +0000295}
296
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000297SYS_FUNC(splice)
Dmitry V. Levind99e48c2011-10-11 17:07:05 +0000298{
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000299 /* int fd_in */
300 printfd(tcp, tcp->u_arg[0]);
301 tprints(", ");
302 /* loff_t *off_in */
Dmitry V. Levin16a52b42016-02-13 22:31:30 +0000303 printnum_int64(tcp, tcp->u_arg[1], "%" PRId64);
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000304 tprints(", ");
305 /* int fd_out */
306 printfd(tcp, tcp->u_arg[2]);
307 tprints(", ");
308 /* loff_t *off_out */
Dmitry V. Levin16a52b42016-02-13 22:31:30 +0000309 printnum_int64(tcp, tcp->u_arg[3], "%" PRId64);
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000310 tprints(", ");
311 /* size_t len */
Elliott Hughesd35df492017-02-15 15:19:05 -0800312 tprintf("%" PRI_klu ", ", tcp->u_arg[4]);
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000313 /* unsigned int flags */
314 printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???");
315
316 return RVAL_DECODED;
Dmitry V. Levind99e48c2011-10-11 17:07:05 +0000317}
318
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000319SYS_FUNC(vmsplice)
Dmitry V. Levind99e48c2011-10-11 17:07:05 +0000320{
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000321 /* int fd */
322 printfd(tcp, tcp->u_arg[0]);
323 tprints(", ");
324 /* const struct iovec *iov, unsigned long nr_segs */
Fabien Siron2a54d8b2016-06-22 13:27:03 +0000325 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR);
Elliott Hughesd35df492017-02-15 15:19:05 -0800326 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
Dmitry V. Levin1f255fd2015-07-20 11:19:30 +0000327 /* unsigned int flags */
328 printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
329
330 return RVAL_DECODED;
Dmitry V. Levind99e48c2011-10-11 17:07:05 +0000331}