Teach the testsuite that GDBserver reliably reports program exits.
authorPedro Alves <palves@redhat.com>
Wed, 2 Oct 2013 11:44:20 +0000 (11:44 +0000)
committerPedro Alves <palves@redhat.com>
Wed, 2 Oct 2013 11:44:20 +0000 (11:44 +0000)
Running catch-syscall.exp against a gdbserver that actually supports
it, we get:

 FAIL: gdb.base/catch-syscall.exp: continue until exit (the program exited)
 FAIL: gdb.base/catch-syscall.exp: continue until exit (the program exited)
 FAIL: gdb.base/catch-syscall.exp: continue until exit (the program exited)
 FAIL: gdb.base/catch-syscall.exp: continue until exit at catch syscall with unused syscall (mlock) (the program exited)
 FAIL: gdb.base/catch-syscall.exp: continue until exit (the program exited)

The fail pattern is:

 Catchpoint 2 (call to syscall exit_group), 0x000000323d4baa29 in _exit () from /lib64/libc.so.6
 (gdb) PASS: gdb.base/catch-syscall.exp: program has called exit_group
 delete breakpoints
 Delete all breakpoints? (y or n) y
 (gdb) info breakpoints
 No breakpoints or watchpoints.
 (gdb) break exit
 Breakpoint 3 at 0x323d438bf0
 (gdb) continue
 Continuing.
 [Inferior 1 (process 21081) exited normally]

That "break exit" + "continue" comes from:

> # gdb_continue_to_end:
> # The case where the target uses stubs has to be handled specially. If a
> #       stub is used, we set a breakpoint at exit because we cannot rely on
> #       exit() behavior of a remote target.
> #

The native-gdbserver.exp board, used to test against gdbserver in
"target remote" mode, triggers that case ($use_gdb_stub is true).  So
gdb_continue_to_end doesn't work for catch-syscall.exp as here we
catch the exit_group and continue from that, expecting to see a real
program exit.  I was about to post a patch that changes
catch-syscall.exp to call a new function that just always does what
gdb_continue_to_end does in the !$use_gdb_stub case.  But, since
GDBserver doesn't really need this, in the end I thought it better to
teach the testsuite that there are stubs that know how to report
program exits, by adding a new "exit_is_reliable" board variable that
then gdb_continue_to_end checks.

Tested on x86_64 Fedora 17, native and gdbserver.

gdb/testsuite/
2013-10-02  Pedro Alves  <palves@redhat.com>

* README (Board Settings): Document "exit_is_reliable".
* lib/gdb.exp (gdb_continue_to_end): Check whether the board says
running to exit reliably reports program exits.
* boards/native-gdbserver.exp: Set exit_is_reliable in the board
info.
* boards/native-stdio-gdbserver.exp: Likewise.

gdb/testsuite/ChangeLog
gdb/testsuite/README
gdb/testsuite/boards/native-gdbserver.exp
gdb/testsuite/boards/native-stdio-gdbserver.exp
gdb/testsuite/lib/gdb.exp

index 04d9450..3acc521 100644 (file)
@@ -1,3 +1,12 @@
+2013-10-02  Pedro Alves  <palves@redhat.com>
+
+       * README (Board Settings): Document "exit_is_reliable".
+       * lib/gdb.exp (gdb_continue_to_end): Check whether the board says
+       running to exit reliably reports program exits.
+       * boards/native-gdbserver.exp: Set exit_is_reliable in the board
+       info.
+       * boards/native-stdio-gdbserver.exp: Likewise.
+
 2013-10-01  Doug Evans  <dje@google.com>
 
        * gdb.python/python.exp: Remove redundant print-stack tests.
index 4d369c5..ec91b14 100644 (file)
@@ -247,6 +247,15 @@ use_gdb_stub
 
   The tests are running with a GDB stub.
 
+exit_is_reliable
+
+  Set to true if GDB can assume that letting the program run to end
+  reliably results in program exits being reported as such, as opposed
+  to, e.g., the program ending in an infinite loop or the board
+  crashing/resetting.  If not set, this defaults to $use_gdb_stub.  In
+  other words, native targets are assumed reliable by default, and
+  remote stubs assumed unreliable.
+
 gdb,predefined_tsv
 
   The predefined trace state variables the board has.
index 6c1430f..ab239ec 100644 (file)
@@ -31,6 +31,7 @@ set_board_info noargs 1
 
 set_board_info sockethost "localhost:"
 set_board_info use_gdb_stub 1
+set_board_info exit_is_reliable 1
 
 # We will be using the standard GDB remote protocol.
 set_board_info gdb_protocol "remote"
index 3b99909..a093904 100644 (file)
@@ -34,6 +34,7 @@ set_board_info sockethost "stdio"
 set_board_info gdb,socketport ""
 set_board_info gdb,get_remote_address ${board}_get_remote_address
 set_board_info use_gdb_stub 1
+set_board_info exit_is_reliable 1
 
 # We will be using the standard GDB remote protocol.
 set_board_info gdb_protocol "remote"
index 5e3331a..6c9948f 100644 (file)
@@ -3806,11 +3806,8 @@ proc gdb_get_line_number { text { file "" } } {
     return $found
 }
 
-# gdb_continue_to_end:
-#      The case where the target uses stubs has to be handled specially. If a
-#       stub is used, we set a breakpoint at exit because we cannot rely on
-#       exit() behavior of a remote target.
-# 
+# Continue the program until it ends.
+#
 # MSSG is the error message that gets printed.  If not given, a
 #      default is used.
 # COMMAND is the command to invoke.  If not given, "continue" is
@@ -3833,7 +3830,19 @@ proc gdb_continue_to_end {{mssg ""} {command continue} {allow_extra 0}} {
   } else {
       set extra ""
   }
-  if $use_gdb_stub {
+
+  # By default, we don't rely on exit() behavior of remote stubs --
+  # it's common for exit() to be implemented as a simple infinite
+  # loop, or a forced crash/reset.  For native targets, by default, we
+  # assume process exit is reported as such.  If a non-reliable target
+  # is used, we set a breakpoint at exit, and continue to that.
+  if { [target_info exists exit_is_reliable] } {
+      set exit_is_reliable [target_info exit_is_reliable]
+  } else {
+      set exit_is_reliable [expr ! $use_gdb_stub]
+  }
+
+  if { ! $exit_is_reliable } {
     if {![gdb_breakpoint "exit"]} {
       return 0
     }