This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: Gdbserver unit testing


Something Andrew suggested to me a long time ago.  This patch refactors the
gdbserver testsuite support routines so that they can be used concurrently
with a native test.  If gdbserver has been built, it will be tested.  If it
hasn't, the tests will be quietly skipped.  How's it look?  The only test
using the machinery is trivial; it verifies that gdbserver starts, and that
we can connect to it, and run to a breakpoint.

Eli, this creates gdb.gdbserver/ next to gdb.gdb/; what does this mean for
fnchange.lst?  Do I need to find a different name for the directory?

-- 
Daniel Jacobowitz
CodeSourcery, LLC

2005-03-26  Daniel Jacobowitz  <dan@codesourcery.com>

	* Makefile.in (ALL_SUBDIRS): Add gdb.gdbserver.
	* configure.ac: Create gdb.gdbserver/Makefile.
	* lib/gdbserver-support.exp: New file, derived from
	config/gdbserver.exp.
	* config/gdbserver.exp: Use gdbserver-support.exp.
	* gdb.gdbserver/Makefile.in: New file.
	* gdb.gdbserver/server.c: New file.
	* gdb.gdbserver/server-run.exp: New file.

Index: Makefile.in
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/testsuite/Makefile.in,v
retrieving revision 1.11
diff -u -p -r1.11 Makefile.in
--- Makefile.in	12 Oct 2004 14:41:42 -0000	1.11
+++ Makefile.in	27 Mar 2005 02:43:48 -0000
@@ -1,5 +1,6 @@
 # Makefile for regression testing the GNU debugger.
-# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002, 2003, 2004
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002, 2003, 2004,
+# 2005
 # Free Software Foundation, Inc.
 
 # This file is part of GDB.
@@ -37,7 +38,8 @@ SUBDIRS = @subdirs@
 RPATH_ENVVAR = @RPATH_ENVVAR@
 ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.cp gdb.disasm \
 	gdb.dwarf2 \
