blob: 32327c264db2cf3aba41b2b8e5dfea6b32c1dcdb [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>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * 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.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000029 */
30
31#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032#include <fcntl.h>
33#include <sys/file.h>
Roland McGrath63d6e542004-10-20 02:17:41 +000034#ifdef HAVE_SYS_EPOLL_H
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +010035# include <sys/epoll.h>
Roland McGrath93817bf2004-10-06 22:23:31 +000036#endif
Ben Noordhuis88eafd82013-02-04 00:04:57 +010037#ifdef HAVE_LINUX_PERF_EVENT_H
38# include <linux/perf_event.h>
39#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000041#include "xlat/fcntlcmds.h"
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000042#include "xlat/fdflags.h"
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000043#include "xlat/flockcmds.h"
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000044#include "xlat/lockfcmds.h"
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000045#include "xlat/notifyflags.h"
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000046#include "xlat/perf_event_open_flags.h"
Ben Noordhuis88eafd82013-02-04 00:04:57 +010047
Dmitry V. Levin54cabef2014-03-03 23:09:47 +000048/*
49 * Assume that F_SETLK64, F_SETLKW64, and F_GETLK64 are either defined
50 * or not defined altogether.
51 */
Dmitry V. Levin594eb8f2013-11-12 21:49:03 +000052#if defined(F_SETLK64) && F_SETLK64 + 0 != F_SETLK
Dmitry V. Levin54cabef2014-03-03 23:09:47 +000053# define USE_PRINTFLOCK64 1
Dmitry V. Levin594eb8f2013-11-12 21:49:03 +000054#else
Dmitry V. Levin54cabef2014-03-03 23:09:47 +000055# define USE_PRINTFLOCK64 0
Dmitry V. Levin594eb8f2013-11-12 21:49:03 +000056#endif
57
Dmitry V. Levin54cabef2014-03-03 23:09:47 +000058#if USE_PRINTFLOCK64
Dmitry V. Levin594eb8f2013-11-12 21:49:03 +000059
Dmitry V. Levin54cabef2014-03-03 23:09:47 +000060# ifndef HAVE_STRUCT_FLOCK64
Dmitry V. Levin594eb8f2013-11-12 21:49:03 +000061struct flock64 {
62 short int l_type, l_whence;
63 int64_t l_start, l_len;
64 int l_pid;
65};
Dmitry V. Levin54cabef2014-03-03 23:09:47 +000066# endif
Dmitry V. Levin594eb8f2013-11-12 21:49:03 +000067
Dmitry V. Levin0eeda2c2013-05-01 16:37:08 +000068static void
69printflock64(struct tcb *tcp, long addr, int getlk)
70{
71 struct flock64 fl;
72
Dmitry V. Levine6019fd2015-07-20 16:44:51 +000073 if (umove_or_printaddr(tcp, addr, &fl))
Dmitry V. Levin0eeda2c2013-05-01 16:37:08 +000074 return;
Dmitry V. Levin0eeda2c2013-05-01 16:37:08 +000075 tprints("{type=");
76 printxval(lockfcmds, fl.l_type, "F_???");
77 tprints(", whence=");
78 printxval(whence_codes, fl.l_whence, "SEEK_???");
79 tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len);
80 if (getlk)
81 tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
82 else
83 tprints("}");
84}
Dmitry V. Levin54cabef2014-03-03 23:09:47 +000085#endif /* USE_PRINTFLOCK64 */
Dmitry V. Levin0eeda2c2013-05-01 16:37:08 +000086
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087static void
Denys Vlasenko30b5e5a2009-01-06 15:12:52 +000088printflock(struct tcb *tcp, long addr, int getlk)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089{
90 struct flock fl;
91
Denys Vlasenko7a862d72009-04-15 13:22:59 +000092#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin54cabef2014-03-03 23:09:47 +000093 if (
94# if SIZEOF_OFF_T > SIZEOF_LONG
Dmitry V. Levine6019fd2015-07-20 16:44:51 +000095 current_personality != DEFAULT_PERSONALITY &&
96# endif
Dmitry V. Levin54cabef2014-03-03 23:09:47 +000097 current_wordsize != sizeof(fl.l_start)) {
Denys Vlasenko9fd4f962012-03-19 09:36:42 +010098 if (current_wordsize == 4) {
Denys Vlasenko7a862d72009-04-15 13:22:59 +000099 /* 32-bit x86 app on x86_64 and similar cases */
100 struct {
101 short int l_type;
102 short int l_whence;
103 int32_t l_start; /* off_t */
104 int32_t l_len; /* off_t */
105 int32_t l_pid; /* pid_t */
106 } fl32;
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000107 if (umove_or_printaddr(tcp, addr, &fl32))
108 return;
109 fl.l_type = fl32.l_type;
110 fl.l_whence = fl32.l_whence;
111 fl.l_start = fl32.l_start;
112 fl.l_len = fl32.l_len;
113 fl.l_pid = fl32.l_pid;
Denys Vlasenko7a862d72009-04-15 13:22:59 +0000114 } else {
115 /* let people know we have a problem here */
Denys Vlasenko751acb32013-02-08 15:34:46 +0100116 tprintf("<decode error: unsupported wordsize %d>",
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100117 current_wordsize);
Denys Vlasenko7a862d72009-04-15 13:22:59 +0000118 return;
119 }
120 } else
121#endif
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000122 if (umove_or_printaddr(tcp, addr, &fl))
Dmitry V. Levin54cabef2014-03-03 23:09:47 +0000123 return;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200124 tprints("{type=");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125 printxval(lockfcmds, fl.l_type, "F_???");
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200126 tprints(", whence=");
Denys Vlasenko86738a22013-02-17 14:31:55 +0100127 printxval(whence_codes, fl.l_whence, "SEEK_???");
Dmitry V. Levin54cabef2014-03-03 23:09:47 +0000128#if SIZEOF_OFF_T > SIZEOF_LONG
Dmitry V. Levin0eeda2c2013-05-01 16:37:08 +0000129 tprintf(", start=%lld, len=%lld", fl.l_start, fl.l_len);
130#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131 tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
John Hughesbdf48f52001-03-06 15:08:09 +0000132#endif
Dmitry V. Levin0eeda2c2013-05-01 16:37:08 +0000133 if (getlk)
134 tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
135 else
136 tprints("}");
137}
John Hughesbdf48f52001-03-06 15:08:09 +0000138
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000139SYS_FUNC(fcntl)
Dmitry V. Levin9b5b67e2007-01-11 23:19:55 +0000140{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141 if (entering(tcp)) {
Dmitry V. Levin31382132011-03-04 05:08:02 +0300142 printfd(tcp, tcp->u_arg[0]);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200143 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144 printxval(fcntlcmds, tcp->u_arg[1], "F_???");
145 switch (tcp->u_arg[1]) {
146 case F_SETFD:
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200147 tprints(", ");
Roland McGrathb2dee132005-06-01 19:02:36 +0000148 printflags(fdflags, tcp->u_arg[2], "FD_???");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149 break;
150 case F_SETOWN: case F_DUPFD:
Denys Vlasenkoeedaac72009-03-10 20:41:58 +0000151#ifdef F_DUPFD_CLOEXEC
152 case F_DUPFD_CLOEXEC:
153#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154 tprintf(", %ld", tcp->u_arg[2]);
155 break;
156 case F_SETFL:
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200157 tprints(", ");
Denys Vlasenkoeedaac72009-03-10 20:41:58 +0000158 tprint_open_modes(tcp->u_arg[2]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159 break;
160 case F_SETLK: case F_SETLKW:
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200161 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162 printflock(tcp, tcp->u_arg[2], 0);
163 break;
Dmitry V. Levin54cabef2014-03-03 23:09:47 +0000164#if USE_PRINTFLOCK64
165 case F_SETLK64: case F_SETLKW64:
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200166 tprints(", ");
John Hughesbdf48f52001-03-06 15:08:09 +0000167 printflock64(tcp, tcp->u_arg[2], 0);
168 break;
Dmitry V. Levin54cabef2014-03-03 23:09:47 +0000169#endif /* USE_PRINTFLOCK64 */
Denys Vlasenkoeedaac72009-03-10 20:41:58 +0000170#ifdef F_NOTIFY
171 case F_NOTIFY:
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200172 tprints(", ");
Denys Vlasenkoeedaac72009-03-10 20:41:58 +0000173 printflags(notifyflags, tcp->u_arg[2], "DN_???");
174 break;
175#endif
176#ifdef F_SETLEASE
177 case F_SETLEASE:
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200178 tprints(", ");
Denys Vlasenkoeedaac72009-03-10 20:41:58 +0000179 printxval(lockfcmds, tcp->u_arg[2], "F_???");
180 break;
181#endif
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000182 }
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000183 } else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184 switch (tcp->u_arg[1]) {
185 case F_DUPFD:
Denys Vlasenkoeedaac72009-03-10 20:41:58 +0000186#ifdef F_DUPFD_CLOEXEC
187 case F_DUPFD_CLOEXEC:
188#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000189 case F_SETFD: case F_SETFL:
190 case F_SETLK: case F_SETLKW:
191 case F_SETOWN: case F_GETOWN:
Denys Vlasenkoeedaac72009-03-10 20:41:58 +0000192#ifdef F_NOTIFY
193 case F_NOTIFY:
194#endif
195#ifdef F_SETLEASE
196 case F_SETLEASE:
197#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198 break;
199 case F_GETFD:
Dmitry V. Levin21a75342008-09-03 01:22:18 +0000200 if (syserror(tcp) || tcp->u_rval == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201 return 0;
Denys Vlasenkoeedaac72009-03-10 20:41:58 +0000202 tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000203 return RVAL_HEX|RVAL_STR;
204 case F_GETFL:
Dmitry V. Levin21a75342008-09-03 01:22:18 +0000205 if (syserror(tcp))
206 return 0;
Dmitry V. Levin9b5b67e2007-01-11 23:19:55 +0000207 tcp->auxstr = sprint_open_modes(tcp->u_rval);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000208 return RVAL_HEX|RVAL_STR;
209 case F_GETLK:
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200210 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211 printflock(tcp, tcp->u_arg[2], 1);
212 break;
Dmitry V. Levin54cabef2014-03-03 23:09:47 +0000213#if USE_PRINTFLOCK64
John Hughesbdf48f52001-03-06 15:08:09 +0000214 case F_GETLK64:
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200215 tprints(", ");
John Hughesbdf48f52001-03-06 15:08:09 +0000216 printflock64(tcp, tcp->u_arg[2], 1);
217 break;
218#endif
Denys Vlasenkoeedaac72009-03-10 20:41:58 +0000219#ifdef F_GETLEASE
220 case F_GETLEASE:
221 if (syserror(tcp))
222 return 0;
223 tcp->auxstr = xlookup(lockfcmds, tcp->u_rval);
224 return RVAL_HEX|RVAL_STR;
225#endif
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000226 default:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000227 tprintf(", %#lx", tcp->u_arg[2]);
228 break;
229 }
230 }
231 return 0;
232}
233
234#ifdef LOCK_SH
235
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000236SYS_FUNC(flock)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000238 printfd(tcp, tcp->u_arg[0]);
239 tprints(", ");
240 printflags(flockcmds, tcp->u_arg[1], "LOCK_???");
241
242 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000243}
244#endif /* LOCK_SH */
245
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000246SYS_FUNC(close)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000247{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000248 printfd(tcp, tcp->u_arg[0]);
249
250 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251}
252
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000253SYS_FUNC(dup)
Zubin Mithra64aa1b12014-06-04 08:30:41 +0530254{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000255 printfd(tcp, tcp->u_arg[0]);
256
257 return RVAL_DECODED | RVAL_FD;
Zubin Mithra64aa1b12014-06-04 08:30:41 +0530258}
259
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000260static int
261do_dup2(struct tcb *tcp, int flags_arg)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000262{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000263 printfd(tcp, tcp->u_arg[0]);
264 tprints(", ");
265 printfd(tcp, tcp->u_arg[1]);
266 if (flags_arg >= 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200267 tprints(", ");
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000268 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000269 }
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000270
271 return RVAL_DECODED | RVAL_FD;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000272}
273
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000274SYS_FUNC(dup2)
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000275{
276 return do_dup2(tcp, -1);
277}
278
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000279SYS_FUNC(dup3)
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000280{
281 return do_dup2(tcp, 2);
282}
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000283
Denys Vlasenko84703742012-02-25 02:38:52 +0100284#if defined(ALPHA)
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000285SYS_FUNC(getdtablesize)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000286{
287 return 0;
288}
Denys Vlasenko84703742012-02-25 02:38:52 +0100289#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000290
Dmitry V. Levinc2982b52013-11-05 23:00:22 +0000291static int
Dmitry V. Levina7945a32006-12-13 17:10:11 +0000292decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000293{
Denys Vlasenkoad5155a2011-09-01 18:18:04 +0200294 int i, j;
Denys Vlasenko1f65c3c2013-11-05 16:20:16 +0100295 int nfds, fdsize;
Dmitry V. Levin6522f132014-09-09 22:42:12 +0000296 fd_set *fds = NULL;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000297 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000298 long arg;
299
Dmitry V. Levinf3696b32013-11-05 22:46:43 +0000300 /* Kernel truncates arg[0] to int, we do the same. */
301 nfds = (int) args[0];
302
303 /* Kernel rejects negative nfds, so we don't parse it either. */
Dmitry V. Levin6522f132014-09-09 22:42:12 +0000304 if (nfds < 0)
Dmitry V. Levinf3696b32013-11-05 22:46:43 +0000305 nfds = 0;
Dmitry V. Levin6522f132014-09-09 22:42:12 +0000306
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200307 /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
Dmitry V. Levinf3696b32013-11-05 22:46:43 +0000308 if (nfds > 1024*1024)
309 nfds = 1024*1024;
310
311 /*
312 * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below.
Dr. David Alan Gilbert025f1082013-11-05 11:54:51 +0100313 * Instead of args[0], use nfds for fd count, fdsize for array lengths.
314 */
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100315 fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200316
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000317 if (entering(tcp)) {
Dmitry V. Levinf3696b32013-11-05 22:46:43 +0000318 tprintf("%d", (int) args[0]);
319
Dmitry V. Levin3e9d71f2015-05-25 20:41:02 +0000320 if (verbose(tcp) && fdsize > 0)
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000321 fds = malloc(fdsize);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000322 for (i = 0; i < 3; i++) {
323 arg = args[i+1];
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000324 tprints(", ");
Dmitry V. Levin2fc5d802015-01-28 01:26:04 +0000325 if (!fds) {
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000326 printaddr(arg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000327 continue;
328 }
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000329 if (umoven_or_printaddr(tcp, arg, fdsize, fds))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000330 continue;
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000331 tprints("[");
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100332 for (j = 0, sep = "";; j++) {
333 j = next_set_bit(fds, j, nfds);
334 if (j < 0)
335 break;
336 tprints(sep);
337 printfd(tcp, j);
338 sep = " ";
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000339 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200340 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000341 }
Roland McGrathe85aaa42005-02-06 01:55:12 +0000342 free(fds);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200343 tprints(", ");
Roland McGrath6afc5652007-07-24 01:57:11 +0000344 printtv_bitness(tcp, args[4], bitness, 0);
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000345 } else {
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200346 static char outstr[1024];
347 char *outptr;
348#define end_outstr (outstr + sizeof(outstr))
Dmitry V. Levinf3696b32013-11-05 22:46:43 +0000349 int ready_fds;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000350
351 if (syserror(tcp))
352 return 0;
353
Dr. David Alan Gilbert025f1082013-11-05 11:54:51 +0100354 ready_fds = tcp->u_rval;
355 if (ready_fds == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000356 tcp->auxstr = "Timeout";
357 return RVAL_STR;
358 }
Roland McGrathe85aaa42005-02-06 01:55:12 +0000359
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000360 fds = malloc(fdsize);
Roland McGrathe85aaa42005-02-06 01:55:12 +0000361
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200362 outptr = outstr;
363 sep = "";
Dmitry V. Levinf3696b32013-11-05 22:46:43 +0000364 for (i = 0; i < 3 && ready_fds > 0; i++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000365 int first = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000366
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000367 arg = args[i+1];
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000368 if (!arg || !fds || umoven(tcp, arg, fdsize, fds) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000369 continue;
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100370 for (j = 0;; j++) {
371 j = next_set_bit(fds, j, nfds);
372 if (j < 0)
373 break;
374 /* +2 chars needed at the end: ']',NUL */
375 if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
376 if (first) {
377 outptr += sprintf(outptr, "%s%s [%u",
378 sep,
379 i == 0 ? "in" : i == 1 ? "out" : "except",
380 j
381 );
382 first = 0;
383 sep = ", ";
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000384 }
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100385 else {
386 outptr += sprintf(outptr, " %u", j);
387 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000388 }
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100389 if (--ready_fds == 0)
390 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391 }
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200392 if (outptr != outstr)
393 *outptr++ = ']';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000394 }
Roland McGrathe85aaa42005-02-06 01:55:12 +0000395 free(fds);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000396 /* This contains no useful information on SunOS. */
397 if (args[4]) {
Denys Vlasenkoa1d541e2012-01-20 11:04:04 +0100398 if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) {
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200399 outptr += sprintf(outptr, "%sleft ", sep);
Denys Vlasenkoa1d541e2012-01-20 11:04:04 +0100400 outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0);
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200401 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000402 }
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200403 *outptr = '\0';
Denys Vlasenko11617252011-09-01 11:27:37 +0200404 tcp->auxstr = outstr;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000405 return RVAL_STR;
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200406#undef end_outstr
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000407 }
408 return 0;
409}
410
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000411SYS_FUNC(oldselect)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000412{
Elvira Khabirovac44df3e2015-07-29 21:38:54 +0300413 long long_args[5];
414#undef oldselect_args
415#if SIZEOF_LONG == 4
416# define oldselect_args long_args
417#else
418 unsigned int oldselect_args[5];
419 unsigned int i;
420#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000421
Elvira Khabirovac44df3e2015-07-29 21:38:54 +0300422 if (umove(tcp, tcp->u_arg[0], &oldselect_args) < 0) {
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000423 printaddr(tcp->u_arg[0]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000424 return 0;
425 }
Elvira Khabirovac44df3e2015-07-29 21:38:54 +0300426#ifndef oldselect_args
427 for (i = 0; i < 5; i++) {
428 long_args[i] = oldselect_args[i];
429 }
430#endif
431 return decode_select(tcp, long_args, BITNESS_CURRENT);
432#undef oldselect_args
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433}
434
Wichert Akkermanf5eeabb1999-11-18 17:09:47 +0000435#ifdef ALPHA
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000436SYS_FUNC(osf_select)
Wichert Akkermanf5eeabb1999-11-18 17:09:47 +0000437{
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000438 return decode_select(tcp, tcp->u_arg, BITNESS_32);
Wichert Akkermanf5eeabb1999-11-18 17:09:47 +0000439}
440#endif
441
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +0000442#include "xlat/epollctls.h"
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +0000443#include "xlat/epollevents.h"
Dmitry V. Levind35bdca2014-04-26 18:10:19 +0000444#include "xlat/epollflags.h"
Roland McGrath93817bf2004-10-06 22:23:31 +0000445
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000446SYS_FUNC(epoll_create1)
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000447{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000448 printflags(epollflags, tcp->u_arg[0], "EPOLL_???");
449
450 return RVAL_DECODED;
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000451}
452
Roland McGrath63d6e542004-10-20 02:17:41 +0000453#ifdef HAVE_SYS_EPOLL_H
Roland McGrath93817bf2004-10-06 22:23:31 +0000454static void
Denys Vlasenko30b5e5a2009-01-06 15:12:52 +0000455print_epoll_event(struct epoll_event *ev)
Roland McGrath93817bf2004-10-06 22:23:31 +0000456{
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200457 tprints("{");
Roland McGrathb2dee132005-06-01 19:02:36 +0000458 printflags(epollevents, ev->events, "EPOLL???");
Roland McGrath93817bf2004-10-06 22:23:31 +0000459 /* We cannot know what format the program uses, so print u32 and u64
460 which will cover every value. */
461 tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}",
462 ev->data.u32, ev->data.u64);
463}
Roland McGrath63d6e542004-10-20 02:17:41 +0000464#endif
Roland McGrath93817bf2004-10-06 22:23:31 +0000465
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000466SYS_FUNC(epoll_ctl)
Roland McGrath93817bf2004-10-06 22:23:31 +0000467{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000468 struct epoll_event ev;
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000469
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000470 printfd(tcp, tcp->u_arg[0]);
471 tprints(", ");
472 printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???");
473 tprints(", ");
474 printfd(tcp, tcp->u_arg[2]);
475 tprints(", ");
Roland McGrath63d6e542004-10-20 02:17:41 +0000476#ifdef HAVE_SYS_EPOLL_H
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000477 if (EPOLL_CTL_DEL == tcp->u_arg[1])
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000478 printaddr(tcp->u_arg[3]);
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000479 else if (!umove_or_printaddr(tcp, tcp->u_arg[3], &ev))
480 print_epoll_event(&ev);
481#else
482 printaddr(tcp->u_arg[3]);
Dmitry V. Levine51ce472014-04-17 14:33:59 +0000483#endif
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000484
485 return RVAL_DECODED;
Roland McGrath93817bf2004-10-06 22:23:31 +0000486}
487
Roland McGrathf2400052007-08-02 01:13:26 +0000488static void
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000489print_epoll_event_array(struct tcb *tcp, const long addr, const long len)
490{
491#ifdef HAVE_SYS_EPOLL_H
492 struct epoll_event ev, *start, *cur, *end;
493
494 if (!len) {
495 tprints("[]");
496 return;
497 }
498
499 if (umove_or_printaddr(tcp, addr, &ev))
500 return;
501
502 tprints("[");
503 print_epoll_event(&ev);
504
505 start = (struct epoll_event *) addr;
506 end = start + len;
507 for (cur = start + 1; cur < end; ++cur) {
508 tprints(", ");
509 if (umove_or_printaddr(tcp, (long) cur, &ev))
510 break;
511 print_epoll_event(&ev);
512 }
513 tprints("]");
514#else
515 printaddr(addr);
516#endif
517}
518
519static void
Denys Vlasenko30b5e5a2009-01-06 15:12:52 +0000520epoll_wait_common(struct tcb *tcp)
Roland McGrath93817bf2004-10-06 22:23:31 +0000521{
Dmitry V. Levin31382132011-03-04 05:08:02 +0300522 if (entering(tcp)) {
523 printfd(tcp, tcp->u_arg[0]);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200524 tprints(", ");
Dmitry V. Levin31382132011-03-04 05:08:02 +0300525 } else {
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000526 print_epoll_event_array(tcp, tcp->u_arg[1], tcp->u_rval);
Dmitry V. Levinc327d712011-10-11 16:05:57 +0000527 tprintf(", %d, %d", (int) tcp->u_arg[2], (int) tcp->u_arg[3]);
Roland McGrath93817bf2004-10-06 22:23:31 +0000528 }
Roland McGrathf2400052007-08-02 01:13:26 +0000529}
530
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000531SYS_FUNC(epoll_wait)
Roland McGrathf2400052007-08-02 01:13:26 +0000532{
533 epoll_wait_common(tcp);
534 return 0;
535}
536
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000537SYS_FUNC(epoll_pwait)
Roland McGrathf2400052007-08-02 01:13:26 +0000538{
539 epoll_wait_common(tcp);
Dmitry V. Levin96764992010-04-06 23:54:18 +0000540 if (exiting(tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200541 tprints(", ");
Denys Vlasenko5e133aa2013-07-18 17:02:21 +0200542 /* NB: kernel requires arg[5] == NSIG / 8 */
543 print_sigset_addr_len(tcp, tcp->u_arg[4], tcp->u_arg[5]);
544 tprintf(", %lu", tcp->u_arg[5]);
Dmitry V. Levin96764992010-04-06 23:54:18 +0000545 }
Roland McGrath93817bf2004-10-06 22:23:31 +0000546 return 0;
547}
Roland McGrath37b9f842005-05-09 08:02:00 +0000548
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000549SYS_FUNC(select)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000550{
Dmitry V. Levina7945a32006-12-13 17:10:11 +0000551 return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000552}
Dmitry V. Levin95ebf5a2006-10-13 20:25:12 +0000553
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000554SYS_FUNC(pselect6)
Dmitry V. Levin95ebf5a2006-10-13 20:25:12 +0000555{
Dmitry V. Levina7945a32006-12-13 17:10:11 +0000556 int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
Roland McGrathfe10aa72007-11-01 21:52:20 +0000557 if (entering(tcp)) {
Denys Vlasenko8a1ebbb2013-07-18 18:10:13 +0200558 long r;
Dmitry V. Levin95ebf5a2006-10-13 20:25:12 +0000559 struct {
Denys Vlasenko8a1ebbb2013-07-18 18:10:13 +0200560 unsigned long ptr;
Dmitry V. Levin95ebf5a2006-10-13 20:25:12 +0000561 unsigned long len;
562 } data;
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000563
564 tprints(", ");
Denys Vlasenko8a1ebbb2013-07-18 18:10:13 +0200565#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
566 if (current_wordsize == 4) {
567 struct {
568 uint32_t ptr;
569 uint32_t len;
570 } data32;
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000571 r = umove_or_printaddr(tcp, tcp->u_arg[5], &data32);
Denys Vlasenko8a1ebbb2013-07-18 18:10:13 +0200572 data.ptr = data32.ptr;
573 data.len = data32.len;
574 } else
575#endif
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000576 r = umove_or_printaddr(tcp, tcp->u_arg[5], &data);
577 if (r == 0) {
578 tprints("{");
Denys Vlasenko5e133aa2013-07-18 17:02:21 +0200579 /* NB: kernel requires data.len == NSIG / 8 */
Denys Vlasenko8a1ebbb2013-07-18 18:10:13 +0200580 print_sigset_addr_len(tcp, data.ptr, data.len);
Dmitry V. Levin95ebf5a2006-10-13 20:25:12 +0000581 tprintf(", %lu}", data.len);
582 }
583 }
584 return rc;
585}
Roland McGrathe7c39672007-08-02 01:32:17 +0000586
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000587static int
588do_eventfd(struct tcb *tcp, int flags_arg)
Roland McGrathe7c39672007-08-02 01:32:17 +0000589{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000590 tprintf("%lu", tcp->u_arg[0]);
591 if (flags_arg >= 0) {
592 tprints(", ");
593 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000594 }
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000595
596 return RVAL_DECODED;
Roland McGrathe7c39672007-08-02 01:32:17 +0000597}
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000598
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000599SYS_FUNC(eventfd)
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000600{
601 return do_eventfd(tcp, -1);
602}
603
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000604SYS_FUNC(eventfd2)
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000605{
606 return do_eventfd(tcp, 1);
607}
Ben Noordhuis88eafd82013-02-04 00:04:57 +0100608
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000609SYS_FUNC(perf_event_open)
Ben Noordhuis88eafd82013-02-04 00:04:57 +0100610{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000611 printaddr(tcp->u_arg[0]);
612 tprintf(", %d, %d, %d, ",
613 (int) tcp->u_arg[1],
614 (int) tcp->u_arg[2],
615 (int) tcp->u_arg[3]);
616 printflags(perf_event_open_flags, tcp->u_arg[4],
617 "PERF_FLAG_???");
618
619 return RVAL_DECODED;
Ben Noordhuis88eafd82013-02-04 00:04:57 +0100620}