Improvements for testing and compilation breakage for the GDB server
on various platforms:

* In all gdbserver_tests using gdb:
  Made a more general way to remove the initial start message.

* tests using threads burning cpu modified to have only 1 thread.
  This makes them independent of the scheduler fairness.

* filter_gdb and filter_vgdb enhanced to anonymise
    some debian 6.0/ppc specific things
    some s390x/gdb 7.0, gdb 7.1  specific things

* vgdb.c: added an #include <linux/ptrace.h> to fix compilation
  on s390x fedora and suse. (Christian Boerntrager)

* fixed a bug in valgrind-low.c debug log :
  when a register size is 0, its image cannot be output (and register
  should not be transferred).

* added a parameter --keep-unfiltered to vg_regtest.in
  This will make it easier to update filter_gdb:
  in case gdbserver_tests are failing due to "artificial"
  differences to be filtered, re-run the tests using:
     perl tests/vg_regtest --keep-unfiltered gdbserver_tests
  Then a tar file with all the *.out in gdbserver_tests
  will allow me to better/faster update the filter_gdb.

* made a better detection of a working PTRACE_GETREGS at compile time
  and/or at run-time.

This is the patch on bug 214909 comment 69.
(Philippe Waroquiers, philippe.waroquiers@skynet.be)



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11740 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_gdbserver/valgrind-low.c b/coregrind/m_gdbserver/valgrind-low.c
index fc376fa..5d3f708 100644
--- a/coregrind/m_gdbserver/valgrind-low.c
+++ b/coregrind/m_gdbserver/valgrind-low.c
@@ -176,7 +176,7 @@
       return;
    }
    size = register_size (regno);
