Commit | Line | Data |
---|---|---|
9b254dd1 | 1 | # Copyright 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008 |
2f83a18e | 2 | # Free Software Foundation, Inc. |
6f8eac0e DJ |
3 | |
4 | # This program is free software; you can redistribute it and/or modify | |
5 | # it under the terms of the GNU General Public License as published by | |
e22f8b7c | 6 | # the Free Software Foundation; either version 3 of the License, or |
6f8eac0e | 7 | # (at your option) any later version. |
e22f8b7c | 8 | # |
6f8eac0e DJ |
9 | # This program is distributed in the hope that it will be useful, |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. | |
e22f8b7c | 13 | # |
6f8eac0e | 14 | # You should have received a copy of the GNU General Public License |
e22f8b7c | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
6f8eac0e DJ |
16 | |
17 | # This file is based on config/gdbserver.exp, which was written by | |
18 | # Michael Snyder (msnyder@redhat.com). | |
19 | ||
20 | # | |
21 | # To be addressed or set in your baseboard config file: | |
22 | # | |
23 | # set_board_info gdb_protocol "remote" | |
24 | # Unles you have a gdbserver that uses a different protocol... | |
25 | # | |
26 | # set_board_info gdb_server_prog | |
27 | # This will be the path to the gdbserver program you want to test. | |
28 | # Defaults to "gdbserver". | |
29 | # | |
30 | # set_board_info sockethost | |
31 | # The name of the host computer whose socket is being used. | |
32 | # Defaults to "localhost". Note: old gdbserver requires | |
33 | # that you define this, but libremote/gdbserver does not. | |
34 | # | |
35 | # set_board_info gdb,socketport | |
36 | # Port id to use for socket connection. If not set explicitly, | |
37 | # it will start at "2345" and increment for each use. | |
38 | # | |
39 | ||
40 | # | |
41 | # gdb_target_cmd | |
42 | # Send gdb the "target" command | |
43 | # | |
44 | proc gdb_target_cmd { targetname serialport } { | |
45 | global gdb_prompt | |
46 | ||
ef783a7d | 47 | set serialport_re [string_to_regexp $serialport] |
6f8eac0e DJ |
48 | for {set i 1} {$i <= 3} {incr i} { |
49 | send_gdb "target $targetname $serialport\n" | |
50 | gdb_expect 60 { | |
51 | -re "A program is being debugged already.*ill it.*y or n. $" { | |
52 | send_gdb "y\n" | |
53 | exp_continue | |
54 | } | |
2f83a18e | 55 | -re "Couldn't establish connection to remote.*$gdb_prompt $" { |
6f8eac0e DJ |
56 | verbose "Connection failed" |
57 | } | |
58 | -re "Remote MIPS debugging.*$gdb_prompt" { | |
59 | verbose "Set target to $targetname" | |
60 | return 0 | |
61 | } | |
ef783a7d | 62 | -re "Remote debugging using .*$serialport_re.*$gdb_prompt $" { |
6f8eac0e DJ |
63 | verbose "Set target to $targetname" |
64 | return 0 | |
65 | } | |
2f83a18e | 66 | -re "Remote target $targetname connected to.*$gdb_prompt $" { |
6f8eac0e DJ |
67 | verbose "Set target to $targetname" |
68 | return 0 | |
69 | } | |
2f83a18e | 70 | -re "Connected to.*$gdb_prompt $" { |
6f8eac0e DJ |
71 | verbose "Set target to $targetname" |
72 | return 0 | |
73 | } | |
2f83a18e DJ |
74 | -re "Ending remote.*$gdb_prompt $" { } |
75 | -re "Connection refused.*$gdb_prompt $" { | |
6f8eac0e DJ |
76 | verbose "Connection refused by remote target. Pausing, and trying again." |
77 | sleep 30 | |
78 | continue | |
79 | } | |
2f83a18e | 80 | -re "Timeout reading from remote system.*$gdb_prompt $" { |
6f8eac0e DJ |
81 | verbose "Got timeout error from gdb." |
82 | } | |
b741e217 DJ |
83 | -notransfer -re "Remote debugging using .*\r\n> $" { |
84 | # We got an unexpected prompt while creating the target. | |
85 | # Leave it there for the test to diagnose. | |
86 | return 1 | |
87 | } | |
6f8eac0e DJ |
88 | timeout { |
89 | send_gdb "\ 3" | |
90 | break | |
91 | } | |
92 | } | |
93 | } | |
94 | return 1 | |
95 | } | |
96 | ||
97 | ||
98 | global portnum | |
99 | set portnum "2345" | |
100 | ||
101 | # Locate the gdbserver binary. Returns "" if gdbserver could not be found. | |
102 | ||
103 | proc find_gdbserver { } { | |
104 | global GDB | |
105 | ||
106 | if [target_info exists gdb_server_prog] { | |
107 | return [target_info gdb_server_prog] | |
108 | } | |
109 | ||
110 | set gdbserver "${GDB}server" | |
111 | if { [file isdirectory $gdbserver] } { | |
112 | append gdbserver "/gdbserver" | |
113 | } | |
114 | ||
115 | if { [file executable $gdbserver] } { | |
116 | return $gdbserver | |
117 | } | |
118 | ||
119 | return "" | |
120 | } | |
121 | ||
122 | # Return non-zero if we should skip gdbserver-specific tests. | |
123 | ||
124 | proc skip_gdbserver_tests { } { | |
125 | if { [find_gdbserver] == "" } { | |
126 | return 1 | |
127 | } | |
128 | ||
129 | return 0 | |
130 | } | |
131 | ||
132 | # Start a gdbserver process running SERVER_EXEC, and connect GDB | |
133 | # to it. CHILD_ARGS are passed to the inferior. | |
134 | # | |
135 | # Returns the target protocol and socket to connect to. | |
136 | ||
b741e217 | 137 | proc gdbserver_spawn { child_args } { |
6f8eac0e | 138 | global portnum |
b741e217 DJ |
139 | global gdbserver_host_exec |
140 | global gdbserver_host_mtime | |
141 | global gdbserver_server_exec | |
142 | global last_loaded_file | |
143 | ||
144 | set host_exec $last_loaded_file | |
145 | ||
146 | # If we already downloaded a file to the target, see if we can reuse it. | |
147 | set reuse 0 | |
148 | if { [info exists gdbserver_server_exec] } { | |
149 | set reuse 1 | |
150 | ||
151 | # If the file has changed, we can not. | |
152 | if { $host_exec != $gdbserver_host_exec } { | |
153 | set reuse 0 | |
154 | } | |
155 | ||
156 | # If the mtime has changed, we can not. | |
157 | if { [file mtime $host_exec] != $gdbserver_host_mtime } { | |
158 | set reuse 0 | |
159 | } | |
160 | } | |
161 | ||
162 | if { $reuse == 0 } { | |
163 | set gdbserver_host_exec $host_exec | |
164 | set gdbserver_host_mtime [file mtime $host_exec] | |
165 | if [is_remote target] { | |
93f02886 | 166 | set gdbserver_server_exec [gdb_download $host_exec] |
b741e217 DJ |
167 | } else { |
168 | set gdbserver_server_exec $host_exec | |
169 | } | |
170 | } | |
6f8eac0e DJ |
171 | |
172 | # Port id -- either specified in baseboard file, or managed here. | |
173 | if [target_info exists gdb,socketport] { | |
174 | set portnum [target_info gdb,socketport] | |
175 | } else { | |
176 | # Bump the port number to avoid conflicts with hung ports. | |
177 | incr portnum | |
178 | } | |
179 | ||
180 | # Extract the local and remote host ids from the target board struct. | |
181 | if [target_info exists sockethost] { | |
182 | set debughost [target_info sockethost] | |
183 | } else { | |
184 | set debughost "localhost:" | |
185 | } | |
186 | ||
187 | # Extract the protocol | |
188 | if [target_info exists gdb_protocol] { | |
189 | set protocol [target_info gdb_protocol] | |
190 | } else { | |
191 | set protocol "remote" | |
192 | } | |
193 | ||
194 | set gdbserver [find_gdbserver] | |
195 | ||
196 | # Export the host:port pair. | |
197 | set gdbport $debughost$portnum | |
198 | ||
199 | # Fire off the debug agent. This flavour of gdbserver takes as | |
200 | # arguments the port information, the name of the executable file to | |
201 | # be debugged, and any arguments. | |
b741e217 | 202 | set gdbserver_command "$gdbserver :$portnum $gdbserver_server_exec" |
6f8eac0e DJ |
203 | if { $child_args != "" } { |
204 | append gdbserver_command " $child_args" | |
205 | } | |
206 | ||
207 | set server_spawn_id [remote_spawn target $gdbserver_command] | |
208 | ||
209 | # Wait for the server to produce at least one line and an additional | |
210 | # character of output. This will wait until any TCP socket has been | |
211 | # created, so that GDB can connect. | |
212 | expect { | |
213 | -i $server_spawn_id | |
214 | -notransfer | |
215 | -re ".*\n." { } | |
216 | } | |
217 | ||
218 | # We can't just call close, because if gdbserver is local then that means | |
219 | # that it will get a SIGHUP. Doing it this way could also allow us to | |
220 | # get at the inferior's input or output if necessary, and means that we | |
221 | # don't need to redirect output. | |
222 | expect_background { | |
223 | -i $server_spawn_id | |
2226f861 | 224 | full_buffer { } |
6f8eac0e DJ |
225 | eof { |
226 | # The spawn ID is already closed now (but not yet waited for). | |
227 | wait -i $expect_out(spawn_id) | |
228 | } | |
229 | } | |
230 | ||
231 | return [list $protocol $gdbport] | |
232 | } | |
233 | ||
6f8eac0e DJ |
234 | # Start a gdbserver process running HOST_EXEC and pass CHILD_ARGS |
235 | # to it. Return 0 on success, or non-zero on failure. | |
236 | ||
b741e217 | 237 | proc gdbserver_run { child_args } { |
b0f4b84b DJ |
238 | global gdbserver_protocol |
239 | global gdbserver_gdbport | |
240 | ||
2226f861 DJ |
241 | # Kill anything running before we try to start gdbserver, in case |
242 | # we are sharing a serial connection. | |
243 | global gdb_prompt | |
244 | send_gdb "kill\n" | |
245 | gdb_expect 120 { | |
246 | -re "Kill the program being debugged. .y or n. $" { | |
247 | send_gdb "y\n" | |
248 | verbose "\t\tKilling previous program being debugged" | |
249 | exp_continue | |
250 | } | |
251 | -re "$gdb_prompt $" { | |
252 | # OK. | |
253 | } | |
254 | } | |
255 | ||
b741e217 | 256 | set res [gdbserver_spawn $child_args] |
b0f4b84b DJ |
257 | set gdbserver_protocol [lindex $res 0] |
258 | set gdbserver_gdbport [lindex $res 1] | |
259 | ||
260 | return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport] | |
261 | } | |
262 | ||
263 | # Reconnect to the previous gdbserver session. | |
264 | ||
265 | proc gdbserver_reconnect { } { | |
266 | global gdbserver_protocol | |
267 | global gdbserver_gdbport | |
6f8eac0e | 268 | |
b0f4b84b | 269 | return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport] |
6f8eac0e | 270 | } |