Make moans about unknown ioctls more informative (#336772)

This is a slightly modified version of a patch from Ivo Raisr <ivosh@ivosh.net>.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14116 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index 370e9ba..39ee199 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -3427,16 +3427,27 @@
        * commands becomes very tiresome.
        */
    } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) {
-      //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request);
-      //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
-      static Int moans = 3;
+      static UWord unknown_ioctl[10];
+      static Int moans = sizeof(unknown_ioctl) / sizeof(unknown_ioctl[0]);
+
       if (moans > 0 && !VG_(clo_xml)) {
-         moans--;
-         VG_(umsg)("Warning: noted but unhandled ioctl 0x%lx"
-                   " with no size/direction hints\n", request); 
-         VG_(umsg)("   This could cause spurious value errors to appear.\n");
-         VG_(umsg)("   See README_MISSING_SYSCALL_OR_IOCTL for "
-                   "guidance on writing a proper wrapper.\n" );
+         /* Check if have not already moaned for this request. */
+         UInt i;
+         for (i = 0; i < sizeof(unknown_ioctl)/sizeof(unknown_ioctl[0]); i++) {
+            if (unknown_ioctl[i] == request)
+               break;
+            if (unknown_ioctl[i] == 0) {
+               unknown_ioctl[i] = request;
+               moans--;
+               VG_(umsg)("Warning: noted but unhandled ioctl 0x%lx"
+                         " with no size/direction hints.\n", request); 
+               VG_(umsg)("   This could cause spurious value errors to appear.\n");
+               VG_(umsg)("   See README_MISSING_SYSCALL_OR_IOCTL for "
+                         "guidance on writing a proper wrapper.\n" );
+               //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
+               return;
+            }
+         }
       }
    } else {
       //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request);
diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am
index 65689dc..d11004a 100644
--- a/none/tests/Makefile.am
+++ b/none/tests/Makefile.am
@@ -49,6 +49,7 @@
 	filter_cmdline0 \
 	filter_cmdline1 \
 	filter_fdleak \
+	filter_ioctl_moans \
 	filter_linenos \
 	filter_none_discards \
 	filter_shell_output \
@@ -100,6 +101,7 @@
 	fucomip.stderr.exp fucomip.vgtest \
 	gxx304.stderr.exp gxx304.vgtest \
 	ifunc.stderr.exp ifunc.stdout.exp ifunc.vgtest \
+	ioctl_moans.stderr.exp ioctl_moans.vgtest \
 	manythreads.stdout.exp manythreads.stderr.exp manythreads.vgtest \
 	map_unaligned.stderr.exp map_unaligned.vgtest \
 	map_unmap.stderr.exp map_unmap.stdout.exp map_unmap.vgtest \
@@ -184,6 +186,7 @@
 	fdleak_fcntl fdleak_ipv4 fdleak_open fdleak_pipe \
 	fdleak_socketpair \
 	floored fork fucomip \
+	ioctl_moans \
 	mmap_fcntl_bug \
 	munmap_exe map_unaligned map_unmap mq \
 	pending \
diff --git a/none/tests/filter_ioctl_moans b/none/tests/filter_ioctl_moans
new file mode 100644
index 0000000..b4b8e62
--- /dev/null
+++ b/none/tests/filter_ioctl_moans
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+dir=`dirname $0`
+
+$dir/../../tests/filter_stderr_basic |
+
+# Remove "Nulgrind, ..." line and the following copyright line.
+sed "/^Nulgrind, the minimal Valgrind tool/ , /./ d"
diff --git a/none/tests/ioctl_moans.c b/none/tests/ioctl_moans.c
new file mode 100644
index 0000000..d56e6f7
--- /dev/null
+++ b/none/tests/ioctl_moans.c
@@ -0,0 +1,39 @@
+/* Tests Valgrind moans about unknown ioctl.
+   10 unique moans should be produced.
+ */
+
+#include <sys/ioctl.h>
+
+/* An ioctl request for a strange ioctl device driver. */
+#define IOCTL_REQUEST_BASE 0x12345670
+
+int main(int argc, const char *argv[])
+{
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x0);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x1);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x0);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x2);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x3);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x4);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x1);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x5);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x5);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x1);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x6);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x7);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x8);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x1);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x9);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x1);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x0);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0xa);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0xb);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0xc);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0xd);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x1);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0xe);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0x0);
+   ioctl(-1, IOCTL_REQUEST_BASE + 0xf);
+
+   return 0;
+}
diff --git a/none/tests/ioctl_moans.stderr.exp b/none/tests/ioctl_moans.stderr.exp
new file mode 100644
index 0000000..10bda0b
--- /dev/null
+++ b/none/tests/ioctl_moans.stderr.exp
@@ -0,0 +1,30 @@
+Warning: noted but unhandled ioctl 0x12345670 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
+Warning: noted but unhandled ioctl 0x12345671 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
+Warning: noted but unhandled ioctl 0x12345672 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
+Warning: noted but unhandled ioctl 0x12345673 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
+Warning: noted but unhandled ioctl 0x12345674 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
+Warning: noted but unhandled ioctl 0x12345675 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
+Warning: noted but unhandled ioctl 0x12345676 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
+Warning: noted but unhandled ioctl 0x12345677 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
+Warning: noted but unhandled ioctl 0x12345678 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
+Warning: noted but unhandled ioctl 0x12345679 with no size/direction hints.
+   This could cause spurious value errors to appear.
+   See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
diff --git a/none/tests/ioctl_moans.vgtest b/none/tests/ioctl_moans.vgtest
new file mode 100644
index 0000000..180db12
--- /dev/null
+++ b/none/tests/ioctl_moans.vgtest
@@ -0,0 +1,3 @@
+prog: ioctl_moans
+vgopts: -q
+stderr_filter: filter_ioctl_moans