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