1# Test framework for GDB (remote protocol) using a "gdbserver",
2# ie. a debug agent running as a native process on the same or
3# a different host.
4
5#   Copyright 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
6
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
21# Please email any bugs, comments, and/or additions to this file to:
22# bug-gdb@prep.ai.mit.edu
23
24# This file was written by Michael Snyder. (msnyder@redhat.com)
25
26#
27# This module to be used for testing gdb with a "gdbserver"
28# built either from libremote or from gdb/gdbserver.
29#
30
31# Load the basic testing library, and the remote stuff.
32load_lib ../config/monitor.exp
33
34#
35# To be addressed or set in your baseboard config file:
36#
37#   set_board_info gdb_protocol "remote"
38#	Unles you have a gdbserver that uses a different protocol...
39#
40#   set_board_info use_gdb_stub 1
41#	This tells the rest of the test suite not to do things
42#	like "run" which don't work well on remote targets.
43#
44#   set_board_info gdb,do_reload_on_run 1
45#	Unles you have a gdbserver that can handle multiple sessions.
46#
47#   set_board_info noargs 1
48#	At present there is no provision in the remote protocol
49#	for passing arguments.  This test framework does not
50#	address the issue, so it's best to set this variable
51#	in your baseboard configuration file.
52#	FIXME: there's no reason why the test harness couldn't
53#	pass commandline args when it spawns gdbserver.
54#
55#   set_board_info gdb,noinferiorio 1
56#	Neither the traditional gdbserver nor the one in libremote
57#	can presently capture stdout and relay it to GDB via the
58#	'O' packet.  This means that tests involving printf will
59#	fail unles you set this varibale in your baseboard
60#	configuration file.
61#
62#   set_board_info gdb,no_hardware_watchpoints 1
63#	Unles you have a gdbserver that supports hardware watchpoints.
64#	FIXME: gdb should detect if the target doesn't support them,
65#	and fall back to using software watchpoints.
66#
67#   set_board_info gdb_server_prog
68#	This will be the path to the gdbserver program you want to test.
69#	Defaults to "gdbserver".
70#
71#   set_board_info sockethost
72#	The name of the host computer whose socket is being used.
73#	Defaults to "localhost".  Note: old gdbserver requires
74#	that you define this, but libremote/gdbserver does not.
75#
76#   set_board_info socketport
77#	Port id to use for socket connection.  If not set explicitly,
78#	it will start at "2345" and increment for each use.
79#
80
81
82
83#
84# gdb_load -- load a file into the debugger.
85#             return a -1 if anything goes wrong.
86#
87
88global server_exec;
89global portnum;
90set portnum "2345";
91
92proc gdbserver_gdb_load { server_exec } {
93    global portnum
94
95    # Port id -- either specified in baseboard file, or managed here.
96    if [target_info exists gdb,socketport] {
97	set portnum [target_info gdb,socketport];
98    } else {
99	# Bump the port number to avoid conflicts with hung ports.
100	incr portnum;
101    }
102
103    # Extract the local and remote host ids from the target board struct.
104
105    if [target_info exists sockethost] {
106	set debughost  [target_info sockethost];
107    } else {
108	set debughost "localhost:";
109    }
110    # Extract the protocol
111    if [target_info exists gdb_protocol] {
112	set protocol [target_info gdb_protocol];
113    } else {
114	set protocol "remote";
115    }
116
117    # Extract the name of the gdbserver, if known (default 'gdbserver').
118    if [target_info exists gdb_server_prog] {
119	set gdbserver [target_info gdb_server_prog];
120    } else {
121	set gdbserver "gdbserver";
122    }
123    # Extract the socket hostname
124    if [target_info exists sockethost] {
125	set sockethost [target_info sockethost];
126    } else {
127	set sockethost ""
128    }
129
130    # Export the host:port pair.
131    set gdbport $debughost$portnum;
132
133    # Fire off the debug agent
134    if [target_info exists gdb_server_args] {
135        # This flavour of gdbserver takes as arguments those specified
136        # in the board configuration file
137        set custom_args [target_info gdb_server_args];
138	set server_spawn_id [remote_spawn target \
139               "$gdbserver $custom_args"]
140    } else {
141        # This flavour of gdbserver takes as arguments the port information
142        # and the name of the executable file to be debugged.
143	set server_spawn_id [remote_spawn target \
144	    "$gdbserver $sockethost$portnum $server_exec"]
145    }
146
147    # Wait for the server to produce at least one line and an additional
148    # character of output.  This will wait until any TCP socket has been
149    # created, so that GDB can connect.
150    expect {
151	-i $server_spawn_id
152	-notransfer
153	-re ".*\n." { }
154    }
155
156    # We can't just call close, because if gdbserver is local then that means
157    # that it will get a SIGHUP.  Doing it this way could also allow us to
158    # get at the inferior's input or output if necessary, and means that we
159    # don't need to redirect output.
160    expect_background {
161	-i $server_spawn_id
162	-re "." { }
163	eof {
164	    # The spawn ID is already closed now (but not yet waited for).
165	    wait -i $expect_out(spawn_id)
166	}
167    }
168
169    return [list $protocol $gdbport];
170}
171
172proc infer_host_exec { } {
173    set host_exec ""
174
175    send_gdb "info files\n";
176    gdb_expect 30 {
177	-re "Symbols from \"(\[^\"\]+)\"" {
178	    set host_exec $expect_out(1,string);
179	    exp_continue;
180	}
181	-re "Local exec file:\[\r\n\]+\[ \t\]*`(\[^'\]+)'," {
182	    set host_exec $expect_out(1,string);
183	    exp_continue;
184	}
185	-re "$gdb_prompt $" { }
186    }
187
188    return $host_exec
189}
190
191proc gdb_load { arg } {
192    global host_exec
193    global server_exec
194
195    if { $arg == "" && $host_exec == "" } {
196	set host_exec [infer_host_exec]
197    } elseif { $arg != "" } {
198	set host_exec $arg
199	if [info exists server_exec] { unset server_exec }
200    }
201
202    if { ! [info exists server_exec] } {
203	if [is_remote target] {
204	    set server_exec [remote_download target $host_exec]
205	} else {
206	    set server_exec $host_exec
207	}
208    }
209
210    set res [gdbserver_gdb_load $server_exec]
211    set protocol [lindex $res 0]
212    set gdbport [lindex $res 1]
213
214    if { $arg != "" } {
215	if [gdb_file_cmd $arg] {
216	    return -1
217	}
218    }
219    gdb_target_cmd $protocol $gdbport
220}
221