Re: [PATCH 1/2] Make catch-syscall.exp work with "target remote". A.k.a., teach the testsuite that GDBserver reliably reports program exits.

Pedro Alves
2013-10-02T11:51:29Z

Now applied as well (after patch 2/2), as below.

-----
Subject: Teach the testsuite that GDBserver reliably reports program exits.

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/README | 9 +++++++++
gdb/testsuite/boards/native-gdbserver.exp | 1 +
gdb/testsuite/boards/native-stdio-gdbserver.exp | 1 +
gdb/testsuite/lib/gdb.exp | 21 +++++++++++++++------
4 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/gdb/testsuite/README b/gdb/testsuite/README
index 4d369c5..ec91b14 100644
--- a/gdb/testsuite/README
+++ b/gdb/testsuite/README
@@ -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.
diff --git a/gdb/testsuite/boards/native-gdbserver.exp b/gdb/testsuite/boards/native-gdbserver.exp
index 6c1430f..ab239ec 100644
--- a/gdb/testsuite/boards/native-gdbserver.exp
+++ b/gdb/testsuite/boards/native-gdbserver.exp
@@ -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"
diff --git a/gdb/testsuite/boards/native-stdio-gdbserver.exp b/gdb/testsuite/boards/native-stdio-gdbserver.exp
index 3b99909..a093904 100644
--- a/gdb/testsuite/boards/native-stdio-gdbserver.exp
+++ b/gdb/testsuite/boards/native-stdio-gdbserver.exp
@@ -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"
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 5e3331a..6c9948f 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -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
}