-	gdb.fortran gdb.java gdb.mi gdb.objc gdb.threads gdb.trace \
+	gdb.fortran gdb.gdbserver gdb.java gdb.mi \
+	gdb.objc gdb.threads gdb.trace \
 	$(SUBDIRS)
 
 EXPECT = `if [ -f $${rootme}/../../expect/expect ] ; then \
Index: configure.ac
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/testsuite/configure.ac,v
retrieving revision 1.2
diff -u -p -r1.2 configure.ac
--- configure.ac	3 Feb 2005 03:58:51 -0000	1.2
+++ configure.ac	27 Mar 2005 02:43:32 -0000
@@ -1,7 +1,7 @@
 #                                                       -*- Autoconf -*-
 # Process this file with autoconf to produce a configure script.
 
-# Copyright 2002, 2003, 2004
+# Copyright 2002, 2003, 2004, 2005
 # Free Software Foundation, Inc.
 #
 # This program is free software; you can redistribute it and/or modify
@@ -112,5 +112,6 @@ AC_OUTPUT([Makefile \
   gdb.ada/Makefile \
   gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
   gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile \
-  gdb.fortran/Makefile gdb.java/Makefile gdb.mi/Makefile \
+  gdb.fortran/Makefile gdb.gdbserver/Makefile \
+  gdb.java/Makefile gdb.mi/Makefile \
   gdb.objc/Makefile gdb.threads/Makefile gdb.trace/Makefile])
Index: config/gdbserver.exp
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/testsuite/config/gdbserver.exp,v
retrieving revision 1.8
diff -u -p -r1.8 gdbserver.exp
--- config/gdbserver.exp	6 Oct 2004 22:51:00 -0000	1.8
+++ config/gdbserver.exp	27 Mar 2005 02:42:25 -0000
@@ -1,8 +1,4 @@
-# Test framework for GDB (remote protocol) using a "gdbserver",
-# ie. a debug agent running as a native process on the same or
-# a different host.
-
-#   Copyright 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -18,19 +14,15 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
 
-# Please email any bugs, comments, and/or additions to this file to:
-# bug-gdb@prep.ai.mit.edu
-
-# This file was written by Michael Snyder. (msnyder@redhat.com)
+# Test framework for GDB (remote protocol) using a "gdbserver",
+# ie. a debug agent running as a native process on the same or
+# a different host.
 
 #
 # This module to be used for testing gdb with a "gdbserver" 
 # built either from libremote or from gdb/gdbserver.  
 #
 
-# Load the basic testing library, and the remote stuff.
-load_lib ../config/monitor.exp
-
 #
 # To be addressed or set in your baseboard config file:
 #
@@ -73,148 +65,19 @@ load_lib ../config/monitor.exp
 #	Defaults to "localhost".  Note: old gdbserver requires 
 #	that you define this, but libremote/gdbserver does not.
 #
-#   set_board_info socketport
+#   set_board_info gdb,socketport
 #	Port id to use for socket connection.  If not set explicitly,
 #	it will start at "2345" and increment for each use.
 #
 
+# The guts live in gdbserver-support.exp now.
 
+load_lib gdbserver-support.exp
 
-#
-# gdb_load -- load a file into the debugger.
-#             return a -1 if anything goes wrong.
-#
-
-global server_exec;
-global portnum;
-set portnum "2345";
-
-proc gdbserver_gdb_load { server_exec } {
-    global portnum
-
-    # Port id -- either specified in baseboard file, or managed here.
-    if [target_info exists gdb,socketport] {
-	set portnum [target_info gdb,socketport];
-    } else {
-	# Bump the port number to avoid conflicts with hung ports.
-	incr portnum;
-    }
-
-    # Extract the local and remote host ids from the target board struct.
-
-    if [target_info exists sockethost] {
-	set debughost  [target_info sockethost];
-    } else {
-	set debughost "localhost:";
-    }
-    # Extract the protocol
-    if [target_info exists gdb_protocol] {
-	set protocol [target_info gdb_protocol];
-    } else {
-	set protocol "remote";
-    }
-
-    # Extract the name of the gdbserver, if known (default 'gdbserver').
-    if [target_info exists gdb_server_prog] {
-	set gdbserver [target_info gdb_server_prog];
-    } else {
-	set gdbserver "gdbserver";
-    }
-    # Extract the socket hostname
-    if [target_info exists sockethost] {
-	set sockethost [target_info sockethost];
-    } else {
-	set sockethost ""
-    }
-
-    # Export the host:port pair.
-    set gdbport $debughost$portnum;
-
-    # Fire off the debug agent
-    if [target_info exists gdb_server_args] {
-        # This flavour of gdbserver takes as arguments those specified
-        # in the board configuration file
-        set custom_args [target_info gdb_server_args];
-	set server_spawn_id [remote_spawn target \
-               "$gdbserver $custom_args"]
-    } else {
-        # This flavour of gdbserver takes as arguments the port information
-        # and the name of the executable file to be debugged.
-	set server_spawn_id [remote_spawn target \
-	    "$gdbserver $sockethost$portnum $server_exec"]
-    }
-
-    # Wait for the server to produce at least one line and an additional
-    # character of output.  This will wait until any TCP socket has been
-    # created, so that GDB can connect.
-    expect {
-	-i $server_spawn_id
-	-notransfer
-	-re ".*\n." { }
-    }
-
-    # We can't just call close, because if gdbserver is local then that means
-    # that it will get a SIGHUP.  Doing it this way could also allow us to
-    # get at the inferior's input or output if necessary, and means that we
-    # don't need to redirect output.
-    expect_background {
-	-i $server_spawn_id
-	-re "." { }
-	eof {
-	    # The spawn ID is already closed now (but not yet waited for).
-	    wait -i $expect_out(spawn_id)
-	}
-    }
-
-    return [list $protocol $gdbport];
-}
-
-proc infer_host_exec { } {
-    set host_exec ""
-
-    send_gdb "info files\n";
-    gdb_expect 30 {
-	-re "Symbols from \"(\[^\"\]+)\"" {
-	    set host_exec $expect_out(1,string);
-	    exp_continue;
-	}
-	-re "Local exec file:\[\r\n\]+\[ \t\]*`(\[^'\]+)'," {
-	    set host_exec $expect_out(1,string);
-	    exp_continue;
-	}
-	-re "$gdb_prompt $" { }
-    }
-
-    return $host_exec
+proc gdbserver_gdb_load { arg } {
+    return [gdbserver_spawn $arg ""]
 }
 
 proc gdb_load { arg } {
-    global host_exec
-    global server_exec
-
-    if { $arg == "" && $host_exec == "" } {
-	set host_exec [infer_host_exec]
-    } elseif { $arg != "" } {
-	set host_exec $arg
-	if [info exists server_exec] { unset server_exec }
-    }
-
-    if { ! [info exists server_exec] } {
-	if [is_remote target] {
-	    set server_exec [remote_download target $host_exec]
-	} else {
-	    set server_exec $host_exec
-	}
-    }
-
-    set res [gdbserver_gdb_load $server_exec]
-    set protocol [lindex $res 0]
-    set gdbport [lindex $res 1]
-
-    if { $arg != "" } {
-	if [gdb_file_cmd $arg] {
-	    return -1
-	}
-    }
-    gdb_target_cmd $protocol $gdbport
+    return [gdbserver_load $arg ""]
 }