-   {
+   if (size > 0) {
       Bool mod;
       char buf [size];
       VG_(memset) (buf, 0, size); // registers not fetched will be seen as 0.
@@ -225,7 +225,7 @@
       }
       
       size = register_size (regno);
-      {
+      if (size > 0) {
          Bool mod;
          Addr old_SP, new_SP;
          char buf[size];
diff --git a/coregrind/vgdb.c b/coregrind/vgdb.c
index fffc7cc..d5cacd3 100644
--- a/coregrind/vgdb.c
+++ b/coregrind/vgdb.c
@@ -51,6 +51,7 @@
 
 #  if defined(VGO_linux)
 #include <sys/prctl.h>
+#include <linux/ptrace.h>
 #  endif
 
 /* vgdb has two usages:
@@ -624,67 +625,137 @@
 static int pid_of_save_regs = 0;
 static struct user user_save;
 
+// The below indicates if ptrace_getregs (and ptrace_setregs) can be used.
+// Note that some linux versions are defining PTRACE_GETREGS but using
+// it gives back EIO.
+// has_working_ptrace_getregs can take the following values:
+//  -1 : PTRACE_GETREGS is defined
+//       runtime check not yet done.
+//   0 : PTRACE_GETREGS runtime check has failed.
+//   1 : PTRACE_GETREGS defined and runtime check ok.
+#ifdef PTRACE_GETREGS
+static int has_working_ptrace_getregs = -1;
+#endif
+
 /* Get the registers from pid into regs.
+   regs_bsz value gives the length of *regs. 
    Returns True if all ok, otherwise False. */
 static
-Bool getregs (int pid, void *regs)
+Bool getregs (int pid, void *regs, long regs_bsz)
 {
-#  ifdef VGA_s390x
-   char *pregs = (char *) regs;
-   long offset;
-   errno = 0;
-   DEBUG(1, "getregs PTRACE_PEEKUSER(s)\n");
-   for (offset = 0; offset < PT_ENDREGS; offset = offset + sizeof(long)) {
-      *(long *)(pregs+offset) = ptrace(PTRACE_PEEKUSER, pid, offset, NULL);
-      if (errno != 0) {
-         ERROR(errno, "PTRACE_PEEKUSER offset %ld\n", offset);
+   DEBUG(1, "getregs regs_bsz %ld\n", regs_bsz);
+#  ifdef PTRACE_GETREGS
+   if (has_working_ptrace_getregs) {
+      // Platforms having GETREGS
+      long res;
+      DEBUG(1, "getregs PTRACE_GETREGS\n");
+      res = ptrace (PTRACE_GETREGS, pid, NULL, regs);
+      if (res == 0) {
+         if (has_working_ptrace_getregs == -1) {
+            // First call to PTRACE_GETREGS succesful =>
+            has_working_ptrace_getregs = 1;
+            DEBUG(1, "detected a working PTRACE_GETREGS\n");
+         }
+         assert (has_working_ptrace_getregs == 1);
+         return True;
+      }
+      else if (has_working_ptrace_getregs == 1) {
+         // We had a working call, but now it fails.
+         // This is unexpected.
+         ERROR(errno, "PTRACE_GETREGS %ld\n", res);
          return False;
+      } else {
+         // Check this is the first call:
+         assert (has_working_ptrace_getregs == -1);
+         if (errno == EIO) {
+            DEBUG(1, "detected a broken PTRACE_GETREGS with EIO\n");
+            has_working_ptrace_getregs = 0;
+            // Fall over to the PTRACE_PEEKUSER case.
+         } else {
+            ERROR(errno, "broken PTRACE_GETREGS unexpected errno %ld\n", res);
+            return False;
+         }
       }
    }
-   return True;
-#  else
-   // Platforms having GETREGS
-   long res;
-   DEBUG(1, "getregs PTRACE_GETREGS\n");
-   res = ptrace (PTRACE_GETREGS, pid, NULL, regs);
-   if (res != 0) {
-      ERROR(errno, "PTRACE_GETREGS %ld\n", res);
-      return False;
-   }
-   return True;
 #  endif
+
+   // We assume  PTRACE_PEEKUSER is defined everywhere.
+   {
+#     ifdef PT_ENDREGS
+      long peek_bsz = PT_ENDREGS;
+      assert (peek_bsz <= regs_bsz);
+#     else
+      long peek_bsz = regs_bsz-1;
+#     endif
+      char *pregs = (char *) regs;
+      long offset;
+      errno = 0;
+      DEBUG(1, "getregs PTRACE_PEEKUSER(s) peek_bsz %ld\n", peek_bsz);
+      for (offset = 0; offset < peek_bsz; offset = offset + sizeof(long)) {
+         *(long *)(pregs+offset) = ptrace(PTRACE_PEEKUSER, pid, offset, NULL);
+         if (errno != 0) {
+            ERROR(errno, "PTRACE_PEEKUSER offset %ld\n", offset);
+            return False;
+         }
+      }
+      return True;
+   }
+
+   // If neither PTRACE_GETREGS not PTRACE_PEEKUSER have returned,
+   // then we are in serious trouble.
+   assert (0);
 }
 
 /* Set the registers of pid to regs.
+   regs_bsz value gives the length of *regs. 
    Returns True if all ok, otherwise False. */
 static
-Bool setregs (int pid, void *regs)
+Bool setregs (int pid, void *regs, long regs_bsz)
 {
-#  ifdef VGA_s390x
-   char *pregs = (char *) regs;
-   long offset;
-   long res;
-   errno = 0;
-   DEBUG(1, "setregs PTRACE_POKEUSER(s)\n");
-   for (offset = 0; offset < PT_ENDREGS; offset = offset + sizeof(long)) {
-      res = ptrace(PTRACE_POKEUSER, pid, offset, *(long*)(pregs+offset));
-      if (errno != 0) {
-         ERROR(errno, "PTRACE_POKEUSER offset %ld res %ld\n", offset, res);
+   DEBUG(1, "setregs regs_bsz %ld\n", regs_bsz);
+// Note : the below is checking for GETREGS, not SETREGS
+// as if one is defined and working, the other one should also work.
+#  ifdef PTRACE_GETREGS
+   if (has_working_ptrace_getregs) {
+      // Platforms having SETREGS
+      long res;
+      // setregs can never be called before getregs has done a runtime check.
+      assert (has_working_ptrace_getregs == 1);
+      DEBUG(1, "setregs PTRACE_SETREGS\n");
+      res = ptrace (PTRACE_SETREGS, pid, NULL, regs);
+      if (res != 0) {
+         ERROR(errno, "PTRACE_SETREGS %ld\n", res);
          return False;
       }
+      return True;
    }
-   return True;
-#  else
-   // Platforms having SETREGS
-   long res;
-   DEBUG(1, "setregs PTRACE_SETREGS\n");
-   res = ptrace (PTRACE_SETREGS, pid, NULL, regs);
-   if (res != 0) {
-      ERROR(errno, "PTRACE_SETREGS %ld\n", res);
-      return False;
-   }
-   return True;
 #  endif
+
+   {
+      char *pregs = (char *) regs;
+      long offset;
+      long res;
+#     ifdef PT_ENDREGS
+      long peek_bsz = PT_ENDREGS;
+      assert (peek_bsz <= regs_bsz);
+#     else
+      long peek_bsz = regs_bsz-1;
+#     endif
+      errno = 0;
+      DEBUG(1, "setregs PTRACE_POKEUSER(s) %ld\n", peek_bsz);
+      for (offset = 0; offset < peek_bsz; offset = offset + sizeof(long)) {
+         res = ptrace(PTRACE_POKEUSER, pid, offset, *(long*)(pregs+offset));
+         if (errno != 0) {
+            ERROR(errno, "PTRACE_POKEUSER offset %ld res %ld\n", offset, res);
+            return False;
+         }
+      }
+      return True;
+   }
+
+   // If neither PTRACE_SETREGS not PTRACE_POKEUSER have returned,
+   // then we are in serious trouble.
+   assert (0);
 }
 
 /* Restore the registers to the saved value, then detaches from all threads */
@@ -701,7 +772,7 @@
       }
 
       DEBUG(1, "setregs restore registers pid %d\n", pid_of_save_regs);
-      if (!setregs(pid_of_save_regs, &user_save.regs)) {
+      if (!setregs(pid_of_save_regs, &user_save.regs, sizeof(user_save.regs))) {
          ERROR(errno, "setregs restore registers pid %d after cont\n",
                pid_of_save_regs);
       }
@@ -757,7 +828,7 @@
       return False;
    }
 
-   if (!getregs(pid, &user_mod.regs)) {
+   if (!getregs(pid, &user_mod.regs, sizeof(user_mod.regs))) {
       detach_from_all_threads(pid);
       return False;
    }
@@ -944,7 +1015,7 @@
       assert(0);
    }
    
-   if (!setregs(pid, &user_mod.regs)) {
+   if (!setregs(pid, &user_mod.regs, sizeof(user_mod.regs))) {
       detach_from_all_threads(pid);
       return False;
    }
diff --git a/gdbserver_tests/filter_gdb b/gdbserver_tests/filter_gdb
index 9dd7a3b..9069470 100755
--- a/gdbserver_tests/filter_gdb
+++ b/gdbserver_tests/filter_gdb
@@ -14,6 +14,10 @@
 
 
 # Anonymise or remove :
+#       delete the initial lines between the launch of vgdb and the
+#         output of the echo command telling it is launched.
+#         This removes a whole lot of uninteresting lines varying
+#         with OS/glibc/gdb dep
 #       initial tty control character sent by gdb 7.0
 #       remove missing debuginfos
 #       vgdb message
@@ -23,7 +27,7 @@
 #       info threads output (e.g. which thread is running and syscall)
 #       delete Reading symbols file lines
 #       delete Loaded symbols file lines
-#       initial break message
+#       delete language switch messages.
 #       remove gdb prompts.
 #       remove gdb continuation prompts.
 #       remove gdb done prompts.
@@ -46,7 +50,8 @@
 #         a.o. produced by gdb 7.2 on arm (same with standard gdbserver)
 #       delete empty lines (the last line (only made of prompts) sometimes
 #           finishes with a new line, sometimes not ???).
-sed -e 's/^\[?1034hReading symbols/Reading symbols/'                                                \
+sed -e '/Remote debugging using/,/vgdb launched process attached/d' \
+    -e 's/^\[?1034hReading symbols/Reading symbols/'                                                \
     -e '/Missing separate debuginfos, use: debuginfo-install/d'                                       \
     -e 's/\(relaying data between gdb and process \)[0-9][0-9]*/\1..../'                              \
     -e 's/pid [0-9][0-9]*/pid ..../g'                                                                 \
@@ -56,12 +61,8 @@
     -e 's/#[0-9]\(  0x........ in sleeper_or_burner\)/#.\1/'                                          \
     -e '/^Reading symbols from .*\.\.\.done\./d'                                                      \
     -e '/^Loaded symbols for .*$/d'                                                                   \
-    -e '1,8s/_start () from [^ ][^ ]*/_start () from ...start file.../'                               \
-    -e '1,8s/\(0x........ in\) ?? () from \/lib\/ld-linux\.so\../\1 _start () from ...start file.../' \
-    -e '1,8s/\(0x........ in\) ?? () from \/lib\/ld\.so\../\1 _start () from ...start file.../'       \
-    -e '1,8s/\(0x........ in\) ?? () from \/lib64\/ld64\.so\../\1 _start () from ...start file.../'   \
-    -e '1,8s/\(0x........ in\) ?? () from \/lib64\/ld-linux-x86-64\.so\../\1 _start () from ...start file.../'   \
-    -e '1,8s/\(0x........ in\) ?? ()$/\1 _start () from ...start file.../'                            \
+    -e '/^Current language.*/d'                                                                       \
+    -e '/^The current source language is.*/d'                                                         \
     -e 's/(gdb) //g'                                                                                  \
     -e 's/^>[> ]*//'                                                                                  \
     -e '/^done\.$/d'                                                                                  \
@@ -70,9 +71,13 @@
     -e '/^   from \/lib\/ld-linux.so.*$/d'                                                            \
     -e 's/\(0x........\) in ?? () from \/lib\/ld-linux\.so\../\1 in syscall .../'                     \
     -e 's/\(0x........\) in ?? () from \/lib64\/tls\/libc\.so\../\1 in syscall .../'                  \
+    -e 's/\(0x........\) in ?? ()$/\1 in syscall .../'                                                \
     -e 's/in \(.__\)\{0,1\}select () from \/.*$/in syscall .../'                                      \
     -e '/^   from \/lib\/libc.so.*$/d'                                                                \
+    -e '/^   from \/lib64\/libc.so.*$/d'                                                              \
+    -e '/^   from \/lib64\/tls\/libc.so.*$/d'                                                         \
     -e 's/in select ()$/in syscall .../'                                                              \
+    -e 's/in \.__select ()$/in syscall .../'                                                          \
     -e 's/in select () at \.\.\/sysdeps\/unix\/syscall-template\.S.*$/in syscall .../'                \
     -e '/^[ 	]*at \.\.\/sysdeps\/unix\/syscall-template\.S/d'                                      \
     -e '/^[ 	]*in \.\.\/sysdeps\/unix\/syscall-template\.S/d'                                      \
diff --git a/gdbserver_tests/filter_vgdb b/gdbserver_tests/filter_vgdb
index 71b3511..2edc75a 100755
--- a/gdbserver_tests/filter_vgdb
+++ b/gdbserver_tests/filter_vgdb
@@ -7,9 +7,11 @@
 # Anonymise addresses
 $dir/../tests/filter_addresses                  |
 
-# filter vgdb process id, pid
-# gdb 7.2 sometimes tries to access address 0x0
-#   (same as with standard gdbserver)
+# filter vgdb process id,
+#             pid
+# gdb 7.2 sometimes tries to access address 0x0 (same as with standard gdbserver)
+# filter a debian 6.0/ppc32 line
 sed -e 's/\(relaying data between gdb and process \)[0-9][0-9]*/\1..../' \
     -e 's/\(sending command .* to pid \)[0-9][0-9]*/\1..../'             \
-    -e '/Cannot access memory at address 0x......../d'
+    -e '/Cannot access memory at address 0x......../d'                   \
+    -e '/^[1-9][0-9]*	\.\.\/sysdeps\/powerpc\/powerpc32\/dl-start\.S: No such file or directory\./d'
diff --git a/gdbserver_tests/mcbreak.stdinB.gdb b/gdbserver_tests/mcbreak.stdinB.gdb
index a154925..19f3d86 100644
--- a/gdbserver_tests/mcbreak.stdinB.gdb
+++ b/gdbserver_tests/mcbreak.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcbreak
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 define checkstep
diff --git a/gdbserver_tests/mcbreak.stdoutB.exp b/gdbserver_tests/mcbreak.stdoutB.exp
index 2c51b39..e12d2e4 100644
--- a/gdbserver_tests/mcbreak.stdoutB.exp
+++ b/gdbserver_tests/mcbreak.stdoutB.exp
@@ -1,5 +1,3 @@
-Remote debugging using | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcbreak
-0x........ in _start () from ...start file...
 Breakpoint 1 at 0x........: file t.c, line 112.
 Breakpoint 2 at 0x........: file t.c, line 117.
 Continuing.
diff --git a/gdbserver_tests/mcbreak.vgtest b/gdbserver_tests/mcbreak.vgtest
index b79f41a..41ea5e3 100644
--- a/gdbserver_tests/mcbreak.vgtest
+++ b/gdbserver_tests/mcbreak.vgtest
@@ -3,9 +3,11 @@
 prog: t
 vgopts: --tool=memcheck --vgdb=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcbreak
 stdout_filter: filter_gdb
+#stdout_filter: /bin/cat
 stderr_filter: filter_make_empty
 progB: gdb
 argsB:  --quiet -l 60 --nx ./t
 stdinB: mcbreak.stdinB.gdb
 stdoutB_filter: filter_gdb
+#stdoutB_filter: /bin/cat
 stderrB_filter: filter_memcheck_monitor
diff --git a/gdbserver_tests/mcclean_after_fork.stdinB.gdb b/gdbserver_tests/mcclean_after_fork.stdinB.gdb
index 145ad93..f91ca9e 100644
--- a/gdbserver_tests/mcclean_after_fork.stdinB.gdb
+++ b/gdbserver_tests/mcclean_after_fork.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcclean_after_fork
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 # put a break in main, and then a watch
diff --git a/gdbserver_tests/mcclean_after_fork.stdoutB.exp b/gdbserver_tests/mcclean_after_fork.stdoutB.exp
index 8c6a8d3..6db3d3a 100644
--- a/gdbserver_tests/mcclean_after_fork.stdoutB.exp
+++ b/gdbserver_tests/mcclean_after_fork.stdoutB.exp
@@ -1,5 +1,3 @@
-Remote debugging using | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcclean_after_fork
-0x........ in _start () from ...start file...
 Breakpoint 1 at 0x........: file clean_after_fork.c, line 9.
 Breakpoint 2 at 0x........: file clean_after_fork.c, line 18.
 Breakpoint 3 at 0x........: file clean_after_fork.c, line 20.
diff --git a/gdbserver_tests/mcinfcallRU.stderr.exp b/gdbserver_tests/mcinfcallRU.stderr.exp
index c1dd15b..502dd8a 100644
--- a/gdbserver_tests/mcinfcallRU.stderr.exp
+++ b/gdbserver_tests/mcinfcallRU.stderr.exp
@@ -1,7 +1,4 @@
-loops/sleep_ms/burn/threads_spec:  1 0 2000000000 B-B-B-B-
-Brussels ready to sleep and/or burn
-London ready to sleep and/or burn
-Petaouchnok ready to sleep and/or burn
+loops/sleep_ms/burn/threads_spec:  1 0 2000000000 ------B-
 main ready to sleep and/or burn
 pid .... Thread .... inferior call pushed from gdb in mcinfcallRU.stdinB.gdb
 Reset valgrind output to log (orderly_finish)
diff --git a/gdbserver_tests/mcinfcallRU.stdinB.gdb b/gdbserver_tests/mcinfcallRU.stdinB.gdb
index 08a149b..7ca7290 100644
--- a/gdbserver_tests/mcinfcallRU.stdinB.gdb
+++ b/gdbserver_tests/mcinfcallRU.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcinfcallRU
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 # We will interrupt in a few seconds (be sure all tasks are in
diff --git a/gdbserver_tests/mcinfcallRU.vgtest b/gdbserver_tests/mcinfcallRU.vgtest
index 957458b..d8f54d3 100644
--- a/gdbserver_tests/mcinfcallRU.vgtest
+++ b/gdbserver_tests/mcinfcallRU.vgtest
@@ -1,6 +1,8 @@
 # test inferior calls when all threads are in Runnable or Yielding mode
 prog: sleepers
-args: 1 0 2000000000 B-B-B-B-
+# We would like to use B-B-B-B- instead of ------B- but this gives
+# too much dependencies to the scheduler fairness.
+args: 1 0 2000000000 ------B-
 vgopts: --tool=memcheck --vgdb=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcinfcallRU
 # filter_gdb to replace pid and Thread numbers.
 # Well, the test will verify we have 4 calls (for each thread)
diff --git a/gdbserver_tests/mcinfcallWSRU.stderr.exp b/gdbserver_tests/mcinfcallWSRU.stderr.exp
index 227f862..a6ac617 100644
--- a/gdbserver_tests/mcinfcallWSRU.stderr.exp
+++ b/gdbserver_tests/mcinfcallWSRU.stderr.exp
@@ -1,8 +1,7 @@
-loops/sleep_ms/burn/threads_spec:  100 100000000 1000000000 -S-SB-B-
+loops/sleep_ms/burn/threads_spec:  100 100000000 1000000000 -S-S-SB-
 Brussels ready to sleep and/or burn
 London ready to sleep and/or burn
 Petaouchnok ready to sleep and/or burn
 main ready to sleep and/or burn
 pid .... Thread .... thread 1 inferior call pushed from gdb in mcinfcallWSRU.stdinB.gdb
-pid .... Thread .... thread 4 inferior call pushed from gdb in mcinfcallWSRU.stdinB.gdb
 Reset valgrind output to log (orderly_finish)
diff --git a/gdbserver_tests/mcinfcallWSRU.stderrB.exp b/gdbserver_tests/mcinfcallWSRU.stderrB.exp
index 2e954db..860e07e 100644
--- a/gdbserver_tests/mcinfcallWSRU.stderrB.exp
+++ b/gdbserver_tests/mcinfcallWSRU.stderrB.exp
@@ -1,6 +1,4 @@
 relaying data between gdb and process ....
-Remote debugging using | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcinfcallWSRU
-0x........ in _start () from ...start file...
 vgdb-error value changed from 0 to 999999
 Breakpoint 1 at 0x........: file sleepers.c, line 72.
 Continuing.
@@ -41,8 +39,13 @@
 can only be accepted if the thread is VgTs_Runnable or VgTs_Yielding state
 Thread status is VgTs_WaitSys
 '
-[Switching to thread 4 (Thread ....)]#0  0x........ in do_burn () at sleepers.c:39
-39	   for (i = 0; i < burn; i++) loopnr++;
-$2 = void
+[Switching to thread 4 (Thread ....)]#0  0x........ in syscall ...
+Could not write register  "xxx"; remote failure reply 'E.
+ERROR changing register  xxx regno y
+gdb commands changing registers (pc, sp, ...) (e.g. 'jump',
+set pc, calling from gdb a function in the debugged process, ...)
+can only be accepted if the thread is VgTs_Runnable or VgTs_Yielding state
+Thread status is VgTs_WaitSys
+'
 monitor command request to kill this process
 Remote connection closed
diff --git a/gdbserver_tests/mcinfcallWSRU.stdinB.gdb b/gdbserver_tests/mcinfcallWSRU.stdinB.gdb
index 8429dde..4ccbcdc 100644
--- a/gdbserver_tests/mcinfcallWSRU.stdinB.gdb
+++ b/gdbserver_tests/mcinfcallWSRU.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcinfcallWSRU
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 # ensure all threads are known
diff --git a/gdbserver_tests/mcinfcallWSRU.vgtest b/gdbserver_tests/mcinfcallWSRU.vgtest
index 859ba17..683be02 100644
--- a/gdbserver_tests/mcinfcallWSRU.vgtest
+++ b/gdbserver_tests/mcinfcallWSRU.vgtest
@@ -1,7 +1,9 @@
 # test inferior calls when some threads are in Runnable or Yielding mode,
 # some threads are in WaitSys.
 prog: sleepers
-args: 100 100000000 1000000000 -S-SB-B-
+# We would like to have two threads running (i.e. -S-SB-B-)
+# but this introduces too much dependencies to scheduler fairness.
+args: 100 100000000 1000000000 -S-S-SB-
 vgopts: --tool=memcheck --vgdb=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcinfcallWSRU
 # Disable on Darwin: inferior call rejected as it cannot find malloc.
 prereq: ../tests/os_test linux
diff --git a/gdbserver_tests/mcleak.stdinB.gdb b/gdbserver_tests/mcleak.stdinB.gdb
index 5cdcbe9..15c533b 100644
--- a/gdbserver_tests/mcleak.stdinB.gdb
+++ b/gdbserver_tests/mcleak.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcleak
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 #
diff --git a/gdbserver_tests/mcsignopass.stdinB.gdb b/gdbserver_tests/mcsignopass.stdinB.gdb
index 44a5c08..ef904d8 100644
--- a/gdbserver_tests/mcsignopass.stdinB.gdb
+++ b/gdbserver_tests/mcsignopass.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcsignopass
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 # instruct gdb to not pass (i.e. ignore) these signals.
diff --git a/gdbserver_tests/mcsignopass.stdoutB.exp b/gdbserver_tests/mcsignopass.stdoutB.exp
index 70ff5ba..06c00ca 100644
--- a/gdbserver_tests/mcsignopass.stdoutB.exp
+++ b/gdbserver_tests/mcsignopass.stdoutB.exp
@@ -1,5 +1,3 @@
-Remote debugging using | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcsignopass
-0x........ in _start () from ...start file...
 Signal        Stop	Print	Pass to program	Description
 SIGSEGV       Yes	Yes	No		Segmentation fault
 Signal        Stop	Print	Pass to program	Description
diff --git a/gdbserver_tests/mcsigpass.stdinB.gdb b/gdbserver_tests/mcsigpass.stdinB.gdb
index ebd0cc7..0e1799a 100644
--- a/gdbserver_tests/mcsigpass.stdinB.gdb
+++ b/gdbserver_tests/mcsigpass.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcsigpass
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 # After this continue, we will receive 5 signals.
diff --git a/gdbserver_tests/mcsigpass.stdoutB.exp b/gdbserver_tests/mcsigpass.stdoutB.exp
index e924592..c7723dc 100644
--- a/gdbserver_tests/mcsigpass.stdoutB.exp
+++ b/gdbserver_tests/mcsigpass.stdoutB.exp
@@ -1,5 +1,3 @@
-Remote debugging using | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcsigpass
-0x........ in _start () from ...start file...
 Continuing.
 Program received signal SIGSEGV, Segmentation fault.
 0x........ in test1 () at faultstatus.c:105
diff --git a/gdbserver_tests/mcvabits.stdinB.gdb b/gdbserver_tests/mcvabits.stdinB.gdb
index 7aa423a..4fc1eeb 100644
--- a/gdbserver_tests/mcvabits.stdinB.gdb
+++ b/gdbserver_tests/mcvabits.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcvabits
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 #
diff --git a/gdbserver_tests/mcvabits.stdoutB.exp b/gdbserver_tests/mcvabits.stdoutB.exp
index 68df7e1..e8d3661 100644
--- a/gdbserver_tests/mcvabits.stdoutB.exp
+++ b/gdbserver_tests/mcvabits.stdoutB.exp
@@ -1,5 +1,3 @@
-Remote debugging using | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcvabits
-0x........ in _start () from ...start file...
 Breakpoint 1 at 0x........: file t.c, line 100.
 Continuing.
 Breakpoint 1, breakme (line=112) at t.c:100
diff --git a/gdbserver_tests/mcwatchpoints.stdinB.gdb b/gdbserver_tests/mcwatchpoints.stdinB.gdb
index 5ec79fa..243453b 100644
--- a/gdbserver_tests/mcwatchpoints.stdinB.gdb
+++ b/gdbserver_tests/mcwatchpoints.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcwatchpoints
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 #
diff --git a/gdbserver_tests/mcwatchpoints.stdoutB.exp b/gdbserver_tests/mcwatchpoints.stdoutB.exp
index 7c6e09d..0604aeb 100644
--- a/gdbserver_tests/mcwatchpoints.stdoutB.exp
+++ b/gdbserver_tests/mcwatchpoints.stdoutB.exp
@@ -1,5 +1,3 @@
-Remote debugging using | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcwatchpoints
-0x........ in _start () from ...start file...
 Breakpoint 1 at 0x........: file watchpoints.c, line 7.
 Continuing.
 Breakpoint 1, breakme (line=19) at watchpoints.c:7
diff --git a/gdbserver_tests/mssnapshot.stdinB.gdb b/gdbserver_tests/mssnapshot.stdinB.gdb
index 42b56fe..efe5a7e 100644
--- a/gdbserver_tests/mssnapshot.stdinB.gdb
+++ b/gdbserver_tests/mssnapshot.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mssnapshot
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 #
diff --git a/gdbserver_tests/mssnapshot.stdoutB.exp b/gdbserver_tests/mssnapshot.stdoutB.exp
index 0166d55..a2a7c55 100644
--- a/gdbserver_tests/mssnapshot.stdoutB.exp
+++ b/gdbserver_tests/mssnapshot.stdoutB.exp
@@ -1,5 +1,3 @@
-Remote debugging using | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mssnapshot
-0x........ in _start () from ...start file...
 Breakpoint 1 at 0x........: file t.c, line 105.
 Continuing.
 Breakpoint 1, main (argc=1, argv=0x........) at t.c:105
diff --git a/gdbserver_tests/nlcontrolc.stdinB.gdb b/gdbserver_tests/nlcontrolc.stdinB.gdb
index 53a8d68..9fc5132 100644
--- a/gdbserver_tests/nlcontrolc.stdinB.gdb
+++ b/gdbserver_tests/nlcontrolc.stdinB.gdb
@@ -1,5 +1,6 @@
 # connect gdb to Valgrind gdbserver:
 target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-nlcontrolc
+echo vgdb launched process attached\n
 monitor vg.set vgdb-error 999999
 #
 #
diff --git a/gdbserver_tests/nlcontrolc.stdoutB.exp b/gdbserver_tests/nlcontrolc.stdoutB.exp
index a79f5d2..90d6d3c 100644
--- a/gdbserver_tests/nlcontrolc.stdoutB.exp
+++ b/gdbserver_tests/nlcontrolc.stdoutB.exp
@@ -1,5 +1,3 @@
-Remote debugging using | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-nlcontrolc
-0x........ in _start () from ...start file...
 Continuing.
 Program received signal SIGTRAP, Trace/breakpoint trap.
 0x........ in syscall ...
diff --git a/gdbserver_tests/sleepers.c b/gdbserver_tests/sleepers.c
index 67c3743..13cc1e0 100644
--- a/gdbserver_tests/sleepers.c
+++ b/gdbserver_tests/sleepers.c
@@ -155,23 +155,32 @@
   b.name = "Brussels";
   b.burn = *threads_spec++ == 'B';
   b.sleep = *threads_spec++ == 'S';
-  b.t = 1;
-  pthread_create(&ebbr, NULL, sleeper_or_burner, &b);
-  wait_ready();
+  b.t = -1;
+  if (b.burn || b.sleep) {
+     b.t = 1;
+     pthread_create(&ebbr, NULL, sleeper_or_burner, &b);
+     wait_ready();
+  }
   
   l.name = "London";
   l.burn = *threads_spec++ == 'B';
   l.sleep = *threads_spec++ == 'S';
-  l.t = 2;
-  pthread_create(&egll, NULL, sleeper_or_burner, &l);
-  wait_ready();
+  l.t = -1;
+  if (l.burn || l.sleep) {
+     l.t = 2;
+     pthread_create(&egll, NULL, sleeper_or_burner, &l);
+     wait_ready();
+  }
 
   p.name = "Petaouchnok";
   p.burn = *threads_spec++ == 'B';
   p.sleep = *threads_spec++ == 'S';
-  p.t = 3;
-  pthread_create(&zzzz, NULL, sleeper_or_burner, &p);
-  wait_ready();
+  p.t = -1;
+  if (p.burn || p.sleep) {
+     p.t = 3;
+     pthread_create(&zzzz, NULL, sleeper_or_burner, &p);
+     wait_ready();
+  }
 
   m.name = "main";
   m.burn = *threads_spec++ == 'B';
@@ -179,9 +188,9 @@
   m.t = 0;
   sleeper_or_burner(&m);
 
-  pthread_join(ebbr, NULL);
-  pthread_join(egll, NULL);
-  pthread_join(zzzz, NULL);
+  if (b.t != -1) pthread_join(ebbr, NULL);
+  if (l.t != -1) pthread_join(egll, NULL);
+  if (p.t != -1) pthread_join(zzzz, NULL);
 
   return 0;
 }
diff --git a/tests/vg_regtest.in b/tests/vg_regtest.in
index 68e3138..6712a04 100755
--- a/tests/vg_regtest.in
+++ b/tests/vg_regtest.in
@@ -37,6 +37,8 @@
 #   --valgrind-lib: valgrind libraries to use.  Default is $tests_dir/.in_place.
 #               (This option should probably only be used in conjunction with
 #               --valgrind.)
+#   --keep-unfiltered: keep a copy of the unfiltered output/error output
+#     of each test by adding an extension .unfiltered.out
 #
 # The easiest way is to run all tests in valgrind/ with (assuming you installed
 # in $PREFIX):
@@ -113,10 +115,10 @@
 # Global vars
 #----------------------------------------------------------------------------
 my $usage="\n"
-          . "Usage:\n"
-          . "   vg_regtest [--all, --valgrind, --valgrind-lib]\n"
-          . "   Use EXTRA_REGTEST_OPTS to supply extra args for all tests\n"
-          . "\n";
+     . "Usage:\n"
+     . "   vg_regtest [--all, --valgrind, --valgrind-lib, --keep-unfiltered]\n"
+     . "   Use EXTRA_REGTEST_OPTS to supply extra args for all tests\n"
+     . "\n";
 
 my $tmp="vg_regtest.tmp.$$";
 
@@ -148,6 +150,7 @@
 chomp(my $tests_dir = `pwd`);
 
 my $valgrind_lib = "$tests_dir/.in_place";
+my $keepunfiltered = 0;
 
 # default filter is the one named "filter_stderr" in the test's directory
 my $default_stderr_filter = "filter_stderr";
@@ -196,6 +199,8 @@
                 $valgrind = $1;
             } elsif ($arg =~ /^--valgrind-lib=(.*)$/) {
                 $valgrind_lib = $1;
+            } elsif ($arg =~ /^--keep-unfiltered$/) {
+                $keepunfiltered = 1;
             } else {
                 die $usage;
             }
@@ -292,6 +297,17 @@
     return $exit_code;
 }
 
+# if $keepunfiltered, copies $1 to $1.unfiltered.out
+# renames $0 tp $1
+sub filtered_rename($$) 
+{
+    if ($keepunfiltered == 1) {
+        mysystem("cp  $_[1] $_[1].unfiltered.out");
+    }
+    rename ($_[0], $_[1]);
+}
+
+
 # from a directory name like "/foo/cachesim/tests/" determine the tool name
 sub determine_tool()
 {
@@ -402,7 +418,7 @@
     # Filter stdout
     if (defined $stdout_filter) {
         mysystem("$stdout_filter < $name.stdout.out > $tmp");
-        rename($tmp, "$name.stdout.out");
+        filtered_rename($tmp, "$name.stdout.out");
     }
     # Find all the .stdout.exp files.  If none, use /dev/null.
     my @stdout_exps = <$name.stdout.exp*>;
@@ -411,7 +427,7 @@
 
     # Filter stderr
     mysystem("$stderr_filter < $name.stderr.out > $tmp");
-    rename($tmp, "$name.stderr.out");
+    filtered_rename($tmp, "$name.stderr.out");
     # Find all the .stderr.exp files.  At least one must exist.
     my @stderr_exps = <$name.stderr.exp*>;
     (0 != scalar @stderr_exps) or die "Could not find `$name.stderr.exp*'\n";
@@ -433,7 +449,7 @@
         # Filter stdout
         if (defined $stdoutB_filter) {
             mysystem("$stdoutB_filter < $name.stdoutB.out > $tmp");
-            rename($tmp, "$name.stdoutB.out");
+            filtered_rename($tmp, "$name.stdoutB.out");
         }
         # Find all the .stdoutB.exp files.  If none, use /dev/null.
         my @stdoutB_exps = <$name.stdoutB.exp*>;
@@ -442,7 +458,7 @@
         
         # Filter stderr
         mysystem("$stderrB_filter < $name.stderrB.out > $tmp");
-        rename($tmp, "$name.stderrB.out");
+        filtered_rename($tmp, "$name.stderrB.out");
         # Find all the .stderrB.exp files.  At least one must exist.
         my @stderrB_exps = <$name.stderrB.exp*>;
         (0 != scalar @stderrB_exps) or die "Could not find `$name.stderrB.exp*'\n";