2 * Check decoding of poll syscall.
4 * Copyright (c) 2016-2018 Dmitry V. Levin <ldv@altlinux.org>
7 * SPDX-License-Identifier: GPL-2.0-or-later
11 #include <asm/unistd.h>
23 #define PRINT_EVENT(flag, member) \
25 if (member & flag) { \
26 if (member != pfd->member) \
34 print_pollfd_entering(const struct pollfd *const pfd)
36 tprintf("{fd=%d", pfd->fd);
39 short events = pfd->events;
42 PRINT_EVENT(POLLIN, events);
43 PRINT_EVENT(POLLPRI, events);
44 PRINT_EVENT(POLLOUT, events);
46 PRINT_EVENT(POLLRDNORM, events);
49 PRINT_EVENT(POLLWRNORM, events);
52 PRINT_EVENT(POLLRDBAND, events);
55 PRINT_EVENT(POLLWRBAND, events);
57 PRINT_EVENT(POLLERR, events);
58 PRINT_EVENT(POLLHUP, events);
59 PRINT_EVENT(POLLNVAL, events);
67 print_pollfd_array_entering(const struct pollfd *const pfd,
68 const unsigned int size,
69 const unsigned int valid,
70 const unsigned int abbrev)
74 for (i = 0; i < size; ++i) {
78 tprintf("... /* %p */", &pfd[i]);
85 print_pollfd_entering(&pfd[i]);
91 print_pollfd_exiting(const struct pollfd *const pfd,
92 unsigned int *const seen,
93 const unsigned int abbrev)
95 if (!pfd->revents || pfd->fd < 0 || *seen > abbrev)
102 if (*seen > abbrev) {
106 tprintf("{fd=%d, revents=", pfd->fd);
107 short revents = pfd->revents;
109 PRINT_EVENT(POLLIN, revents);
110 PRINT_EVENT(POLLPRI, revents);
111 PRINT_EVENT(POLLOUT, revents);
113 PRINT_EVENT(POLLRDNORM, revents);
116 PRINT_EVENT(POLLWRNORM, revents);
119 PRINT_EVENT(POLLRDBAND, revents);
122 PRINT_EVENT(POLLWRBAND, revents);
124 PRINT_EVENT(POLLERR, revents);
125 PRINT_EVENT(POLLHUP, revents);
126 PRINT_EVENT(POLLNVAL, revents);
131 print_pollfd_array_exiting(const struct pollfd *const pfd,
132 const unsigned int size,
133 const unsigned int abbrev)
136 unsigned int seen = 0;
138 for (i = 0; i < size; ++i)
139 print_pollfd_exiting(&pfd[i], &seen, abbrev);
144 main(int ac, char **av)
146 # ifdef PATH_TRACING_FD
147 skip_if_unavailable("/proc/self/fd/");
152 assert(syscall(__NR_poll, NULL, 42, 0) == -1);
154 perror_msg_and_skip("poll");
156 # ifndef PATH_TRACING_FD
157 tprintf("poll(NULL, 42, 0) = -1 EFAULT (%m)\n");
161 if (pipe(fds) || pipe(fds))
162 perror_msg_and_fail("pipe");
164 const unsigned int abbrev = (ac > 1) ? atoi(av[1]) : -1;
165 const struct pollfd pfds0[] = {
166 { .fd = 0, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND },
167 { .fd = 1, .events = POLLOUT | POLLWRNORM | POLLWRBAND },
168 { .fd = fds[0], .events = POLLIN | POLLPRI },
169 { .fd = fds[1], .events = POLLOUT },
170 { .fd = 2, .events = POLLOUT | POLLWRBAND }
172 struct pollfd *const tail_fds0 = tail_memdup(pfds0, sizeof(pfds0));
173 const int timeout = 42;
174 int rc = syscall(__NR_poll, tail_fds0, 0, timeout);
177 # ifndef PATH_TRACING_FD
178 tprintf("poll([], 0, %d) = %d (Timeout)\n", timeout, rc);
181 rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
184 # ifndef PATH_TRACING_FD
186 print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
187 ARRAY_SIZE(pfds0), abbrev);
188 tprintf(", %u, %d) = %d (",
189 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
190 print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
192 # endif /* !PATH_TRACING_FD */
194 tail_fds0[0].fd = -1;
195 tail_fds0[2].fd = -3;
196 tail_fds0[4].events = 0;
197 rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
200 # ifndef PATH_TRACING_FD
202 print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
203 ARRAY_SIZE(pfds0), abbrev);
204 tprintf(", %u, %d) = %d (",
205 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
206 print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
208 # endif /* !PATH_TRACING_FD */
210 tail_fds0[1].fd = -2;
211 tail_fds0[4].fd = -5;
212 rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
215 # ifndef PATH_TRACING_FD
217 print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
218 ARRAY_SIZE(pfds0), abbrev);
219 tprintf(", %u, %d) = %d (",
220 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
221 print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
223 # endif /* !PATH_TRACING_FD */
225 struct pollfd pfds1[] = {
226 { .fd = 1, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND },
227 { .fd = 0, .events = POLLOUT | POLLWRNORM | POLLWRBAND }
229 struct pollfd *const tail_fds1 = tail_memdup(pfds1, sizeof(pfds1));
230 rc = syscall(__NR_poll, tail_fds1, ARRAY_SIZE(pfds1), timeout);
233 # ifndef PATH_TRACING_FD
235 print_pollfd_array_entering(tail_fds1, ARRAY_SIZE(pfds1),
236 ARRAY_SIZE(pfds1), abbrev);
237 tprintf(", %u, %d) = %d (Timeout)\n",
238 (unsigned int) ARRAY_SIZE(pfds1), timeout, rc);
239 # endif /* !PATH_TRACING_FD */
241 const void *const efault = tail_fds0 + ARRAY_SIZE(pfds0);
242 rc = syscall(__NR_poll, efault, 1, 0);
245 # ifndef PATH_TRACING_FD
246 tprintf("poll(%p, 1, 0) = -1 EFAULT (%m)\n", efault);
249 const unsigned int valid = 1;
250 const void *const epfds = tail_fds0 + ARRAY_SIZE(pfds0) - valid;
251 rc = syscall(__NR_poll, epfds, valid + 1, 0);
254 # ifndef PATH_TRACING_FD
256 print_pollfd_array_entering(epfds, valid + 1, valid, abbrev);
258 tprintf(", %u, 0) = -1 EFAULT (%m)\n", valid + 1);
259 # endif /* !PATH_TRACING_FD */
261 # ifdef PATH_TRACING_FD
262 memcpy(tail_fds0, pfds0, sizeof(pfds0));
263 tail_fds0[4].fd = PATH_TRACING_FD;
265 rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
269 print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
270 ARRAY_SIZE(pfds0), abbrev);
271 tprintf(", %u, %d) = %d (",
272 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
273 print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
276 rc = syscall(__NR_poll, epfds, valid + 1, 0);
279 /* the 1st pollfd element is readable and contains PATH_TRACING_FD */
281 print_pollfd_array_entering(epfds, valid + 1, valid, abbrev);
283 tprintf(", %u, 0) = -1 EFAULT (%m)\n", valid + 1);
284 # endif /* PATH_TRACING_FD */
286 tprintf("+++ exited with 0 +++\n");
292 SKIP_MAIN_UNDEFINED("__NR_poll")