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 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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-2019 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 sprint_obj_by_addr_fn sprint_ts,
  38. const kernel_ulong_t pts)
  39. {
  40. struct pollfd fds;
  41. const unsigned int nfds = tcp->u_arg[1];
  42. const unsigned long size = sizeof(fds) * nfds;
  43. const kernel_ulong_t start = tcp->u_arg[0];
  44. const kernel_ulong_t end = start + size;
  45. kernel_ulong_t cur;
  46. const unsigned int max_printed =
  47. abbrev(tcp) ? max_strlen : -1U;
  48. unsigned int printed;
  49. static char outstr[1024];
  50. char *outptr;
  51. #define end_outstr (outstr + sizeof(outstr))
  52. if (syserror(tcp))
  53. return 0;
  54. if (tcp->u_rval == 0) {
  55. tcp->auxstr = "Timeout";
  56. return RVAL_STR;
  57. }
  58. if (!verbose(tcp) || !start || !nfds ||
  59. size / sizeof(fds) != nfds || end < start)
  60. return 0;
  61. outptr = outstr;
  62. for (printed = 0, cur = start; cur < end; cur += sizeof(fds)) {
  63. if (umove(tcp, cur, &fds) < 0) {
  64. if (outptr == outstr)
  65. *outptr++ = '[';
  66. else
  67. outptr = stpcpy(outptr, ", ");
  68. outptr = xappendstr(outstr, outptr, "%#" PRI_klx, cur);
  69. break;
  70. }
  71. if (!fds.revents)
  72. continue;
  73. if (outptr == outstr)
  74. *outptr++ = '[';
  75. else
  76. outptr = stpcpy(outptr, ", ");
  77. if (printed >= max_printed) {
  78. outptr = stpcpy(outptr, "...");
  79. break;
  80. }
  81. static const char fmt[] = "{fd=%d, revents=";
  82. char fdstr[sizeof(fmt) + sizeof(int) * 3];
  83. xsprintf(fdstr, fmt, fds.fd);
  84. const char *flagstr = sprintflags("", pollflags,
  85. (unsigned short) fds.revents);
  86. if (outptr + strlen(fdstr) + strlen(flagstr) + 1 >=
  87. end_outstr - (2 + 2 * sizeof(long) + sizeof(", ], ..."))) {
  88. outptr = stpcpy(outptr, "...");
  89. break;
  90. }
  91. outptr = stpcpy(outptr, fdstr);
  92. outptr = stpcpy(outptr, flagstr);
  93. *outptr++ = '}';
  94. ++printed;
  95. }
  96. if (outptr != outstr)
  97. *outptr++ = ']';
  98. *outptr = '\0';
  99. if (pts) {
  100. const char *str = sprint_ts(tcp, pts);
  101. if (outptr + sizeof(", left ") + strlen(str) < end_outstr) {
  102. outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
  103. outptr = stpcpy(outptr, str);
  104. } else {
  105. outptr = stpcpy(outptr, ", ...");
  106. }
  107. }
  108. if (outptr == outstr)
  109. return 0;
  110. tcp->auxstr = outstr;
  111. return RVAL_STR;
  112. #undef end_outstr
  113. }
  114. #if HAVE_ARCH_TIME32_SYSCALLS || HAVE_ARCH_OLD_TIME64_SYSCALLS
  115. static int
  116. do_poll(struct tcb *const tcp, const sprint_obj_by_addr_fn sprint_ts)
  117. {
  118. if (entering(tcp)) {
  119. decode_poll_entering(tcp);
  120. tprintf("%d", (int) tcp->u_arg[2]);
  121. return 0;
  122. } else {
  123. return decode_poll_exiting(tcp, sprint_ts, 0);
  124. }
  125. }
  126. #endif /* HAVE_ARCH_TIME32_SYSCALLS || HAVE_ARCH_OLD_TIME64_SYSCALLS */
  127. #if HAVE_ARCH_TIME32_SYSCALLS
  128. SYS_FUNC(poll_time32)
  129. {
  130. return do_poll(tcp, sprint_timespec32);
  131. }
  132. #endif
  133. #if HAVE_ARCH_OLD_TIME64_SYSCALLS
  134. SYS_FUNC(poll_time64)
  135. {
  136. return do_poll(tcp, sprint_timespec64);
  137. }
  138. #endif
  139. static int
  140. do_ppoll(struct tcb *const tcp, const print_obj_by_addr_fn print_ts,
  141. const sprint_obj_by_addr_fn sprint_ts)
  142. {
  143. if (entering(tcp)) {
  144. decode_poll_entering(tcp);
  145. print_ts(tcp, tcp->u_arg[2]);
  146. tprints(", ");
  147. /* NB: kernel requires arg[4] == NSIG_BYTES */
  148. print_sigset_addr_len(tcp, tcp->u_arg[3], tcp->u_arg[4]);
  149. tprintf(", %" PRI_klu, tcp->u_arg[4]);
  150. return 0;
  151. } else {
  152. return decode_poll_exiting(tcp, sprint_ts, tcp->u_arg[2]);
  153. }
  154. }
  155. #if HAVE_ARCH_TIME32_SYSCALLS
  156. SYS_FUNC(ppoll_time32)
  157. {
  158. return do_ppoll(tcp, print_timespec32, sprint_timespec32);
  159. }
  160. #endif
  161. SYS_FUNC(ppoll_time64)
  162. {
  163. return do_ppoll(tcp, print_timespec64, sprint_timespec64);
  164. }