Index: gdb.gdbserver/Makefile.in
===================================================================
RCS file: gdb.gdbserver/Makefile.in
diff -N gdb.gdbserver/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb.gdbserver/Makefile.in	27 Mar 2005 02:44:20 -0000
@@ -0,0 +1,24 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+EXECUTABLES =
+
+MISCELLANEOUS =
+
+all info install-info dvi install uninstall installcheck check:
+	@echo "Nothing to be done for $@..."
+
+clean mostlyclean:
+	-find . -name '*.o' -print | xargs rm -f
+	-find . -name '*.ali' -print | xargs rm -f
+	-find . -name 'b~*.ad[sb]' -print | xargs rm -f
+	-rm -f *~ a.out xgdb *.x *.ci *.tmp
+	-rm -f *~ *.o a.out xgdb *.x *.ci *.tmp
+	-rm -f core core.coremaker coremaker.core corefile $(EXECUTABLES)
+	-rm -f $(MISCELLANEOUS) twice-tmp.c
+
+distclean maintainer-clean realclean: clean
+	-rm -f *~ core
+	-rm -f Makefile config.status config.log
+	-rm -f *-init.exp
+	-rm -fr *.log summary detail *.plog *.sum *.psum site.*
Index: gdb.gdbserver/server-run.exp
===================================================================
RCS file: gdb.gdbserver/server-run.exp
diff -N gdb.gdbserver/server-run.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb.gdbserver/server-run.exp	27 Mar 2005 02:51:36 -0000
@@ -0,0 +1,42 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2005 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# Test the basic functionality of gdbserver.
+
+load_lib gdbserver-support.exp
+
+set testfile "server"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [skip_gdbserver_tests] } {
+    return 0
+}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    return -1
+}
+
+gdb_exit
+gdb_start
+
+gdbserver_load $binfile ""
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_breakpoint main
+gdb_test "continue" "Breakpoint.* main .*" "continue to main"
Index: gdb.gdbserver/server.c
===================================================================
RCS file: gdb.gdbserver/server.c
diff -N gdb.gdbserver/server.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb.gdbserver/server.c	27 Mar 2005 02:52:41 -0000
@@ -0,0 +1,24 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2005 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+int
+main (int argc, char **argv)
+{
+  return 0;
+}
Index: lib/gdbserver-support.exp
===================================================================
RCS file: lib/gdbserver-support.exp
diff -N lib/gdbserver-support.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/gdbserver-support.exp	27 Mar 2005 02:53:16 -0000
@@ -0,0 +1,250 @@
+# Copyright 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# This file is based on config/gdbserver.exp, which was written by
+# Michael Snyder (msnyder@redhat.com).
+
+#
+# To be addressed or set in your baseboard config file:
+#
+#   set_board_info gdb_protocol "remote"
+#	Unles you have a gdbserver that uses a different protocol...
+#
+#   set_board_info gdb_server_prog
+#	This will be the path to the gdbserver program you want to test.
+#	Defaults to "gdbserver".
+#
+#   set_board_info sockethost
+#	The name of the host computer whose socket is being used.
+#	Defaults to "localhost".  Note: old gdbserver requires 
+#	that you define this, but libremote/gdbserver does not.
+#
+#   set_board_info gdb,socketport
+#	Port id to use for socket connection.  If not set explicitly,
+#	it will start at "2345" and increment for each use.
+#
+
+#
+# gdb_target_cmd
+# Send gdb the "target" command
+#
+proc gdb_target_cmd { targetname serialport } {
+    global gdb_prompt
+
+    for {set i 1} {$i <= 3} {incr i} {
+	send_gdb "target $targetname $serialport\n"
+	gdb_expect 60 {
+	    -re "A program is being debugged already.*ill it.*y or n. $" {
+		send_gdb "y\n"
+		exp_continue
+	    }
+	    -re "Couldn't establish connection to remote.*$gdb_prompt" {
+		verbose "Connection failed"
+	    }
+	    -re "Remote MIPS debugging.*$gdb_prompt" {
+		verbose "Set target to $targetname"
+		return 0
+	    }
+	    -re "Remote debugging using .*$serialport.*$gdb_prompt" {
+		verbose "Set target to $targetname"
+		return 0
+	    }
+	    -re "Remote target $targetname connected to.*$gdb_prompt" {
+		verbose "Set target to $targetname"
+		return 0
+	    }
+	    -re "Connected to.*$gdb_prompt" { 
+		verbose "Set target to $targetname"
+		return 0
+	    }
+	    -re "Ending remote.*$gdb_prompt" { }
+	    -re "Connection refused.*$gdb_prompt" {
+		verbose "Connection refused by remote target.  Pausing, and trying again."
+		sleep 30
+		continue
+	    }
+	    -re "Timeout reading from remote system.*$gdb_prompt" {
+		verbose "Got timeout error from gdb."
+	    }
+	    timeout {
+		send_gdb ""
+		break
+	    }
+	}
+    }
+    return 1
+}
+
+
+global portnum
+set portnum "2345"
+
+# Locate the gdbserver binary.  Returns "" if gdbserver could not be found.
+
+proc find_gdbserver { } {
+  global GDB
+
+  if [target_info exists gdb_server_prog] {
+    return [target_info gdb_server_prog]
+  }
+
+  set gdbserver "${GDB}server"
+  if { [file isdirectory $gdbserver] } {
+    append gdbserver "/gdbserver"
+  }
+
+  if { [file executable $gdbserver] } {
+    return $gdbserver
+  }
+
+  return ""
+}
+
+# Return non-zero if we should skip gdbserver-specific tests.
+
+proc skip_gdbserver_tests { } {
+  if { [find_gdbserver] == "" } {
+    return 1
+  }
+
+  return 0
+}
+
+# Start a gdbserver process running SERVER_EXEC, and connect GDB
+# to it.  CHILD_ARGS are passed to the inferior.
+#
+# Returns the target protocol and socket to connect to.
+
+proc gdbserver_spawn { server_exec child_args } {
+    global portnum
+
+    # Port id -- either specified in baseboard file, or managed here.
+    if [target_info exists gdb,socketport] {
+	set portnum [target_info gdb,socketport]
+    } else {
+	# Bump the port number to avoid conflicts with hung ports.
+	incr portnum
+    }
+
+    # Extract the local and remote host ids from the target board struct.
+    if [target_info exists sockethost] {
+	set debughost  [target_info sockethost]
+    } else {
+	set debughost "localhost:"
+    }
+
+    # Extract the protocol
+    if [target_info exists gdb_protocol] {
+	set protocol [target_info gdb_protocol]
+    } else {
+	set protocol "remote"
+    }
+
+    set gdbserver [find_gdbserver]
+
+    # Export the host:port pair.
+    set gdbport $debughost$portnum
+
+    # Fire off the debug agent.  This flavour of gdbserver takes as
+    # arguments the port information, the name of the executable file to
+    # be debugged, and any arguments.
+    set gdbserver_command "$gdbserver :$portnum $server_exec"
+    if { $child_args != "" } {
+	append gdbserver_command " $child_args"
+    }
+
+    set server_spawn_id [remote_spawn target $gdbserver_command]
+
+    # Wait for the server to produce at least one line and an additional
+    # character of output.  This will wait until any TCP socket has been
+    # created, so that GDB can connect.
+    expect {
+	-i $server_spawn_id
+	-notransfer
+	-re ".*\n." { }
+    }
+
+    # We can't just call close, because if gdbserver is local then that means
+    # that it will get a SIGHUP.  Doing it this way could also allow us to
+    # get at the inferior's input or output if necessary, and means that we
+    # don't need to redirect output.
+    expect_background {
+	-i $server_spawn_id
+	-re "." { }
+	eof {
+	    # The spawn ID is already closed now (but not yet waited for).
+	    wait -i $expect_out(spawn_id)
+	}
+    }
+
+    return [list $protocol $gdbport]
+}
+
+proc infer_host_exec { } {
+    set host_exec ""
+
+    send_gdb "info files\n"
+    gdb_expect 30 {
+	-re "Symbols from \"(\[^\"\]+)\"" {
+	    set host_exec $expect_out(1,string)
+	    exp_continue
+	}
+	-re "Local exec file:\[\r\n\]+\[ \t\]*`(\[^'\]+)'," {
+	    set host_exec $expect_out(1,string)
+	    exp_continue
+	}
+	-re "$gdb_prompt $" { }
+    }
+
+    return $host_exec
+}
+
+# Start a gdbserver process running HOST_EXEC and pass CHILD_ARGS
+# to it.  Return 0 on success, or non-zero on failure.
+
+proc gdbserver_load { host_exec child_args } {
+    global gdbserver_host_exec
+    global gdbserver_server_exec
+
+    # If we weren't passed an explicit binary, try to reuse the current
+    # one.  If we were, be sure to redownload it.
+
+    if { $host_exec == "" && $gdbserver_host_exec == "" } {
+	set gdbserver_host_exec [infer_host_exec]
+    } elseif { $host_exec != "" } {
+	set gdbserver_host_exec $host_exec
+	if [info exists gdbserver_server_exec] { unset gdbserver_server_exec }
+    }
+
+    if { ! [info exists gdbserver_server_exec] } {
+	if [is_remote target] {
+	    set gdbserver_server_exec [remote_download target $gdbserver_host_exec]
+	} else {
+	    set gdbserver_server_exec $gdbserver_host_exec
+	}
+    }
+
+    set res [gdbserver_spawn $gdbserver_server_exec $child_args]
+    set protocol [lindex $res 0]
+    set gdbport [lindex $res 1]
+
+    if { $host_exec != "" } {
+	if [gdb_file_cmd $host_exec] {
+	    return -1
+	}
+    }
+    gdb_target_cmd $protocol $gdbport
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]