Bug#369651: strace: show poll() parameters before blocking
Alan Curry
pacman at theworld.com
Thu Aug 30 23:42:51 UTC 2007
Roland McGrath writes the following:
>
>Please post your patch to strace-devel at lists.sourceforge.net for review.
>Standard form is to include ChangeLog entries before the patch.
OK, here it is. Updated to also provide the same benefit to ppoll().
2007-08-30 Alan Curry <pacman at world.std.com>
* stream.c (sprintflags): New function.
(decode_poll): Rearrange so that arguments are decoded and printed on
syscall entry, except for revents which are now printed in the auxstr.
(sys_poll): Print the timeout argument on syscall entry.
[LINUX] (sys_ppoll): Ditto.
Index: stream.c
===================================================================
RCS file: /cvsroot/strace/strace/stream.c,v
retrieving revision 1.26
diff -u -r1.26 stream.c
--- stream.c 13 Dec 2006 16:59:45 -0000 1.26
+++ stream.c 30 Aug 2007 23:40:13 -0000
@@ -296,6 +296,28 @@
{ 0, NULL },
};
+static const char *
+sprintflags(const struct xlat *xlat, int flags)
+{
+ static char outstr[1024];
+ char *sep;
+
+ outstr[0] = '\0';
+ sep = "";
+ for (; xlat->str; xlat++) {
+ if ((flags & xlat->val) == xlat->val) {
+ sprintf(outstr + strlen(outstr),
+ "%s%s", sep, xlat->str);
+ sep = "|";
+ flags &= ~xlat->val;
+ }
+ }
+ if (flags)
+ sprintf(outstr + strlen(outstr),
+ "%s%#x", sep, flags);
+ return outstr;
+}
+
static int
decode_poll(struct tcb *tcp)
{
@@ -304,62 +326,134 @@
unsigned long size, start, cur, end, abbrev_end;
int failed = 0;
- if (entering(tcp))
- return 0;
-
- 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)
+ 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;
+ }
+ tprintf("[");
+ for (cur = start; cur < end; cur += sizeof(fds)) {
+ if (cur > start)
+ tprintf(", ");
+ if (cur >= abbrev_end) {
+ tprintf("...");
+ break;
+ }
+ if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
+ tprintf("?");
+ failed = 1;
+ break;
+ }
+ if (fds.fd < 0) {
+ tprintf("{fd=%d}", fds.fd);
+ continue;
+ }
+ tprintf("{fd=%d, events=", fds.fd);
+ printflags(pollflags, fds.events, "POLL???");
+ tprintf("}");
+ }
+ tprintf("]");
+ if (failed)
+ tprintf(" %#lx", start);
+ tprintf(", %d, ", nfds);
+ return 0;
} else {
- abbrev_end = end;
- }
- tprintf("[");
- for (cur = start; cur < end; cur += sizeof(fds)) {
- if (cur > start)
- tprintf(", ");
- if (cur >= abbrev_end) {
- tprintf("...");
- break;
+ static char outstr[1024];
+ char str[64];
+ const char *flagstr;
+ unsigned int cumlen;
+
+ if (syserror(tcp))
+ return 0;
+ if (tcp->u_rval == 0) {
+ tcp->auxstr = "Timeout";
+ return RVAL_STR;
}
- if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
- tprintf("?");
- failed = 1;
- break;
+
+ 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 (fds.fd < 0) {
- tprintf("{fd=%d}", fds.fd);
- continue;
- }
- tprintf("{fd=%d, events=", fds.fd);
- printflags(pollflags, fds.events, "POLL???");
- if (!syserror(tcp) && fds.revents) {
- tprintf(", revents=");
- printflags(pollflags, fds.revents, "POLL???");
+
+ outstr[0] = '\0';
+ cumlen = 0;
+
+ for (cur = start; cur < end; cur += sizeof(fds)) {
+ if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
+ ++cumlen;
+ if (cumlen < sizeof(outstr))
+ strcat(outstr, "?");
+ failed = 1;
+ break;
+ }
+ if (!fds.revents)
+ continue;
+ if (!cumlen) {
+ ++cumlen;
+ strcat(outstr, "[");
+ } else {
+ cumlen += 2;
+ if (cumlen < sizeof(outstr))
+ strcat(outstr, ", ");
+ }
+ if (cur >= abbrev_end) {
+ cumlen += 3;
+ if (cumlen < sizeof(outstr))
+ strcat(outstr, "...");
+ break;
+ }
+ if (fds.fd < 0) {
+ sprintf(str, "{fd=%d}", fds.fd);
+ cumlen += strlen(str);
+ if (cumlen < sizeof(outstr))
+ strcat(outstr, str);
+ continue;
+ }
+ sprintf(str, "{fd=%d, revents=", fds.fd);
+ flagstr=sprintflags(pollflags, fds.revents);
+ cumlen += strlen(str) + strlen(flagstr) + 1;
+ if (cumlen < sizeof(outstr)) {
+ strcat(outstr, str);
+ strcat(outstr, flagstr);
+ strcat(outstr, "}");
+ }
}
- tprintf("}");
+ if (failed || !cumlen)
+ return 0;
+ ++cumlen;
+ if (cumlen < sizeof(outstr))
+ strcat(outstr, "]");
+ tcp->auxstr = outstr;
+ return RVAL_STR;
}
- tprintf("]");
- if (failed)
- tprintf(" %#lx", start);
- tprintf(", %d, ", nfds);
- return 0;
}
int
sys_poll(struct tcb *tcp)
{
int rc = decode_poll(tcp);
- if (exiting(tcp)) {
+ if (entering(tcp)) {
#ifdef INFTIM
if (tcp->u_arg[2] == INFTIM)
tprintf("INFTIM");
@@ -375,7 +469,7 @@
sys_ppoll(struct tcb *tcp)
{
int rc = decode_poll(tcp);
- if (exiting(tcp)) {
+ if (entering(tcp)) {
struct timespec ts;
if (umove(tcp, tcp->u_arg[2], &ts) == 0)
tprintf("{%lu, %lu}, ", ts.tv_sec, ts.tv_nsec);
More information about the Strace-devel
mailing list