(root)/
strace-6.5/
tests-mx32/
poll.c
       1  /*
       2   * Check decoding of poll syscall.
       3   *
       4   * Copyright (c) 2016-2018 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include "scno.h"
      13  
      14  #ifdef __NR_poll
      15  
      16  # include <assert.h>
      17  # include <errno.h>
      18  # include <poll.h>
      19  # include <stdio.h>
      20  # include <stdlib.h>
      21  # include <string.h>
      22  # include <unistd.h>
      23  
      24  # define PRINT_EVENT(flag, member)			\
      25  	do {						\
      26  		if (member & flag) {			\
      27  			if (member != pfd->member)	\
      28  				tprintf("|");		\
      29  			tprintf(#flag);			\
      30  			member &= ~flag;		\
      31  		}					\
      32  	} while (0)
      33  
      34  static void
      35  print_pollfd_entering(const struct pollfd *const pfd)
      36  {
      37  	tprintf("{fd=%d", pfd->fd);
      38  	if (pfd->fd >= 0) {
      39  		tprintf(", events=");
      40  		short events = pfd->events;
      41  
      42  		if (pfd->events) {
      43  			PRINT_EVENT(POLLIN, events);
      44  			PRINT_EVENT(POLLPRI, events);
      45  			PRINT_EVENT(POLLOUT, events);
      46  # ifdef POLLRDNORM
      47  			PRINT_EVENT(POLLRDNORM, events);
      48  # endif
      49  # ifdef POLLWRNORM
      50  			PRINT_EVENT(POLLWRNORM, events);
      51  # endif
      52  # ifdef POLLRDBAND
      53  			PRINT_EVENT(POLLRDBAND, events);
      54  # endif
      55  # ifdef POLLWRBAND
      56  			PRINT_EVENT(POLLWRBAND, events);
      57  # endif
      58  			PRINT_EVENT(POLLERR, events);
      59  			PRINT_EVENT(POLLHUP, events);
      60  			PRINT_EVENT(POLLNVAL, events);
      61  		} else
      62  			tprintf("0");
      63  	}
      64  	tprintf("}");
      65  }
      66  
      67  static void
      68  print_pollfd_array_entering(const struct pollfd *const pfd,
      69  			    const unsigned int size,
      70  			    const unsigned int valid,
      71  			    const unsigned int abbrev)
      72  {
      73  	tprintf("[");
      74  	for (unsigned int i = 0; i < size; ++i) {
      75  		if (i)
      76  			tprintf(", ");
      77  		if (i >= valid) {
      78  			tprintf("... /* %p */", &pfd[i]);
      79  			break;
      80  		}
      81  		if (i >= abbrev) {
      82  			tprintf("...");
      83  			break;
      84  		}
      85  		print_pollfd_entering(&pfd[i]);
      86  	}
      87  	tprintf("]");
      88  }
      89  
      90  static void
      91  print_pollfd_exiting(const struct pollfd *const pfd,
      92  		     unsigned int *const seen,
      93  		     const unsigned int abbrev)
      94  {
      95  	if (!pfd->revents || pfd->fd < 0 || *seen > abbrev)
      96  		return;
      97  
      98  	if (*seen)
      99  		tprintf(", ");
     100  	++(*seen);
     101  
     102  	if (*seen > abbrev) {
     103  		tprintf("...");
     104  		return;
     105  	}
     106  	tprintf("{fd=%d, revents=", pfd->fd);
     107  	short revents = pfd->revents;
     108  
     109  	PRINT_EVENT(POLLIN, revents);
     110  	PRINT_EVENT(POLLPRI, revents);
     111  	PRINT_EVENT(POLLOUT, revents);
     112  # ifdef POLLRDNORM
     113  	PRINT_EVENT(POLLRDNORM, revents);
     114  # endif
     115  # ifdef POLLWRNORM
     116  	PRINT_EVENT(POLLWRNORM, revents);
     117  # endif
     118  # ifdef POLLRDBAND
     119  	PRINT_EVENT(POLLRDBAND, revents);
     120  # endif
     121  # ifdef POLLWRBAND
     122  	PRINT_EVENT(POLLWRBAND, revents);
     123  # endif
     124  	PRINT_EVENT(POLLERR, revents);
     125  	PRINT_EVENT(POLLHUP, revents);
     126  	PRINT_EVENT(POLLNVAL, revents);
     127  	tprintf("}");
     128  }
     129  
     130  static void
     131  print_pollfd_array_exiting(const struct pollfd *const pfd,
     132  			   const unsigned int size,
     133  			   const unsigned int abbrev)
     134  {
     135  	tprintf("[");
     136  	unsigned int seen = 0;
     137  	for (unsigned int i = 0; i < size; ++i)
     138  		print_pollfd_exiting(&pfd[i], &seen, abbrev);
     139  	tprintf("]");
     140  }
     141  
     142  int
     143  main(int ac, char **av)
     144  {
     145  # ifdef PATH_TRACING_FD
     146  	skip_if_unavailable("/proc/self/fd/");
     147  # endif
     148  
     149  	tprintf("%s", "");
     150  
     151  	assert(syscall(__NR_poll, NULL, 42, 0) == -1);
     152  	if (ENOSYS == errno)
     153  		perror_msg_and_skip("poll");
     154  
     155  # ifndef PATH_TRACING_FD
     156  	tprintf("poll(NULL, 42, 0) = -1 EFAULT (%m)\n");
     157  # endif
     158  
     159  	int fds[2];
     160  	if (pipe(fds) || pipe(fds))
     161  		perror_msg_and_fail("pipe");
     162  
     163  	const unsigned int abbrev = (ac > 1) ? atoi(av[1]) : -1;
     164  	const struct pollfd pfds0[] = {
     165  		{ .fd = 0, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND },
     166  		{ .fd = 1, .events = POLLOUT | POLLWRNORM | POLLWRBAND },
     167  		{ .fd = fds[0], .events = POLLIN | POLLPRI },
     168  		{ .fd = fds[1], .events = POLLOUT },
     169  		{ .fd = 2, .events = POLLOUT | POLLWRBAND }
     170  	};
     171  	struct pollfd *const tail_fds0 = tail_memdup(pfds0, sizeof(pfds0));
     172  	const int timeout = 42;
     173  	int rc = syscall(__NR_poll, tail_fds0, 0, timeout);
     174  	assert(rc == 0);
     175  
     176  # ifndef PATH_TRACING_FD
     177  	tprintf("poll([], 0, %d) = %d (Timeout)\n", timeout, rc);
     178  # endif
     179  
     180  	rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
     181  	assert(rc == 3);
     182  
     183  # ifndef PATH_TRACING_FD
     184  	tprintf("poll(");
     185  	print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
     186  				    ARRAY_SIZE(pfds0), abbrev);
     187  	tprintf(", %u, %d) = %d (",
     188  		(unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
     189  	print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
     190  	tprintf(")\n");
     191  # endif /* !PATH_TRACING_FD */
     192  
     193  	tail_fds0[0].fd = -1;
     194  	tail_fds0[2].fd = -3;
     195  	tail_fds0[4].events = 0;
     196  	rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
     197  	assert(rc == 2);
     198  
     199  # ifndef PATH_TRACING_FD
     200  	tprintf("poll(");
     201  	print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
     202  				    ARRAY_SIZE(pfds0), abbrev);
     203  	tprintf(", %u, %d) = %d (",
     204  		(unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
     205  	print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
     206  	tprintf(")\n");
     207  # endif /* !PATH_TRACING_FD */
     208  
     209  	tail_fds0[1].fd = -2;
     210  	tail_fds0[4].fd = -5;
     211  	rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
     212  	assert(rc == 1);
     213  
     214  # ifndef PATH_TRACING_FD
     215  	tprintf("poll(");
     216  	print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
     217  				    ARRAY_SIZE(pfds0), abbrev);
     218  	tprintf(", %u, %d) = %d (",
     219  		(unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
     220  	print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
     221  	tprintf(")\n");
     222  # endif /* !PATH_TRACING_FD */
     223  
     224  	struct pollfd pfds1[] = {
     225  		{ .fd = 1, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND },
     226  		{ .fd = 0, .events = POLLOUT | POLLWRNORM | POLLWRBAND }
     227  	};
     228  	struct pollfd *const tail_fds1 = tail_memdup(pfds1, sizeof(pfds1));
     229  	rc = syscall(__NR_poll, tail_fds1, ARRAY_SIZE(pfds1), timeout);
     230  	assert(rc == 0);
     231  
     232  # ifndef PATH_TRACING_FD
     233  	tprintf("poll(");
     234  	print_pollfd_array_entering(tail_fds1, ARRAY_SIZE(pfds1),
     235  				    ARRAY_SIZE(pfds1), abbrev);
     236  	tprintf(", %u, %d) = %d (Timeout)\n",
     237  		(unsigned int) ARRAY_SIZE(pfds1), timeout, rc);
     238  # endif /* !PATH_TRACING_FD */
     239  
     240  	const void *const efault = tail_fds0 + ARRAY_SIZE(pfds0);
     241  	rc = syscall(__NR_poll, efault, 1, 0);
     242  	assert(rc == -1);
     243  
     244  # ifndef PATH_TRACING_FD
     245  	tprintf("poll(%p, 1, 0) = -1 EFAULT (%m)\n", efault);
     246  # endif
     247  
     248  	const unsigned int valid = 1;
     249  	const void *const epfds = tail_fds0 + ARRAY_SIZE(pfds0) - valid;
     250  	rc = syscall(__NR_poll, epfds, valid + 1, 0);
     251  	assert(rc == -1);
     252  
     253  # ifndef PATH_TRACING_FD
     254  	tprintf("poll(");
     255  	print_pollfd_array_entering(epfds, valid + 1, valid, abbrev);
     256  	errno = EFAULT;
     257  	tprintf(", %u, 0) = -1 EFAULT (%m)\n", valid + 1);
     258  # endif /* !PATH_TRACING_FD */
     259  
     260  # ifdef PATH_TRACING_FD
     261  	memcpy(tail_fds0, pfds0, sizeof(pfds0));
     262  	tail_fds0[4].fd = PATH_TRACING_FD;
     263  
     264  	rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
     265  	assert(rc == 3);
     266  
     267  	tprintf("poll(");
     268  	print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
     269  				    ARRAY_SIZE(pfds0), abbrev);
     270  	tprintf(", %u, %d) = %d (",
     271  		(unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
     272  	print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
     273  	tprintf(")\n");
     274  
     275  	rc = syscall(__NR_poll, epfds, valid + 1, 0);
     276  	assert(rc == -1);
     277  
     278  	/* the 1st pollfd element is readable and contains PATH_TRACING_FD */
     279  	tprintf("poll(");
     280  	print_pollfd_array_entering(epfds, valid + 1, valid, abbrev);
     281  	errno = EFAULT;
     282  	tprintf(", %u, 0) = -1 EFAULT (%m)\n", valid + 1);
     283  # endif /* PATH_TRACING_FD */
     284  
     285  	tprintf("+++ exited with 0 +++\n");
     286  	return 0;
     287  }
     288  
     289  #else
     290  
     291  SKIP_MAIN_UNDEFINED("__NR_poll")
     292  
     293  #endif