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, write to the Free Software Foundation,
17 # Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
19 # Note: some of this was cribbed from the gdb testsuite since we need
20 # to use some pretty standard gdb features (breakpoints in particular).
22 # Load up some standard junk.
25 if {![info exists board]} {
26 perror "$board must be set before loading gdb-comm"
29 # The number of times we've tried to download/execute this executable.
33 # Delete all breakpoints and verify that they were deleted. If anything
34 # goes wrong, return -1.
36 proc gdb_comm_delete_breakpoints {} {
39 remote_send host "delete breakpoints\n"
40 remote_expect host 10 {
41 -re "Delete all breakpoints.*y or n. $" {
42 remote_send host "y\n"
45 -re ".*$gdb_prompt $" { }
46 timeout { perror "Delete all breakpoints (timeout)" ; return -1}
48 remote_send host "info breakpoints\n"
49 remote_expect host 10 {
50 -re "No breakpoints or watchpoints..*$gdb_prompt $" {}
51 -re ".*$gdb_prompt $" { perror "breakpoints not deleted" ; return -1}
52 timeout { perror "info breakpoints (timeout)" ; return -1}
58 # Inform the debugger that we have a new exec file.
59 # return a -1 if anything goes wrong, 0 on success.
61 proc gdb_comm_file_cmd { arg } {
69 # The "file" command loads up a new symbol file for gdb, deal with
70 # the various messages it might spew out.
71 if {[isremote host]} {
72 set arg [remote_download host $arg a.out]
74 remote_send host "file $arg\n"
75 remote_expect host 60 {
76 -re "Reading symbols from.*done.*$gdb_prompt $" {
77 verbose "\t\tLoaded $arg into the $GDB"
80 -re "has no symbol-table.*$gdb_prompt $" {
81 perror "$arg wasn't compiled with \"-g\""
84 -re "A program is being debugged already.*Kill it.*y or n. $" {
85 remote_send host "y\n"
86 verbose "\t\tKilling previous program being debugged"
89 -re {Load new symbol table from ".*".*y or n.*$} {
90 remote_send host "y\n"
91 remote_expect host 60 {
92 -re "Reading symbols from.*done.*$gdb_prompt $" {
93 verbose "\t\tLoaded $arg with new symbol table into $GDB"
97 perror "(timeout) Couldn't load $arg, other program already loaded."
102 -re ".*No such file or directory.*$gdb_prompt $" {
103 perror "($arg) No such file or directory\n"
106 -re "$gdb_prompt $" {
107 perror "couldn't load $arg into $GDB."
111 perror "couldn't load $arg into $GDB (timed out)."
115 # This is an attempt to detect a core dump, but seems not to
116 # work. Perhaps we need to match .* followed by eof, in which
117 # expect does not seem to have a way to do that.
118 perror "couldn't load $arg into $GDB (end of file)."
125 # Disconnect from the target and forget that we have an executable. Returns
126 # -1 on failure, 0 on success.
128 proc gdb_comm_go_idle { } {
131 if {![board_info host exists fileid]} {
135 remote_send host "target exec\n"
136 remote_expect host 10 {
137 -re "Kill it.*y or n.*$" {
138 remote_send host "y\n"
141 -re "No exec.* file now.*$gdb_prompt $" {
151 # Start GDB running with target DEST.
152 proc gdb_comm_start { dest } {
157 # The variable gdb_prompt is a regexp which matches the gdb prompt. Set it
158 # if it is not already set.
159 if {![board_info $dest exists gdb_prompt]} then {
160 set gdb_prompt {\(gdb\)}
162 set gdb_prompt [board_info $dest gdb_prompt]
164 # Similarly for GDB. Look in the object directory for gdb if we aren't
166 if {![info exists GDB]} then {
167 set GDB "[lookfor_file $tool_root_dir gdb/gdb]"
169 set GDB [transform gdb]
172 if {[board_info host exists gdb_opts]} {
173 set gdb_opts [board_info host gdb_opts]
177 # Start up gdb (no startfiles, no windows) and wait for a prompt.
178 remote_spawn host "$GDB $gdb_opts -nw -nx"
179 remote_expect host 60 {
180 -re ".*$gdb_prompt $" { }
182 remote_send host "set height 0\n"
183 remote_expect host 10 {
184 -re ".*$gdb_prompt $" {}
186 remote_send host "set width 0\n"
187 remote_expect host 10 {
188 -re ".*$gdb_prompt $" {}
192 # Add a breakpoint at function FUNCTION. We assume that GDB has already been
194 proc gdb_comm_add_breakpoint { function } {
197 remote_send host "break $function\n"
198 remote_expect host 60 {
199 -re "Breakpoint.*$gdb_prompt $" { return "" }
200 -re "Function.*not defined.*$gdb_prompt $" { return "undef" }
201 -re "No symbol table.*$gdb_prompt $" { return "undef" }
202 -re {.*Make breakpoint pending.*\? \(y or \[n\]\) $} {
203 remote_send host "y\n"
213 # quit_gdb -- try to quit GDB gracefully
219 set spawn_id [board_info host fileid]
221 if { $spawn_id ne "" && $spawn_id > -1 } {
222 if { [remote_send host "quit\n"] eq "" } {
223 remote_expect host 10 {
225 remote_send host "y\n"
228 -re {.*[*][*][*].*EXIT code} { }
233 if {![isremote host]} {
238 proc gdb_comm_leave { } {
239 if {[isremote host]} {
246 # gdb_comm_load -- load the program and execute it
248 # PROG is a full pathname to the file to load, no arguments.
249 # Result is "untested", "pass", "fail", etc.
252 proc gdb_comm_load { dest prog args } {
257 set argnames { "command-line arguments" "input file" "output file" }
259 for { set x 0 } { $x < [llength $args] } { incr x } {
260 if { [lindex $args $x] ne "" } {
261 return [list "unsupported" "no support for [lindex $argnames $x] on this target"]
264 # Make sure the file we're supposed to load really exists.
265 if {![file exists $prog]} then {
266 perror "$prog does not exist."
267 return [list "untested" ""]
270 if { [isremote host] || ![board_info host exists fileid] } {
274 # Remove all breakpoints, then tell the debugger that we have
276 if { [gdb_comm_delete_breakpoints] != 0 } {
278 return [gdb_comm_reload $dest $prog $args]
280 if { [gdb_comm_file_cmd $prog] != 0 } {
282 return [gdb_comm_reload $dest $prog $args]
284 if {[board_info $dest exists gdb_sect_offset]} {
285 set textoff [board_info $dest gdb_sect_offset]
286 remote_send host "sect .text $textoff\n"
287 remote_expect host 10 {
288 -re {(0x[0-9a-z]+) - 0x[0-9a-z]+ is \.data} {
289 set dataoff $expect_out(1,string)
292 -re {(0x[0-9a-z]+) - 0x[0-9a-z]+ is \.bss} {
293 set bssoff $expect_out(1,string)
298 set dataoff [format 0x%x [expr {$dataoff + $textoff}]]
299 set bssoff [format 0x%x [expr {$bssoff + $textoff}]]
300 remote_send host "sect .data $dataoff\n"
301 remote_expect host 10 {
304 remote_send host "sect .bss $bssoff\n"
305 remote_expect host 10 {
310 set protocol [board_info $dest gdb_protocol]
311 if {[board_info $dest exists gdb_serial]} {
312 set targetname [board_info $dest gdb_serial]
313 } elseif {[board_info $dest exists netport]} {
314 set targetname [board_info $dest netport]
316 if {[board_info $dest exists serial]} {
317 set targetname [board_info $dest serial]
322 if {[board_info $dest exists baud]} {
323 remote_send host "set remotebaud [board_info $dest baud]\n"
324 remote_expect host 10 {
325 -re ".*$gdb_prompt $" {}
327 warning "failed setting baud rate"
331 remote_send host "target $protocol $targetname\n"
332 remote_expect host 60 {
333 -re "Couldn.t establish conn.*$gdb_prompt $" {
334 warning "Unable to connect to $targetname with GDB."
336 return [gdb_comm_reload $dest $prog $args]
338 -re "Ending remote.*$gdb_prompt $" {
339 warning "Unable to connect to $targetname with GDB."
341 return [gdb_comm_reload $dest $prog $args]
343 -re "Remote target $protocol connected to.*$gdb_prompt $" { }
344 -re "Remote target $targetname connected to.*$gdb_prompt $" { }
345 -re "Connected to ARM RDI target.*$gdb_prompt $" { }
346 -re "Connected to the simulator.*$gdb_prompt $" { }
347 -re "Remote.*using $targetname.*$gdb_prompt $" { }
348 -re "$gdb_prompt $" {
349 warning "Unable to connect to $targetname with GDB."
351 return [gdb_comm_reload $dest $prog $args]
353 -re ".*RDI_open.*should reset target.*" {
354 warning "RDI Open Failed"
356 return [gdb_comm_reload $dest $prog $args]
359 warning "Unable to connect to $targetname with GDB."
361 return [gdb_comm_reload $dest $prog $args]
365 if {[target_info exists gdb_init_command]} {
366 remote_send host "[target_info gdb_init_command]\n"
367 remote_expect host 10 {
368 -re ".*$gdb_prompt $" { }
371 return [list "fail" ""]
375 # Now download the executable to the target board. If communications
376 # with the target are very slow the timeout might need to be increased.
377 if {[board_info $dest exists gdb_load_offset]} {
378 remote_send host "load $prog [board_info $dest gdb_load_offset]\n"
380 remote_send host "load\n"
382 remote_expect host 600 {
383 -re "text.*data.*$gdb_prompt $" { }
384 -re "data.*text.*$gdb_prompt $" { }
385 -re "$gdb_prompt $" {
386 warning "Unable to send program to target board."
388 return [gdb_comm_reload $dest $prog $args]
391 warning "Unable to send program to target board."
393 return [gdb_comm_reload $dest $prog $args]
397 # Now set up breakpoints in exit, _exit, and abort. These
398 # are used to determine if a c-torture test passed or failed. More
399 # work would be necessary for things like the g++ testsuite which
400 # use printf to indicate pass/fail status.
402 if { [gdb_comm_add_breakpoint _exit] ne "" } {
403 gdb_comm_add_breakpoint exit
405 gdb_comm_add_breakpoint abort
409 # Now start up the program and look for our magic breakpoints.
410 # And a whole lot of other magic stuff too.
412 if {[board_info $dest exists gdb_run_command]} {
413 remote_send host "[board_info $dest gdb_run_command]\n"
415 remote_send host "run\n"
417 # FIXME: The value 300 below should be a parameter.
418 if {[board_info $dest exists testcase_timeout]} {
419 set testcase_timeout [board_info $dest testcase_timeout]
421 set testcase_timeout 300
423 remote_expect host $testcase_timeout {
424 -re "Line.*Jump anyway.*.y or n.*" {
425 remote_send host "y\n"
428 -re {Continuing( at |\.| with no signal\.)[^\r\n]*[\r\n]} {
431 -re ".*Start it from the beginning?.*y or n.*" {
432 remote_send host "n\n"
433 remote_expect host 10 {
434 -re ".*$gdb_prompt $" {
435 remote_send host "signal 0\n"
436 remote_expect host 10 {
437 -re {signal 0[\r\n]+} { exp_continue }
438 -re {Continuing(\.| with no signal\.)[\r\n]} {}
444 -re {(run[\r\n]*|)Starting program: [^\r\n]*[\r\n]} {
447 -re "$gdb_prompt (signal 0|continue)\[\r\n\]+Continuing(\\.| with no signal\\.)\[\r\n\]" {
450 -re "(.*)Breakpoint.*exit.*=0.*$gdb_prompt $" {
451 append output $expect_out(1,string)
452 set result [check_for_board_status output]
455 return [list "fail" $output]
457 return [list "pass" $output]
459 -re "(.*)Breakpoint.*exit.*=\[1-9\]\[0-9\]*.*$gdb_prompt $" {
460 append output $expect_out(1,string)
461 set result [check_for_board_status output]
463 if { $result == 0 } {
464 return [list "pass" $output]
466 if {[board_info $dest exists exit_statuses_bad]} {
467 return [list "pass" $output]
469 return [list "fail" $output]
471 -re "(.*)Breakpoint.*exit.*$gdb_prompt $" {
472 append output $expect_out(1,string)
473 set status [check_for_board_status output]
476 return [list "fail" $output]
478 return [list "pass" $output]
480 -re "(.*)Breakpoint.*abort.*$gdb_prompt $" {
481 append output $expect_out(1,string)
482 check_for_board_status output
484 return [list "fail" $output]
486 -re "SIGTRAP.*$gdb_prompt $" {
487 return [gdb_comm_reload $dest $prog $args]
489 -re "(.*)Program (received |terminated ).*$gdb_prompt $" {
490 set output $expect_out(1,string)
491 check_for_board_status output
494 return [list "fail" $output]
496 -re "(.*)Program exited with code \[0-9\]+.*$gdb_prompt $" {
497 set output $expect_out(1,string)
498 set status [check_for_board_status output]
501 return [list "fail" $output]
503 return [list "pass" $output]
507 if {[board_info $dest exists unreliable]} {
508 if { [board_info $dest unreliable] > 0 } {
510 set name [board_info $dest name]
511 incr board_info($name,unreliable) -1
512 set result [gdb_comm_reload $dest $prog $args]
513 incr board_info($name,unreliable)
517 return [list "fail" ""]
521 return [list "fail" ""]
524 # If we've tried less than 4 times to load PROG, reboot the target, restart GDB
525 # and try again. Otherwise, return "untested".
526 proc gdb_comm_reload { dest prog aargs } {
529 # how many times have we done this?
530 set n_reloads [board_info $dest n_reloads]
531 if {$n_reloads eq ""} {
537 set name [board_info $dest name]
538 set board_info($dest,n_reloads) [expr {$n_reloads + 1}]
540 # how many times are we allowed to do this?
541 set max [board_info $dest max_reload_reboots]
546 # if we've been doing this too much, something's very
547 # wrong. just give up, to reduce stress on boards.
548 if {$max == $n_reloads} {
549 perror "Too many reboots. Giving up."
551 if {$max <= $n_reloads} {
555 if { $try_again < 4 } {
560 set result [eval remote_load \"$dest\" \"$prog\" $aargs]
565 return [list "untested" ""]
569 set_board_info protocol "gdb_comm"