1 # Copyright (C) 1992-2016 Free Software Foundation, Inc.
3 # This file is part of DejaGnu.
5 # DejaGnu is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # DejaGnu is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with DejaGnu. If not, see <http://www.gnu.org/licenses/>.
18 # This file was written by Michael Snyder <msnyder@cygnus.com>.
21 # Stub remote run command.
24 proc gdb_stub_init { dest args } {
29 if {![info exists GDB]} then {
30 set GDB "[lookfor_file $tool_root_dir gdb/gdb]"
32 set GDB [transform gdb]
36 if {[board_info $dest exists gdb_prompt]} {
37 set gdb_prompt [board_info $dest gdb_prompt]
39 set gdb_prompt {\(gdb\)}
45 proc gdb_stub_restart { dest } {
51 for { set x 1 } { $x < 4 } {incr x} {
54 set command "$GDB -nw -nx"
55 if {[host_info exists gdb_opts]} {
56 append command " [host_info gdb_opts]"
58 set spawn_id [remote_spawn host $command]
59 remote_expect host 30 {
62 if { $spawn_id >= 0 } {
63 if {[board_info $dest exists baud]} {
64 remote_send host "set remotebaud [board_info $dest baud]\n"
65 remote_expect host 5 {
68 warning "Error setting baud rate."
75 set value [gdb_stub_startup $dest]
79 verbose "got $value from gdb_stub_startup"
80 remote_send host "quit\n"
86 set name [board_info $dest name]
88 set board_info($name,gdb_is_running) 1
95 proc gdb_stub_remote_check { dest } {
98 if {[board_info $dest exists gdb_serial]} {
99 set serial [board_info $dest gdb_serial]
100 } elseif {[board_info $dest exists serial]} {
101 set serial [board_info $dest serial]
103 set serial [board_info $dest netport]
105 remote_send host "target remote $serial\n"
106 remote_expect host 10 {
107 -re "Couldn't establish connection.*$gdb_prompt" {
110 -re "Remote debugging.*$gdb_prompt" {
111 verbose "stub is already running"
118 remote_send host "\003"
119 remote_expect host 10 {
130 proc gdb_stub_startup { dest } {
134 set is_running_stub 0
136 if {[gdb_stub_remote_check $dest]} {
137 set is_running_stub 1
140 if {[board_info $dest exists serial]} {
141 set serial [board_info $dest serial]
143 set serial [board_info $dest netport]
146 if { ! $is_running_stub } {
147 set command "target [board_info $dest gdb_protocol] $serial\n"
148 remote_send host $command
149 remote_expect host 5 {
150 -re "already.*y or n." {
151 remote_send host "y\n"
154 -re "appears to be alive.*$gdb_prompt" { }
155 -re "Remote target.*connected to.*$gdb_prompt" { }
161 if { $is_running_stub == 0 } {
164 verbose "building loader"
166 if {![file exists $loader]} {
167 if {[board_info $dest exists gdb_stub_offset]} {
168 set result [target_compile $libdir/stub-loader.c $loader executable "libs=-Wl,-Ttext,[board_info $dest gdb_stub_offset]"]
170 set result [target_compile $libdir/stub-loader.c $loader executable "ldscript=[board_info $dest gdb_stub_ldscript]"]
172 verbose "result is $result"
173 if {[isremote host]} {
174 set loader [remote_download host $loader]
177 remote_send host "file $loader\n"
178 remote_expect host 20 {
179 -re "A program is being debug.*Kill it.*y or n. $" {
180 remote_send host "y\n"
183 -re "Load new symbol table.*y or n. $" {
184 remote_send host "y\n"
187 -re "Reading symbols from.*done..*$gdb_prompt $" {}
188 -re "$gdb_prompt $" { warning "GDB couldn't find loader" }
190 warning "(timeout) read symbol file"
195 if {[board_info $dest exists serial]} {
196 set serial [board_info $dest serial]
198 set serial [board_info $dest netport]
200 remote_send host "target [board_info $dest gdb_protocol] $serial\n"
201 remote_expect host 60 {
202 -re "appears to be alive.*$gdb_prompt" { }
203 -re "Remote target.*connected to.*$gdb_prompt" { }
205 warning "Error reconnecting to stub."
209 warning "Error reconnecting to stub."
214 # We only send the offset if gdb_load_offset is set. Otherwise, we
215 # assume that sending the offset isn't needed.
216 if {[board_info $dest exists gdb_load_offset]} {
217 remote_send host "load $loader [board_info $dest gdb_stub_offset]\n"
219 remote_send host "load $loader\n"
221 verbose "Loading $loader into $GDB" 2
224 # FIXME: The value 1200 below should be a parameter.
225 remote_expect host 1200 {
226 -re "Transfer rate:.*Switching to remote protocol.*Remote debugging" {
228 remote_send host "
\x03"
230 remote_send host "
\x03"
233 -re "Loading.*Starting.*at.*$gdb_prompt $" {
234 verbose "Loaded $loader into $GDB" 1
237 -re "Loading.*$gdb_prompt $" {
238 verbose "Loaded $loader into $GDB" 1
240 -re "$gdb_prompt $" {
242 warning "GDB couldn't load."
247 warning "Timed out trying to load $arg."
252 if { ! $no_run_command } {
253 remote_send host "run\n"
254 remote_expect host 60 {
255 -re "A program is being debug.*Kill it.*y or n. $" {
256 remote_send host "y\n"
259 -re "The program being debugged .*y or n. $" {
260 remote_send host "y\n"
263 -re "Starting program:.*loader.*$" {
264 verbose "Starting loader succeeded"
267 warning "(timeout) starting the loader"
271 warning "error starting the loader"
275 remote_send host "
\x03"
277 remote_send host "
\x03"
279 remote_expect host 30 {
280 -re "Give up .and stop debugging it.*$" {
281 remote_send host "y\n"
284 -re "$gdb_prompt $" {
285 verbose "Running loader succeeded"
288 warning "(timeout) interrupting the loader"
292 warning "error interrupting the loader"
296 remote_send host "quit\n"
297 return [gdb_stub_restart $dest]
303 # Delete all breakpoints and verify that they were deleted. If anything
304 # goes wrong we just exit.
306 proc gdb_stub_delete_breakpoints {} {
309 remote_send host "delete breakpoints\n"
310 remote_expect host 10 {
311 -re "Delete all breakpoints.*y or n. $" {
312 remote_send host "y\n"
315 -re "$gdb_prompt $" { }
316 timeout { warning "Delete all breakpoints (timeout)" ; return -1}
318 remote_send host "info breakpoints\n"
319 remote_expect host 10 {
320 -re "No breakpoints or watchpoints..*$gdb_prompt $" {}
321 -re "$gdb_prompt $" { warning "breakpoints not deleted" ; return -1}
322 timeout { warning "info breakpoints (timeout)" ; return -1}
327 proc gdb_stub_go_idle { dest } {
328 gdb_stub_delete_breakpoints
331 proc gdb_stub_add_breakpoint { function args } {
334 remote_send host "break $function\n"
335 remote_expect host 60 {
336 -re "Breakpoint (\[0-9\]+).*$gdb_prompt $" { return $expect_out(1,string) }
337 -re "Function.*not defined.*$gdb_prompt $" { return "undef" }
338 -re "No symbol table.*$gdb_prompt $" { return "undef" }
345 proc gdb_stub_start { dest } {
348 set exit_brnum [gdb_stub_add_breakpoint _exit]
349 if { $exit_brnum eq "undef" || [board_info $dest exists always_break_exit] } {
350 set exit_brnum [gdb_stub_add_breakpoint exit]
352 set abort_brnum [gdb_stub_add_breakpoint abort]
354 upvar #0 gdb_stub_info I
355 set I($dest,exit_brnum) $exit_brnum
356 set I($dest,abort_brnum) $abort_brnum
358 remote_send host "set \$fp=0\n"
359 remote_expect host 10 {
362 # This is needed for the SparcLite. Whee.
363 if {[board_info $dest exists gdb,start_symbol]} {
364 set start_comm "jump *[board_info $dest gdb,start_symbol]\n"
366 set start_comm "jump *start\n"
368 remote_send host "break copyloop\n"
369 remote_expect host 10 {
370 -re "Breakpoint.*$gdb_prompt $" {
371 set start_comm "continue\n"
373 -re "Function.*not defined.*$gdb_prompt $" { }
376 remote_send host $start_comm
377 remote_expect host 10 {
379 remote_send host "y\n"
382 -re "Breakpoint.*in copyloop.*$gdb_prompt $" {
383 remote_send host "jump relocd\n"
386 -re {Continuing at.*[\r\n]} { }
394 proc gdb_stub_spawn { dest prog args } {
395 for { set x 0 } { $x < 3 } { incr x } {
396 if { [remote_ld $dest $prog] != 1 } {
397 return [list "fail" "remote_ld failed"]
400 set result [gdb_stub_start $dest]
401 if { [lindex $result 0] ne "pass" } {
404 return 666; # does anyone use this value?
410 proc gdb_stub_wait { dest timeout } {
414 upvar #0 gdb_stub_info I
415 set exit_brnum $I($dest,exit_brnum)
416 set abort_brnum $I($dest,abort_brnum)
418 remote_expect host $timeout {
419 -re "Breakpoint.*exit.*=0.*$gdb_prompt $" {
420 gdb_stub_go_idle $dest
423 -re "Breakpoint.*exit.*=\[1-9\]\[0-9\]*.*$gdb_prompt $" {
424 gdb_stub_go_idle $dest
427 -re "Breakpoint.*exit.*$gdb_prompt $" {
428 gdb_stub_go_idle $dest
431 -re "Breakpoint.*abort.*$gdb_prompt $" {
432 gdb_stub_go_idle $dest
435 -re " EXIT code 0.*$gdb_prompt $" {
436 gdb_stub_go_idle $dest
439 -re " EXIT code \[1-9]\[0-9]*.*$gdb_prompt $" {
440 gdb_stub_go_idle $dest
443 -re " EXIT code 4242.*$gdb_prompt $" {
444 gdb_stub_go_idle $dest
447 -re "Program received.*$gdb_prompt $" {
448 gdb_stub_go_idle $dest
451 -re "Program exited.*$gdb_prompt $" {
452 gdb_stub_go_idle $dest
455 -re "Breakpoint $exit_brnum.*$gdb_prompt $" {
456 gdb_stub_go_idle $dest
459 -re "Breakpoint $abort_brnum.*$gdb_prompt $" {
460 gdb_stub_go_idle $dest
472 proc gdb_stub_load { dest prog args } {
475 set argnames { "command-line arguments" "input file" "output file" }
477 for { set x 0 } { $x < [llength $args] } { incr x } {
478 if { [lindex $args $x] ne "" } {
479 return [list "unsupported" "no support for [lindex $argnames $x] on this target"]
484 if {[info exists test_timeout]} {
485 set wait_timeout $test_timeout
488 verbose -log "Executing on $dest: $prog (timeout = $wait_timeout)" 2
490 set result [remote_spawn $dest $prog]
493 return [list "fail" "remote_spawn failed"]
496 set result [remote_wait $dest $wait_timeout]
497 set status [lindex $result 0]
498 set output [lindex $result 1]
500 if { $status == 0 } {
501 return [list "pass" $output]
502 } elseif { $status > 0 } {
503 return [list "fail" $output]
505 global gdb_stub_retry
507 if {![info exists gdb_stub_retry]} {
510 set result [eval gdb_stub_load \{$dest\} \{$prog\} $args]
514 return [list "fail" $output]
521 # gdb_stub_ld -- load PROG into the board
522 # Returns a 0 if there was an error,
523 # 1 if it loaded successfully.
525 proc gdb_stub_ld { dest prog } {
529 if {![board_info $dest exists gdb_is_running]} {
530 if {![gdb_stub_restart $dest]} {
535 set loadfile [file tail $prog]
536 set loadpath [file dirname $prog]
538 remote_send host "file $prog\n"
539 remote_expect host 30 {
540 -re "A program is being debug.*Kill it.*y or n. $" {
541 remote_send host "y\n"
544 -re "Load new symbol table.*y or n. $" {
545 remote_send host "y\n"
548 -re "Reading symbols from.*done..*$gdb_prompt $" {}
549 -re "$gdb_prompt $" {
550 # Hmmm...is retrying going to help? I kinda doubt it.
551 warning "GDB couldn't read file"
552 return [gdb_stub_retry_ld $dest $prog]
555 warning "(timeout) read symbol file"
556 return [gdb_stub_retry_ld $dest $prog]
560 # just in case there are old breakpoints lying around.
561 gdb_stub_delete_breakpoints
563 if {[board_info $dest exists gdb_serial]} {
564 set serial [board_info $dest gdb_serial]
565 } elseif {[board_info $dest exists serial]} {
566 set serial [board_info $dest serial]
568 set serial [board_info $dest netport]
571 remote_send host "target remote $serial\n"
572 remote_expect host 60 {
573 -re "Kill it?.*y or n.*" {
574 remote_send host "y\n"
577 -re "$gdb_prompt $" {
578 verbose "Set remote target to $serial" 2
581 warning "Couldn't set remote target."
586 if {[board_info $dest exists gdb_load_offset]} {
587 set offset "[board_info $dest gdb_load_offset]"
591 remote_send host "load $prog $offset\n"
592 verbose "Loading $prog into $GDB" 2
594 remote_expect host 1200 {
595 -re "Loading.*$gdb_prompt $" {
596 verbose "Loaded $prog into $GDB" 1
598 -re "$gdb_prompt $" {
600 warning "GDB couldn't load."
605 perror "Timed out trying to load $prog."
613 # Retry the ld operation, but only once.
616 proc gdb_stub_retry_ld { dest prog } {
617 global gdb_stub_retry_ld
620 if {[info exists gdb_stub_retry_ld]} {
621 unset gdb_stub_retry_ld
624 set gdb_stub_retry_ld 1
626 gdb_stub_restart $dest
627 set status [gdb_stub_ld $dest $prog]
628 if {[info exists gdb_stub_retry_ld]} {
629 unset gdb_stub_retry_ld
634 proc gdb_stub_close { dest } {
636 set name [board_info $dest name]
637 if {[info exists board_info($name,gdb_is_running)]} {
638 unset board_info($name,gdb_is_running)
640 return [remote_close host]
643 set_board_info protocol "gdb_stub"