#include "xlat/pollflags.h"
+static bool
+print_pollfd(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
+{
+ const struct pollfd *fds = elem_buf;
+
+ tprints("{fd=");
+ printfd(tcp, fds->fd);
+ if (fds->fd >= 0) {
+ tprints(", events=");
+ printflags(pollflags, (unsigned short) fds->events, "POLL???");
+ }
+ tprints("}");
+
+ return true;
+}
+
+static void
+decode_poll_entering(struct tcb *tcp)
+{
+ const unsigned long addr = tcp->u_arg[0];
+ const unsigned int nfds = tcp->u_arg[1];
+ struct pollfd fds;
+
+ print_array(tcp, addr, nfds, &fds, sizeof(fds),
+ umoven_or_printaddr, print_pollfd, 0);
+ tprintf(", %u, ", nfds);
+}
+
static int
-decode_poll(struct tcb *tcp, long pts)
+decode_poll_exiting(struct tcb *tcp, const long pts)
{
struct pollfd fds;
- unsigned nfds;
- unsigned long size, start, cur, end, abbrev_end;
- int failed = 0;
+ const unsigned int nfds = tcp->u_arg[1];
+ const unsigned long size = sizeof(fds) * nfds;
+ const unsigned long start = tcp->u_arg[0];
+ const unsigned long end = start + size;
+ const unsigned long max_printed =
+ abbrev(tcp) ? max_strlen : (unsigned int) -1;
+ unsigned long printed, cur;
- if (entering(tcp)) {
- nfds = tcp->u_arg[1];
- size = sizeof(fds) * nfds;
- start = tcp->u_arg[0];
- end = start + size;
- if (nfds == 0 || size / sizeof(fds) != nfds || end < start) {
- tprintf("%#lx, %d, ",
- tcp->u_arg[0], nfds);
- return 0;
- }
- if (abbrev(tcp)) {
- abbrev_end = start + max_strlen * sizeof(fds);
- if (abbrev_end < start)
- abbrev_end = end;
- } else {
- abbrev_end = end;
- }
- tprints("[");
- for (cur = start; cur < end; cur += sizeof(fds)) {
- if (cur > start)
- tprints(", ");
- if (cur >= abbrev_end) {
- tprints("...");
- break;
- }
- if (umoven(tcp, cur, sizeof fds, &fds) < 0) {
- tprints("?");
- failed = 1;
- break;
- }
- if (fds.fd < 0) {
- tprintf("{fd=%d}", fds.fd);
- continue;
- }
- tprints("{fd=");
- printfd(tcp, fds.fd);
- tprints(", events=");
- printflags(pollflags, fds.events, "POLL???");
- tprints("}");
- }
- tprints("]");
- if (failed)
- tprintf(" %#lx", start);
- tprintf(", %d, ", nfds);
- return 0;
- } else {
- static char outstr[1024];
- char *outptr;
+ static char outstr[1024];
+ char *outptr;
#define end_outstr (outstr + sizeof(outstr))
- const char *flagstr;
- if (syserror(tcp))
- return 0;
- if (tcp->u_rval == 0) {
- tcp->auxstr = "Timeout";
- return RVAL_STR;
- }
+ if (syserror(tcp))
+ return 0;
+ if (tcp->u_rval == 0) {
+ tcp->auxstr = "Timeout";
+ return RVAL_STR;
+ }
- nfds = tcp->u_arg[1];
- size = sizeof(fds) * nfds;
- start = tcp->u_arg[0];
- end = start + size;
- if (nfds == 0 || size / sizeof(fds) != nfds || end < start)
- return 0;
- if (abbrev(tcp)) {
- abbrev_end = start + max_strlen * sizeof(fds);
- if (abbrev_end < start)
- abbrev_end = end;
- } else {
- abbrev_end = end;
- }
+ if (!verbose(tcp) || !start || !nfds ||
+ size / sizeof(fds) != nfds || end < start)
+ return 0;
+
+ outptr = outstr;
- outptr = outstr;
-
- for (cur = start; cur < end; cur += sizeof(fds)) {
- if (umoven(tcp, cur, sizeof fds, &fds) < 0) {
- if (outptr < end_outstr - 2)
- *outptr++ = '?';
- failed = 1;
- break;
- }
- if (!fds.revents)
- continue;
- if (outptr == outstr) {
+ for (printed = 0, cur = start; cur < end; cur += sizeof(fds)) {
+ if (umove(tcp, cur, &fds) < 0) {
+ if (outptr == outstr)
*outptr++ = '[';
- } else {
- if (outptr < end_outstr - 3)
- outptr = stpcpy(outptr, ", ");
- }
- if (cur >= abbrev_end) {
- if (outptr < end_outstr - 4)
- outptr = stpcpy(outptr, "...");
- break;
- }
- if (outptr < end_outstr - (sizeof("{fd=%d, revents=") + sizeof(int)*3) + 1)
- outptr += sprintf(outptr, "{fd=%d, revents=", fds.fd);
- flagstr = sprintflags("", pollflags, fds.revents);
- if (outptr < end_outstr - (strlen(flagstr) + 2)) {
- outptr = stpcpy(outptr, flagstr);
- *outptr++ = '}';
- }
+ else
+ outptr = stpcpy(outptr, ", ");
+ outptr += sprintf(outptr, "%#lx", cur);
+ break;
}
- if (failed)
- return 0;
-
- if (outptr != outstr /* && outptr < end_outstr - 1 (always true)*/)
- *outptr++ = ']';
-
- *outptr = '\0';
- if (pts) {
- if (outptr < end_outstr - (10 + TIMESPEC_TEXT_BUFSIZE)) {
- outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
- sprint_timespec(outptr, tcp, pts);
- }
+ if (!fds.revents)
+ continue;
+ if (outptr == outstr)
+ *outptr++ = '[';
+ else
+ outptr = stpcpy(outptr, ", ");
+ if (printed >= max_printed) {
+ outptr = stpcpy(outptr, "...");
+ break;
}
- if (outptr == outstr)
- return 0;
+ static const char fmt[] = "{fd=%d, revents=";
+ char fdstr[sizeof(fmt) + sizeof(int) * 3];
+ sprintf(fdstr, fmt, fds.fd);
- tcp->auxstr = outstr;
- return RVAL_STR;
-#undef end_outstr
+ const char *flagstr = sprintflags("", pollflags,
+ (unsigned short) fds.revents);
+
+ if (outptr + strlen(fdstr) + strlen(flagstr) + 1 >=
+ end_outstr - (2 + 2 * sizeof(long) + sizeof(", ], ..."))) {
+ outptr = stpcpy(outptr, "...");
+ break;
+ }
+ outptr = stpcpy(outptr, fdstr);
+ outptr = stpcpy(outptr, flagstr);
+ *outptr++ = '}';
+ ++printed;
+ }
+
+ if (outptr != outstr)
+ *outptr++ = ']';
+
+ *outptr = '\0';
+ if (pts) {
+ const char *str = sprint_timespec(tcp, pts);
+
+ if (outptr + sizeof(", left ") + strlen(str) < end_outstr) {
+ outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
+ outptr = stpcpy(outptr, str);
+ } else {
+ outptr = stpcpy(outptr, ", ...");
+ }
}
+
+ if (outptr == outstr)
+ return 0;
+
+ tcp->auxstr = outstr;
+ return RVAL_STR;
+#undef end_outstr
}
SYS_FUNC(poll)
{
- int rc = decode_poll(tcp, 0);
if (entering(tcp)) {
+ decode_poll_entering(tcp);
+ int timeout = tcp->u_arg[2];
+
#ifdef INFTIM
- if (tcp->u_arg[2] == INFTIM)
+ if (INFTIM == timeout)
tprints("INFTIM");
else
#endif
- tprintf("%ld", tcp->u_arg[2]);
+ tprintf("%d", timeout);
+
+ return 0;
+ } else {
+ return decode_poll_exiting(tcp, 0);
}
- return rc;
}
SYS_FUNC(ppoll)
{
- int rc = decode_poll(tcp, tcp->u_arg[2]);
if (entering(tcp)) {
+ decode_poll_entering(tcp);
+
print_timespec(tcp, tcp->u_arg[2]);
tprints(", ");
/* NB: kernel requires arg[4] == NSIG / 8 */
print_sigset_addr_len(tcp, tcp->u_arg[3], tcp->u_arg[4]);
tprintf(", %lu", tcp->u_arg[4]);
+
+ return 0;
+ } else {
+ return decode_poll_exiting(tcp, tcp->u_arg[2]);
}
- return rc;
}