[PATCH] decode fcntl's F_{GET, SET}LEASE, F_NOTIFY, and F_DUPFD_CLOEXEC

Denys Vlasenko dvlasenk at redhat.com
Tue Mar 10 20:47:53 UTC 2009


On Tue, 2009-03-10 at 05:48 -0400, Mike Frysinger wrote:
> I was tracing an app that was trying to do dnotify calls, but this was
> hard to deduce at first because all I got was:
> fcntl(11, 0x402 /* F_??? */, 0x8000000e) = -1 EINVAL (Invalid argument)
> Which made me think that the code was doing something broken (since the
> fields we not being decoded).  Once I found out 0x402 is actually a valid
> fcntl command for Linux, I took a stab at fixing strace.
> 
> F_DUPFD_CLOEXEC is just like F_DUPFD.  The LEASE funcs are easy becuase
> we can reuse lockfcmds.  F_NOTIFY required a little more work as it has
> its own array of unique flags.
> 
> Now I get a nicely decoded trace:
> fcntl(11, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_DELETE|DN_MULTISHOT) = -1 EINVAL (Invalid argument)
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Applied to cvs as "obviously better than before" category :)
Thanks Mike.

Noticed that we have two places for generation of O_xxx|O_yyy
strings, and merged them into one. Run tested.

Changelog and patch are below.
--
vda


Optimize printing of open modes.
* defs.h: Declare sprint_open_modes(),
remove unused parameter in tprint_open_modes().
* desc.c (sprint_open_modes): Move fuction definition from here...
* file.c (sprint_open_modes): To here.
(tprint_open_modes): Use sprint_open_modes(), it already
generates needed string.
* ipc.c: Remove unused parameter from calls
to tprint_open_modes().


diff -d -urpN strace.7/defs.h strace.8/defs.h
--- strace.7/defs.h	2009-03-10 21:44:24.000000000 +0100
+++ strace.8/defs.h	2009-03-10 21:01:48.000000000 +0100
@@ -534,7 +534,8 @@ extern void printtrailer P((void));
 extern void tabto P((int));
 extern void call_summary P((FILE *));
 extern void tprint_iov P((struct tcb *, unsigned long, unsigned long));
-extern void tprint_open_modes P((struct tcb *, mode_t));
+extern void tprint_open_modes P((mode_t));
+extern const char *sprint_open_modes P((mode_t));
 extern int is_restart_error P((struct tcb *));
 
 extern int change_syscall P((struct tcb *, int));
diff -d -urpN strace.7/desc.c strace.8/desc.c
--- strace.7/desc.c	2009-03-10 21:44:37.000000000 +0100
+++ strace.8/desc.c	2009-03-10 21:00:30.000000000 +0100
@@ -300,40 +300,6 @@ printflock64(struct tcb *tcp, long addr,
 }
 #endif
 
