1 /*
2 * Copyright (c) 2004-2007 Ulrich Drepper <drepper@redhat.com>
3 * Copyright (c) 2004 Roland McGrath <roland@redhat.com>
4 * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2015-2021 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: LGPL-2.1-or-later
9 */
10
11 #include "defs.h"
12 #include "kernel_fcntl.h"
13 #include <sys/epoll.h>
14
15 SYS_FUNC(epoll_create)
16 {
17 /* size */
18 int size = tcp->u_arg[0];
19 PRINT_VAL_D(size);
20
21 return RVAL_DECODED | RVAL_FD;
22 }
23
24 #include "xlat/epollflags.h"
25
26 SYS_FUNC(epoll_create1)
27 {
28 /* flags */
29 printflags(epollflags, tcp->u_arg[0], "EPOLL_???");
30
31 return RVAL_DECODED | RVAL_FD;
32 }
33
34 #include "xlat/epollevents.h"
35
36 static void
37 print_epoll_data(const epoll_data_t data)
38 {
39 /*
40 * We cannot know what format the tracee uses, so
41 * print both u32 and u66 which will cover every value.
42 */
43 tprint_struct_begin();
44 PRINT_FIELD_U(data, u32);
45 tprint_struct_next();
46 PRINT_FIELD_U(data, u64);
47 tprint_struct_end();
48 }
49
50 static bool
51 print_epoll_event(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
52 {
53 const struct epoll_event *ev = elem_buf;
54
55 tprint_struct_begin();
56 PRINT_FIELD_FLAGS(*ev, events, epollevents, "EPOLL???");
57 tprint_struct_next();
58 PRINT_FIELD_OBJ_VAL(*ev, data, print_epoll_data);
59 tprint_struct_end();
60
61 return true;
62 }
63
64 #include "xlat/epollctls.h"
65
66 SYS_FUNC(epoll_ctl)
67 {
68 /* epfd */
69 printfd(tcp, tcp->u_arg[0]);
70 tprint_arg_next();
71
72 /* op */
73 const unsigned int op = tcp->u_arg[1];
74 printxval(epollctls, op, "EPOLL_CTL_???");
75 tprint_arg_next();
76
77 /* fd */
78 printfd(tcp, tcp->u_arg[2]);
79 tprint_arg_next();
80
81 /* event */
82 struct epoll_event ev;
83 if (EPOLL_CTL_DEL == op)
84 printaddr(tcp->u_arg[3]);
85 else if (!umove_or_printaddr(tcp, tcp->u_arg[3], &ev))
86 print_epoll_event(tcp, &ev, sizeof(ev), 0);
87
88 return RVAL_DECODED;
89 }
90
91 static void
92 epoll_wait_common(struct tcb *tcp, const print_obj_by_addr_fn print_timeout)
93 {
94 if (entering(tcp)) {
95 /* epfd */
96 printfd(tcp, tcp->u_arg[0]);
97 tprint_arg_next();
98 } else {
99 /* events */
100 struct epoll_event ev;
101 print_array(tcp, tcp->u_arg[1], tcp->u_rval, &ev, sizeof(ev),
102 tfetch_mem, print_epoll_event, 0);
103 tprint_arg_next();
104
105 /* maxevents */
106 int maxevents = tcp->u_arg[2];
107 PRINT_VAL_D(maxevents);
108 tprint_arg_next();
109
110 /* timeout */
111 print_timeout(tcp, tcp->u_arg[3]);
112 }
113 }
114
115 static int
116 print_timeout_int(struct tcb *tcp, kernel_ulong_t arg)
117 {
118 int timeout = arg;
119 PRINT_VAL_D(timeout);
120 return 0;
121 }
122
123 SYS_FUNC(epoll_wait)
124 {
125 epoll_wait_common(tcp, print_timeout_int);
126 return 0;
127 }
128
129 static int
130 epoll_pwait_common(struct tcb *tcp, const print_obj_by_addr_fn print_timeout)
131 {
132 epoll_wait_common(tcp, print_timeout);
133 if (exiting(tcp)) {
134 tprint_arg_next();
135 /* sigmask */
136 /* NB: kernel requires arg[5] == NSIG_BYTES */
137 print_sigset_addr_len(tcp, tcp->u_arg[4], tcp->u_arg[5]);
138 tprint_arg_next();
139
140 /* sigsetsize */
141 PRINT_VAL_U(tcp->u_arg[5]);
142 }
143 return 0;
144 }
145
146 SYS_FUNC(epoll_pwait)
147 {
148 return epoll_pwait_common(tcp, print_timeout_int);
149 }
150
151 SYS_FUNC(epoll_pwait2)
152 {
153 return epoll_pwait_common(tcp, print_timespec64);
154 }