Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

poll.c 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
  3. * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
  4. * Copyright (c) 1999-2018 The strace developers.
  5. * All rights reserved.
  6. *
  7. * SPDX-License-Identifier: LGPL-2.1-or-later
  8. */
  9. #include "defs.h"
  10. #include <poll.h>
  11. #include "xstring.h"
  12. #include "xlat/pollflags.h"
  13. static bool
  14. print_pollfd(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
  15. {
  16. const struct pollfd *fds = elem_buf;
  17. tprints("{fd=");
  18. printfd(tcp, fds->fd);
  19. if (fds->fd >= 0) {
  20. tprints(", events=");
  21. printflags(pollflags, (unsigned short) fds->events, "POLL???");
  22. }
  23. tprints("}");
  24. return true;
  25. }
  26. static void
  27. decode_poll_entering(struct tcb *tcp)
  28. {
  29. const kernel_ulong_t addr = tcp->u_arg[0];
  30. const unsigned int nfds = tcp->u_arg[1];
  31. struct pollfd fds;
  32. print_array(tcp, addr, nfds, &fds, sizeof(fds),
  33. tfetch_mem, print_pollfd, 0);
  34. tprintf(", %u, ", nfds);
  35. }
  36. static int
  37. decode_poll_exiting(struct tcb *const tcp, const kernel_ulong_t pts)
  38. {
  39. struct pollfd fds;
  40. const unsigned int nfds = tcp->u_arg[1];
  41. const unsigned long size = sizeof(fds) * nfds;
  42. const kernel_ulong_t start = tcp->u_arg[0];
  43. const kernel_ulong_t end = start + size;
  44. kernel_ulong_t cur;
  45. const unsigned int max_printed =
  46. abbrev(tcp) ? max_strlen : -1U;
  47. unsigned int printed;
  48. static char outstr[1024];
  49. char *outptr;
  50. #define end_outstr (outstr + sizeof(outstr))
  51. if (syserror(tcp))
  52. return 0;
  53. if (tcp->u_rval == 0) {
  54. tcp->auxstr = "Timeout";
  55. return RVAL_STR;
  56. }
  57. if (!verbose(tcp) || !start || !nfds ||
  58. size / sizeof(fds) != nfds || end < start)
  59. return 0;
  60. outptr = outstr;
  61. for (printed = 0, cur = start; cur < end; cur += sizeof(fds)) {
  62. if (umove(tcp, cur, &fds) < 0) {
  63. if (outptr == outstr)
  64. *outptr++ = '[';
  65. else
  66. outptr = stpcpy(outptr, ", ");
  67. outptr = xappendstr(outstr, outptr, "%#" PRI_klx, cur);
  68. break;
  69. }
  70. if (!fds.revents)
  71. continue;
  72. if (outptr == outstr)
  73. *outptr++ = '[';
  74. else
  75. outptr = stpcpy(outptr, ", ");
  76. if (printed >= max_printed) {
  77. outptr = stpcpy(outptr, "...");
  78. break;
  79. }
  80. static const char fmt[] = "{fd=%d, revents=";
  81. char fdstr[sizeof(fmt) + sizeof(int) * 3];
  82. xsprintf(fdstr, fmt, fds.fd);
  83. const char *flagstr = sprintflags("", pollflags,
  84. (unsigned short) fds.revents);
  85. if (outptr + strlen(fdstr) + strlen(flagstr) + 1 >=
  86. end_outstr - (2 + 2 * sizeof(long) + sizeof(", ], ..."))) {
  87. outptr = stpcpy(outptr, "...");
  88. break;
  89. }
  90. outptr = stpcpy(outptr, fdstr);
  91. outptr = stpcpy(outptr, flagstr);
  92. *outptr++ = '}';
  93. ++printed;
  94. }
  95. if (outptr != outstr)
  96. *outptr++ = ']';
  97. *outptr = '\0';
  98. if (pts) {
  99. const char *str = sprint_timespec(tcp, pts);
  100. if (outptr + sizeof(", left ") + strlen(str) < end_outstr) {
  101. outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
  102. outptr = stpcpy(outptr, str);
  103. } else {
  104. outptr = stpcpy(outptr, ", ...");
  105. }
  106. }
  107. if (outptr == outstr)
  108. return 0;
  109. tcp->auxstr = outstr;
  110. return RVAL_STR;
  111. #undef end_outstr
  112. }
  113. SYS_FUNC(poll)
  114. {
  115. if (entering(tcp)) {
  116. decode_poll_entering(tcp);
  117. tprintf("%d", (int) tcp->u_arg[2]);
  118. return 0;
  119. } else {
  120. return decode_poll_exiting(tcp, 0);
  121. }
  122. }
  123. SYS_FUNC(ppoll)
  124. {
  125. if (entering(tcp)) {
  126. decode_poll_entering(tcp);
  127. print_timespec(tcp, tcp->u_arg[2]);
  128. tprints(", ");
  129. /* NB: kernel requires arg[4] == NSIG_BYTES */
  130. print_sigset_addr_len(tcp, tcp->u_arg[3], tcp->u_arg[4]);
  131. tprintf(", %" PRI_klu, tcp->u_arg[4]);
  132. return 0;
  133. } else {
  134. return decode_poll_exiting(tcp, tcp->u_arg[2]);
  135. }
  136. }