-/*
- * low bits of the open(2) flags define access mode,
- * other bits are real flags.
- */
-static const char *
-sprint_open_modes(mode_t flags)
-{
-	static char outstr[1024];
-	const char *str = xlookup(open_access_modes, flags & 3);
-	const char *sep = "";
-	const struct xlat *x;
-
-	strcpy(outstr, "flags ");
-	if (str) {
-		strcat(outstr, str);
-		flags &= ~3;
-		if (!flags)
-			return outstr;
-		strcat(outstr, "|");
-	}
-
-	for (x = open_mode_flags; x->str; x++) {
-		if ((flags & x->val) == x->val) {
-			sprintf(outstr + strlen(outstr),
-				"%s%s", sep, x->str);
-			sep = "|";
-			flags &= ~x->val;
-		}
-	}
-	if (flags)
-		sprintf(outstr + strlen(outstr), "%s%#x", sep, flags);
-	return outstr;
-}
-
 int
 sys_fcntl(struct tcb *tcp)
 {
@@ -353,7 +319,7 @@ sys_fcntl(struct tcb *tcp)
 			break;
 		case F_SETFL:
 			tprintf(", ");
-			tprint_open_modes(tcp, tcp->u_arg[2]);
+			tprint_open_modes(tcp->u_arg[2]);
 			break;
 		case F_SETLK: case F_SETLKW:
 #ifdef F_FREESP
diff -d -urpN strace.7/file.c strace.8/file.c
--- strace.7/file.c	2009-03-10 21:44:24.000000000 +0100
+++ strace.8/file.c	2009-03-10 21:19:34.000000000 +0100
@@ -239,7 +239,7 @@ const struct xlat open_mode_flags[] = {
 #ifdef O_RSYNC
 	{ O_RSYNC,	"O_RSYNC"	},
 #endif
-#ifdef O_NDELAY
+#if defined(O_NDELAY) && (O_NDELAY != O_NONBLOCK)
 	{ O_NDELAY,	"O_NDELAY"	},
 #endif
 #ifdef O_PRIV
@@ -339,23 +339,61 @@ print_dirfd(long fd)
 #endif
 
 /*
+ * Pity stpcpy() is not standardized...
+ */
+static char *
+str_append(char *dst, const char *src)
+{
+	while ((*dst = *src++) != '\0')
+		dst++;
+	return dst;
+}
+
+/*
  * low bits of the open(2) flags define access mode,
  * other bits are real flags.
  */
-void
-tprint_open_modes(struct tcb *tcp, mode_t flags)
+const char *
+sprint_open_modes(mode_t flags)
 {
-	const char *str = xlookup(open_access_modes, flags & 3);
+	static char outstr[1024];
+	char *p;
+	char sep = 0;
+	const char *str;
+	const struct xlat *x;
 
-	if (str)
-	{
-		tprintf("%s", str);
+	p = str_append(outstr, "flags ");
+	str = xlookup(open_access_modes, flags & 3);
+	if (str) {
+		p = str_append(p, str);
 		flags &= ~3;
 		if (!flags)
-			return;
-		tprintf("|");
+			return outstr;
+		sep = '|';
 	}
-	printflags(open_mode_flags, flags, "O_???");
+
+	for (x = open_mode_flags; x->str; x++) {
+		if ((flags & x->val) == x->val) {
+			if (sep)
+				*p++ = sep;
+			p = str_append(p, x->str);
+			flags &= ~x->val;
+			if (!flags)
+				return outstr;
+			sep = '|';
+		}
+	}
+	/* flags is still nonzero */
+	if (sep)
+		*p++ = sep;
+	sprintf(p, "%#x", flags);
+	return outstr;
+}
+
+void
+tprint_open_modes(mode_t flags)
+{
+	tprintf(sprint_open_modes(flags) + sizeof("flags"));
 }
 
 static int
@@ -365,7 +403,7 @@ decode_open(struct tcb *tcp, int offset)
 		printpath(tcp, tcp->u_arg[offset]);
 		tprintf(", ");
 		/* flags */
-		tprint_open_modes(tcp, tcp->u_arg[offset + 1]);
+		tprint_open_modes(tcp->u_arg[offset + 1]);
 		if (tcp->u_arg[offset + 1] & O_CREAT) {
 			/* mode */
 			tprintf(", %#lo", tcp->u_arg[offset + 2]);
diff -d -urpN strace.7/ipc.c strace.8/ipc.c
--- strace.7/ipc.c	2009-03-10 21:44:24.000000000 +0100
+++ strace.8/ipc.c	2009-03-10 21:00:40.000000000 +0100
@@ -420,7 +420,7 @@ sys_mq_open(struct tcb *tcp)
 		printpath(tcp, tcp->u_arg[0]);
 		tprintf(", ");
 		/* flags */
-		tprint_open_modes(tcp, tcp->u_arg[1]);
+		tprint_open_modes(tcp->u_arg[1]);
 		if (tcp->u_arg[1] & O_CREAT) {
 # ifndef HAVE_MQUEUE_H
 			tprintf(", %lx", tcp->u_arg[2]);
@@ -489,7 +489,7 @@ printmqattr(struct tcb *tcp, long addr)
 			return;
 		}
 		tprintf("{mq_flags=");
-		tprint_open_modes(tcp, attr.mq_flags);
+		tprint_open_modes(attr.mq_flags);
 		tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
 			attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
 # endif






More information about the Strace-devel mailing list